master
pan 3 years ago
parent 4b99cfdda1
commit c055dacfaf
  1. 88
      mock/test.ts
  2. 54
      src/App.vue
  3. 9
      src/components/ManagerLogin.vue
  4. 93
      src/components/Room.vue
  5. 81
      src/components/UserLogin.vue
  6. 3
      src/global.ts
  7. 6
      src/interface.ts
  8. 15
      src/request.ts
  9. 85
      src/router.ts

@ -1,5 +1,15 @@
import {MockMethod} from 'vite-plugin-mock';
import {changeEmailApi, changePwdApi, checkAdminApi, loginApi, sendCodeApi, telegramBotApi} from "../src/interface";
import {
addRoomApi,
changeEmailApi,
changePwdApi,
checkAdminApi,
getRoomApi,
managerLoginApi,
sendCodeApi,
telegramBotApi,
userLoginApi
} from "../src/interface";
import {JSONResponse} from "../src/request";
@ -108,7 +118,7 @@ export default [
}
},
{
url: loginApi,
url: managerLoginApi,
method: "post",
response: ({body}) => {
const result: JSONResponse = {
@ -156,5 +166,79 @@ export default [
return {message: '查询管理员失败'}
}
}
},
{
url: userLoginApi,
method: "post",
response: ({body}) => {
const result: JSONResponse = {
result: Math.random() < 0.9 ? 'OK' : "FAIL",
}
if (result.result === 'OK') {
return {
...result,
...Mock.mock({
'message': '登陆成功',
'body': {
'token': /[a-zA-Z0-9]{32}/,
'userEmail': body['userEmail']
}
})
}
} else {
return {
...result,
...Mock.mock({
'message': /登陆失败,(邮箱或密码错误)/
})
}
}
}
},
{
url: addRoomApi,
method: "post",
response: ({body}) => {
const result: JSONResponse = {
result: Math.random() < 0.9 ? 'OK' : "FAIL",
}
if (result.result === 'OK') {
return {
...result,
message: '添加成功'
}
} else {
return {
...result,
message: '添加失败'
}
}
}
},
{
url: getRoomApi,
method: "get",
response: ({body}) => {
console.info(111111)
const result: JSONResponse = {
result: Math.random() < 0.9 ? 'OK' : "FAIL",
}
const data = Mock.mock({
"rooms|1-10": [
{
"id|1-100": 100,
user: '@cname',
title: '@ctitle',
"status|1-3": 1,
"email|1": true,
"telegram|1": true
}
]
})
return {
...result,
...data
}
}
}
] as MockMethod[];

