master
pan 3 years ago
commit 14223e89c5
  1. 8
      .gitignore
  2. 12
      Dockerfile
  3. 13
      index.html
  4. 29
      mock/test.ts
  5. 30
      package.json
  6. BIN
      public/favicon.ico
  7. 51
      src/App.vue
  8. BIN
      src/assets/logo.png
  9. 11
      src/assets/scss/style.scss
  10. 28
      src/components/AsyncComponent.vue
  11. 110
      src/components/Email.vue
  12. 13
      src/components/Home.vue
  13. 49
      src/components/Vue3.vue
  14. 1
      src/interface.ts
  15. 11
      src/main.ts
  16. 13
      src/request.ts
  17. 22
      src/router.ts
  18. 16
      src/store.ts
  19. 14
      tsconfig.json
  20. 9
      vite.config.ts
  21. 9
      vue.app.conf

8
.gitignore vendored

@ -0,0 +1,8 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
/yarn.lock
*.log
.idea

@ -0,0 +1,12 @@
FROM nginx:alpine
ADD vue.app.conf /etc/nginx/conf.d/
ADD dist /app
RUN mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.bak \
&& dos2unix /etc/nginx/conf.d/vue.app.conf
EXPOSE 9000
ENTRYPOINT ["nginx","-g","daemon off;"]

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

@ -0,0 +1,29 @@
import {MockMethod} from 'vite-plugin-mock';
import {sendCodeApi} from "../src/interface";
const Mock = require('mockjs')
export default [
{
url: sendCodeApi,
method: 'post',
response: ({ query }) => {
return Mock.mock({
'result':'OK',
'message':'验证码发送成功'
})
},
},
{
url: '/api/post',
method: 'post',
timeout: 2000,
response: {
code: 0,
data: {
name: 'vben',
},
},
},
] as MockMethod[];