@ -1,12 +1,14 @@
<template>
<el-container>
<el-header>
<template v-if="$route.fullPath.startsWith(backend)">
<el-row>
<el-col :span="4">
<h1>bilibili直播通知后台管理</h1>
</el-col>
<el-col :span="20" v-if="![loginPath,registerPath].includes($route.fullPath)">
<el-col :span="20" v-if="[managerLoginPath,managerRegisterPath].includes($route.fullPath)">
<el-menu mode="horizontal" :router="true" :default-active="configPath">
<el-submenu index="1">
<template v-slot:title>推送配置</template>
<el-menu-item :index="configPath">当前配置</el-menu-item>
@ -17,12 +19,29 @@
<template v-slot:title>个人信息</template>
<el-menu-item :index="managerPasswordPath">修改密码</el-menu-item>
<el-menu-item :index="managerEmailPath">修改邮箱</el-menu-item>
<el-menu-item @click="logout">退出登录</el-menu-item>
<el-menu-item @click="managerLogout">退出登录</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</template>
<template v-else-if="$route.fullPath.startsWith(frontend)">
<el-row>
<el-col :span="4">
<h1>bilibili直播通知</h1>
</el-col>
<el-col :span="20" v-if="$route.fullPath!==userLoginPath">
<el-menu mode="horizontal">
<el-submenu index="1">
<template v-slot:title>个人信息</template>
<el-menu-item @click="userLogout">退出登录</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</template>
</el-header>
<el-main>
<router-view/>
</el-main>
@ -31,13 +50,24 @@
</template>
<script lang="ts">
import {defineComponent} from 'vue'
import {computed, defineComponent} from 'vue'
import Config from "./components/Config.vue";
import {useStore} from "vuex";
import {configPath, loginPath, managerEmailPath, managerPasswordPath, registerPath, telegramPath} from "./router";
import {
backend,
configPath,
frontend,
managerEmailPath,
managerLoginPath,
managerPasswordPath,
managerRegisterPath,
telegramPath,
userLoginPath
} from "./router";
//@ts-ignore
import crumbs from 'crumbsjs';
import {useRouter} from "vue-router";
import {manager_token_key} from "./global";
export default defineComponent({
name: 'App',
@ -46,14 +76,22 @@ export default defineComponent({
const store = useStore()
const router = useRouter()
const logout = () => {
const managerLogout = () => {
crumbs.deleteAll()
router.replace(managerLoginPath)
}
const userLogout = () => {
crumbs.deleteAll()
router.replace(loginPath)
router.replace(userLoginPath)
}
const isLogin = computed<boolean>(() => crumbs.get(manager_token_key) !== null)
return {
store, loginPath, registerPath, logout, configPath, telegramPath
, managerEmailPath, managerPasswordPath
store, managerLoginPath, managerRegisterPath, managerLogout, configPath, telegramPath
, managerEmailPath, managerPasswordPath, backend, frontend, userLoginPath, userLogout
}
}
})

@ -26,12 +26,13 @@ import {JSONResponse, login, message} from "../request";
//@ts-ignore
import crumbs from 'crumbsjs';
import {useRouter} from "vue-router";
import {email_cookie_key, token_cookie_key} from "../global";
import {email_cookie_key, manager_token_key} from "../global";
import User from "./User.vue";
import {configPath} from "../router";
import {managerLoginApi} from "../interface";
export default defineComponent({
name: "Login",
name: "ManagerLogin",
components: {User},
setup() {
const user = ref<string>('')
@ -46,11 +47,11 @@ export default defineComponent({
const router = useRouter()
const requestLogin = () => {
login(user.value, password.value).then(res => res.json())
login(managerLoginApi, user.value, password.value).then(res => res.json())
.then((res: JSONResponse) => {
message(res)
if (res.result === 'OK') {
crumbs.set(token_cookie_key, res.body.token)
crumbs.set(manager_token_key, res.body.token)
crumbs.set(email_cookie_key, res.body.userEmail)
router.replace(configPath)
}

@ -0,0 +1,93 @@
<template>
<el-row type="flex" justify="center">
<el-col :span="6">
<el-input placeholder="直播间号" v-model="roomId">
<template v-slot:prepend>请输入直播间号</template>
<template v-slot:append>
<el-button @click="add" :disabled="roomId===''">添加</el-button>
</template>
</el-input>
</el-col>
</el-row>
<el-row type="flex" justify="center">
<el-col :span="12">
<el-table :data="tableData">
<el-table-column prop="id" label="直播间号"/>
<el-table-column prop="user" label="直播用户"/>
<el-table-column prop="title" label="直播标题"/>
<el-table-column label="状态">
<template v-slot="scope">
{{ parseStatus(scope.row.status) }}
</template>
</el-table-column>
<el-table-column label="推送配置">
<template v-slot="scope">
<el-checkbox v-model="scope.row._email">邮箱</el-checkbox>
<el-checkbox v-model="scope.row._telegram">telegram</el-checkbox>
</template>
</el-table-column>
<el-table-column label="操作">
<template v-slot="scope">
<el-popconfirm title="确认删除此直播间号?">
<template v-slot:reference>
<el-button icon="el-icon-delete">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</template>
<script lang="ts">
import {defineComponent, ref} from "vue";
import {addRoom, JSONResponse, loadRoom, message} from "../request";
export default defineComponent({
name: "Room",
setup() {
const tableData = ref<Array>()
const roomId = ref('')
const add = () => {
addRoom(roomId).then(res => res.json())
.then((res: JSONResponse) => {
message(res)
if (res.result === "OK") {
load()
}
})
}
const load = () => loadRoom().then(res => res.json())
.then((res: JSONResponse) => {
res.rooms.forEach(value => {
value._email = ref(value.email)
value._telegram = ref(value.telegram)
})
tableData.value = res.rooms
})
load()
const parseStatus = (status: number) => {
switch (status) {
case 1:
return "直播"
case 2:
return "轮播"
case 3:
return "离线"
}
}
return {tableData, roomId, add, parseStatus}
}
})
</script>
<style scoped>
</style>

@ -0,0 +1,81 @@
<template>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="登录" name="login">
<el-input placeholder="请输入用户名" v-model="user">
<template v-slot:prepend>用户名</template>
</el-input>
<el-input placeholder="请输入密码" v-model="password" show-password>
<template v-slot:prepend>密码</template>
</el-input>
</el-tab-pane>
<el-tab-pane label="注册" name="register">
<el-input placeholder="请输入用户名" v-model="user">
<template v-slot:prepend>用户名</template>
</el-input>
<el-input placeholder="请输入密码" v-model="password" show-password>
<template v-slot:prepend>密码</template>
</el-input>
<el-input placeholder="请确认密码" v-model="confirmPwd" show-password>
<template v-slot:prepend>确认密码</template>
</el-input>
<span v-if="password!==''&&confirmPwd!==''&&password!==confirmPwd">密码不一致</span>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<el-button type="primary" v-if="activeName==='login'"
:disabled="user===''||password===''" @click="requestLogin">登录
</el-button>
<el-button type="success" v-else :disabled="user===''||password===''||confirmPwd===''||password!==confirmPwd">注册
</el-button>
</el-col>
</el-row>
</template>
<script lang="ts">
import {defineComponent, ref} from "vue"
import {JSONResponse, login, message} from "../request";
import {email_cookie_key, user_token_key} from "../global";
import {router, userMainPath} from "../router";
import {userLoginApi} from "../interface";
//@ts-ignore
import crumbs from 'crumbsjs';
export default defineComponent({
name: "UserLogin",
setup() {
const activeName = ref('login')
const handleClick = (tab, event) => {
user.value = ''
password.value = ''
confirmPwd.value = ''
}
const user = ref('')
const password = ref('')
const confirmPwd = ref('')
const requestLogin = () => {
login(userLoginApi, user.value, password.value).then(res => res.json())
.then((res: JSONResponse) => {
message(res)
if (res.result === 'OK') {
crumbs.set(user_token_key, res.body.token)
crumbs.set(email_cookie_key, res.body.userEmail)
router.replace(userMainPath)
}
})
}
return {activeName, handleClick, user, password, confirmPwd, requestLogin}
}
})
</script>
<style scoped>
</style>

@ -1,2 +1,3 @@
export const token_cookie_key = 'token'
export const manager_token_key = 'manager_token'
export const user_token_key = "user_token"
export const email_cookie_key = 'user_email'

@ -5,4 +5,8 @@ export const changePwdApi = `${prefix}/change/pwd`
export const telegramBotApi = `${prefix}/telegram/bot`
export const testTelegramBotApi = (token: string) => `https://api.telegram.org/bot${token}/getMe`
export const checkAdminApi = `${prefix}/checkAdmin`
export const loginApi = `${prefix}/login`
export const managerLoginApi = `${prefix}/login`
const frontend = '/api/frontend'
export const userLoginApi = `${frontend}/login`
export const addRoomApi = `${frontend}/room`
export const getRoomApi = `${frontend}/load/room`

@ -1,8 +1,9 @@
import {
addRoomApi,
changeEmailApi,
changePwdApi,
checkAdminApi,
loginApi,
getRoomApi,
sendCodeApi,
telegramBotApi,
testTelegramBotApi
@ -89,8 +90,16 @@ export function checkAdmin() {
return fetch(new Request(checkAdminApi), {method: 'GET'})
}
export function login(userEmail: string, password: string) {
return fetch(new Request(loginApi), {method: 'POST', body: JSON.stringify({userEmail, password})})
export function login(api: string, userEmail: string, password: string) {
return fetch(new Request(api), {method: 'POST', body: JSON.stringify({userEmail, password})})
}
export function addRoom(roomId: string) {
return fetch(new Request(addRoomApi), {method: 'POST', body: JSON.stringify({roomId})})
}
export function loadRoom() {
return fetch(new Request(getRoomApi), {method: 'GET'})
}
export type Result = 'OK' | 'FAIL'

@ -5,29 +5,40 @@ import {useStore} from "vuex";
import {onMounted} from "vue";
import Password from "./components/Password.vue";
import TelegramBot from "./components/TelegramBot.vue";
import Login from "./components/Login.vue";
import ManagerLogin from "./components/ManagerLogin.vue";
import Register from "./components/Register.vue";
import {checkAdmin, JSONResponse} from "./request";
import UserLogin from "./components/UserLogin.vue"
// @ts-ignore
import crumbs from 'crumbsjs';
import {token_cookie_key} from "./global";
import {manager_token_key, user_token_key} from "./global";
import Room from "./components/Room.vue";
const backend = '/backend'
export const registerPath = `${backend}/register`
export const loginPath = `${backend}/login`
export const backend = '/backend'
export const managerRegisterPath = `${backend}/register`
export const managerLoginPath = `${backend}/login`
export const configPath = `${backend}/config`
export const telegramPath = `${configPath}/telegram`
export const managerEmailPath = `${backend}/email`
export const managerPasswordPath = `${backend}/password`
export const frontend = '/frontend'
export const userLoginPath = `${frontend}/login`
export const userMainPath = `${frontend}/main`
const routes = [
{path: '/', redirect: userLoginPath},
{path: backend, redirect: configPath},
{path: registerPath, component: Register},
{path: configPath, component: Config},
{path: telegramPath, component: TelegramBot},
{path: managerEmailPath, component: Email},
{path: managerPasswordPath, component: Password},
{path: loginPath, component: Login}
{path: managerLoginPath, component: ManagerLogin},
{path: managerRegisterPath, component: Register},
{path: configPath, component: Config},
{path: telegramPath, component: TelegramBot},
{path: userLoginPath, component: UserLogin},
{path: userMainPath, component: Room}
]
@ -37,31 +48,57 @@ export const router = createRouter({
})
//路由导航守卫
router.beforeEach(async (to, from) => {
if (crumbs.get(token_cookie_key)) {
if ([registerPath, loginPath].includes(to.fullPath)) {
console.info('存在cookie,访问的路由是登录或注册,重定向到主页')
return '/'
const fullPath = to.fullPath
if (fullPath.startsWith(backend)) {
const token_key = manager_token_key
const registerPath = managerRegisterPath
const loginPath = managerLoginPath
if (crumbs.get(token_key)) {
if ([registerPath, loginPath].includes(fullPath)) {
console.info('存在cookie,访问的路由是登录或注册,重定向到主页')
return '/'
} else {
console.info('放通路由')
return true
}
} else {
console.info('放通路由')
return true
let res: JSONResponse = await checkAdmin().then(res => res.json())
if (res.body) {
if (fullPath === loginPath) {
console.info('放通路由')
return true
} else {
console.info('存在管理员,访问的不是登录路由,重定向到登录')
return loginPath
}
} else {
if (fullPath === registerPath) {
console.info('放通路由')
return true
} else {
console.info('不存在管理员,访问的不是注册路由,重定向到注册')
return registerPath
}
}
}
} else {
let res: JSONResponse = await checkAdmin().then(res => res.json())
if (res.body) {
if (to.fullPath === loginPath) {
const token_key = user_token_key
const fullPath = to.fullPath
if (crumbs.get(token_key)) {
if (fullPath == userLoginPath) {
console.info('存在cookie,访问的路由是登录或注册,重定向到主页')
return '/'
} else {
console.info('放通路由')
return true
} else {
console.info('存在管理员,访问的不是登录路由,重定向到登录')
return loginPath
}
} else {
if (to.fullPath === registerPath) {
if (fullPath === userLoginPath) {
console.info('放通路由')
return true
} else {
console.info('不存在管理员,访问的不是注册路由,重定向到注册')
return registerPath
console.info('访问的不是登录路由,重定向到登录')
return userLoginPath
}
}
}

Loading…
Cancel
Save