@ -0,0 +1,30 @@
{
"name": "bililive_webapp",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vuedx-typecheck . && vite build",
"serve": "vite preview"
},
"dependencies": {
"element3": "^0.0.39",
"mockjs": "^1.1.0",
"vue": "^3.0.5",
"vue-router": "4",
"vuex": "^4.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.1.4",
"@vue/compiler-sfc": "^3.0.5",
"@vuedx/typecheck": "^0.6.0",
"@vuedx/typescript-plugin-vue": "^0.6.0",
"cross-env": "^7.0.3",
"node-sass": "^5.0.0",
"sass": "^1.32.7",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"typescript": "^4.1.3",
"vite": "^2.0.0-beta.64",
"vite-plugin-mock": "^2.1.4"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,51 @@
<template>
<el-container>
<el-header>
<el-row>
<el-col :span="4">
<h1>直播间状态通知</h1>
</el-col>
<el-col :span="20">
<el-menu mode="horizontal" :default-active="activeIndex">
<el-menu-item index="1"><router-link to="/">主页</router-link></el-menu-item>
<el-submenu index="2">
<template v-slot:title>个人信息</template>
<el-menu-item index="2-1">修改密码</el-menu-item>
<el-menu-item index="2-2"><router-link to="/email">修改邮箱</router-link></el-menu-item>
<el-menu-item index="2-3"><router-link to="">退出登录</router-link></el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</template>
<script lang="ts">
import {defineComponent, ref} from 'vue'
export default defineComponent({
name: 'App',
setup(){
const activeIndex=ref<string>('1')
return {activeIndex}
}
})
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

@ -0,0 +1,11 @@
.mt{
&-1{
margin-top: 1rem;
}
}
.btn-block{
display: block;
width: 100%;
}

@ -0,0 +1,28 @@
<template>
<h1>一个异步组件</h1>
</template>
<script lang="ts">
import {defineComponent} from 'vue'
function sleep(timeout: number | undefined){
return new Promise(resolve => setTimeout(resolve,timeout))
}
export default defineComponent({
name: "AsyncComponent",
props:{
timeout:{
type:Number,
required:true
}
},
async setup(props){
await sleep(props.timeout)
}
})
</script>
<style scoped>
</style>

@ -0,0 +1,110 @@
<template>
<el-row type="flex" justify="center">
<el-col :span="8">
<el-input v-model="userEmail" :disabled="true">
<template v-slot:prepend>当前邮箱</template>
</el-input>
</el-col>
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<el-input v-model="newEmail" :disabled="second>0">
<template v-slot:prepend>新邮箱</template>
</el-input>
</el-col>
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="6">
<el-input v-model="code">
<template v-slot:prepend>验证码</template>
</el-input>
</el-col>
<el-col :span="2">
<el-button type="primary" :disabled="!allowSendCode" @click="sendCode">{{ sendCodeTip }}</el-button>
</el-col>
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="2">
<el-button type="primary" class="btn-block" :disabled="!checkCode">更换邮箱</el-button>
</el-col>
<el-col :span="2"/>
<el-col :span="2">
<el-button type="info" class="btn-block">返回</el-button>
</el-col>
</el-row>
</template>
<script lang="ts">
import {computed, defineComponent, ref} from "vue";
import {changeEmail as _changeEmail, sendCode as _sendCode} from "../request";
import {useStore} from "vuex";
import {Message} from 'element3/src/components/Message'
export default defineComponent<{ userEmail: { require: boolean, type: StringConstructor }, second: { require: boolean, type: NumberConstructor } }>({
name: 'Email',
setup(props) {
const newEmail = ref<string>('')
const code = ref<string>('')
const second = ref<number>(0)
const store=useStore()
const sendCode = () => {
second.value=10
_sendCode(store.state.user.email).then(res=>res.json()).then(res=>{
if(res.result==='OK'){
console.info('发送验证码成功')
new Message({
showClose: true,
message: '发送验证码成功',
type: 'success'
})
const t=setInterval(function (){
if(second.value===0){
clearInterval(t)
}else {
second.value--
}
},1000)
}else{
second.value=0
new Message({
showClose: true,
message: '发送验证码失败',
type: 'error'
})
}
})
}
const changeEmail=()=> _changeEmail(store.state.user.email,newEmail.value,code.value)
const allowSendCode = computed<boolean>(() => second.value === 0 && props.userEmail !== newEmail.value && /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(newEmail.value))
const sendCodeTip = computed<string>(() => second.value > 0 ? second.value + '秒后重发' : '发送验证码')
const checkCode = computed<boolean>(() => /^\d{6}$/.test(code.value))
const userEmail= computed(() => store.state.user.email)
return {
newEmail,
code,
allowSendCode,
sendCodeTip,
checkCode,
second,
sendCode,
userEmail,
changeEmail
}
}
})
</script>
<style scoped>
</style>

@ -0,0 +1,13 @@
<template>
<h1>主页</h1>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>

@ -0,0 +1,49 @@
<template>
<h1>{{num}}*2={{double}}</h1>
<h1>{{num2.count}}*3={{triple}}</h1>
<button @click="add">累加</button>
<button @click="insert">插入</button>
</template>
<script lang="ts">
import {computed, defineComponent, reactive, ref} from 'vue'
export default defineComponent({
name: "Vue3",
setup:()=>{
const num=ref<number>(1)
const isAdd=ref<boolean>(false)
const num2=reactive<{count:number}>({
count:1
})
function add() {
num.value++
num2.count++
}
function insert(){
isAdd.value=true
}
function cancel(){
isAdd.value=false
}
const double=computed<number>(()=>num.value*2)
const triple=computed<number>(()=>num2.count*3)
return {num,add,double,num2,triple,isAdd,insert,cancel}
}
})
</script>
<style scoped>
</style>

@ -0,0 +1 @@
export const sendCodeApi='/api/change/email'

@ -0,0 +1,11 @@
import {createApp} from 'vue'
// TypeScript error? Run VSCode command
// TypeScript: Select TypeScript version - > Use Workspace Version
import App from './App.vue'
import Element3 from 'element3'
import 'element3/lib/theme-chalk/index.css'
import './assets/scss/style.scss'
import {store} from "./store";
import {router} from "./router";
createApp(App).use(router).use(store).use(Element3).mount('#app')

@ -0,0 +1,13 @@
import {sendCodeApi} from "./interface";
/**
*
* @param userEmail
*/
export function sendCode(userEmail:string){
return fetch(new Request(sendCodeApi,{method:'POST',body:JSON.stringify({userEmail})}))
}
export function changeEmail(oldEmail:string,newEmail:string,code:string){
}

@ -0,0 +1,22 @@
// 1. 定义路由组件.
// 也可以从其他文件导入
import {createRouter, createWebHashHistory} from "vue-router";
import Email from "./components/Email.vue";
import Home from "./components/Home.vue";
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{path:'/',component: Home},
{ path: '/email', component: Email },
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
export const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})

@ -0,0 +1,16 @@
import {createStore} from "vuex";
export const store = createStore({
state: () => ({
user: {
email: '1029559041@qq.com'
}
}),
mutations: {
setUser(state, user) {
// @ts-ignore
state.user = user
}
}
})

@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"],
"plugins": [{ "name": "@vuedx/typescript-plugin-vue" }]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

@ -0,0 +1,9 @@
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {viteMockServe} from "vite-plugin-mock";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(),viteMockServe({})]
})

@ -0,0 +1,9 @@
server {
listen 9000;
location / {
root /app;
index index.html;
try_files $uri $uri/ /index.html last;
}
}
Loading…
Cancel
Save