mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-08 02:03:42 +08:00
refactor: refactor controller handler module and admin module
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon">
|
||||
<title>ChatGPT-Plus</title>
|
||||
</head>
|
||||
|
||||
|
||||
BIN
web/src/assets/img/admin-login-bg.jpg
Normal file
BIN
web/src/assets/img/admin-login-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
@@ -7,47 +7,20 @@ import ChatPlus from "@/views/ChatPlus.vue";
|
||||
import NotFound from './views/404.vue'
|
||||
import TestPage from './views/Test.vue'
|
||||
import Home from "@/views/Home.vue";
|
||||
import Admin from "@/views/Admin.vue";
|
||||
import Admin from "@/views/admin/Admin.vue";
|
||||
import Login from "@/views/Login.vue"
|
||||
import Register from "@/views/Register.vue";
|
||||
import AdminLogin from "@/views/admin/Login.vue"
|
||||
|
||||
const routes = [
|
||||
{
|
||||
name: 'home', path: '/', component: Home, meta: {
|
||||
title: 'ChatGPT-Plus'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'login', path: '/login', component: Login, meta: {
|
||||
title: '用户登录'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'register', path: '/register', component: Register, meta: {
|
||||
title: '用户注册'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'plus', path: '/chat', component: ChatPlus, meta: {
|
||||
title: 'ChatGPT-智能助手V3'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'admin', path: '/admin', component: Admin, meta: {
|
||||
title: 'Chat-Plus 控制台'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'test', path: '/test', component: TestPage, meta: {
|
||||
title: '测试页面'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'NotFound', path: '/:all(.*)', component: NotFound, meta: {
|
||||
title: '页面没有找到'
|
||||
}
|
||||
},
|
||||
{name: 'home', path: '/', component: Home, meta: {title: 'ChatGPT-Plus'}},
|
||||
{name: 'login', path: '/login', component: Login, meta: {title: '用户登录'}},
|
||||
{name: 'register', path: '/register', component: Register, meta: {title: '用户注册'}},
|
||||
{name: 'plus', path: '/chat', component: ChatPlus, meta: {title: 'ChatGPT-智能助手V3'}},
|
||||
{name: 'admin', path: '/admin', component: Admin, meta: {title: 'Chat-Plus 控制台'}},
|
||||
{name: 'admin/login', path: '/admin/login', component: AdminLogin, meta: {title: 'Chat-Plus 控制台登录'}},
|
||||
{name: 'test', path: '/test', component: TestPage, meta: {title: '测试页面'}},
|
||||
{name: 'NotFound', path: '/:all(.*)', component: NotFound, meta: {title: '页面没有找到'}},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
/* eslint-disable no-constant-condition */
|
||||
import {dateFormat, removeArrayItem} from "@/utils/libs";
|
||||
import Storage from 'good-storage'
|
||||
|
||||
/**
|
||||
* storage handler
|
||||
*/
|
||||
|
||||
const SessionUserKey = 'LOGIN_USER';
|
||||
const ChatHistoryKey = 'CHAT_HISTORY';
|
||||
const ChatListKey = 'CHAT_LIST';
|
||||
const SessionAdminKey = 'LOGIN_ADMIN';
|
||||
|
||||
export function getSessionId() {
|
||||
const user = getLoginUser();
|
||||
return user ? user['session_id'] : '';
|
||||
}
|
||||
|
||||
export function getLoginAdmin() {
|
||||
const value = sessionStorage.getItem(SessionAdminKey);
|
||||
if (value) {
|
||||
return JSON.parse(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getLoginUser() {
|
||||
const value = sessionStorage.getItem(SessionUserKey);
|
||||
if (value) {
|
||||
@@ -28,73 +34,6 @@ export function setLoginUser(user) {
|
||||
sessionStorage.setItem(SessionUserKey, JSON.stringify(user))
|
||||
}
|
||||
|
||||
export function getUserInfo() {
|
||||
const data = getLoginUser();
|
||||
if (data !== null) {
|
||||
const user = data["user"];
|
||||
user['active_time'] = dateFormat(user['active_time']);
|
||||
user['expired_time'] = dateFormat(user['expired_time']);
|
||||
return user;
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
// 追加历史记录
|
||||
export function appendChatHistory(chatId, message) {
|
||||
let history = Storage.get(ChatHistoryKey);
|
||||
if (!history) {
|
||||
history = {};
|
||||
}
|
||||
if (!history[chatId]) {
|
||||
history[chatId] = [message];
|
||||
} else {
|
||||
history[chatId].push(message);
|
||||
}
|
||||
Storage.set(ChatHistoryKey, history);
|
||||
}
|
||||
|
||||
export function clearChatHistory() {
|
||||
Storage.remove(ChatHistoryKey);
|
||||
Storage.remove(ChatListKey);
|
||||
}
|
||||
|
||||
// 获取指定会话的历史记录
|
||||
export function getChatHistory(chatId) {
|
||||
const history = Storage.get(ChatHistoryKey);
|
||||
if (!history) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return history[chatId] ? history[chatId] : null;
|
||||
}
|
||||
|
||||
export function getChatList() {
|
||||
const list = Storage.get(ChatListKey);
|
||||
if (list) {
|
||||
if (typeof list.reverse !== 'function') {
|
||||
Storage.remove(ChatListKey)
|
||||
return null;
|
||||
}
|
||||
return list.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
export function setChat(chat) {
|
||||
let chatList = Storage.get(ChatListKey);
|
||||
if (!chatList) {
|
||||
chatList = [];
|
||||
}
|
||||
|
||||
chatList.push(chat);
|
||||
Storage.set(ChatListKey, chatList);
|
||||
}
|
||||
|
||||
export function removeChat(chat) {
|
||||
let chatList = Storage.get(ChatListKey);
|
||||
if (chatList) {
|
||||
chatList = removeArrayItem(chatList, chat, function (v1, v2) {
|
||||
return v1.id === v2.id
|
||||
})
|
||||
Storage.set(ChatListKey, chatList);
|
||||
}
|
||||
export function setLoginAdmin(admin) {
|
||||
sessionStorage.setItem(SessionAdminKey, JSON.stringify(admin))
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="main">
|
||||
<div class="contain">
|
||||
<div class="logo">
|
||||
<el-image src="images/logo.png" fit="cover" />
|
||||
<el-image src="images/logo.png" fit="cover"/>
|
||||
</div>
|
||||
|
||||
<div class="header">{{ title }}</div>
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<footer-bar />
|
||||
<footer-bar/>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,13 +140,14 @@ const validateMobile = function (mobile) {
|
||||
width 90%
|
||||
max-width 400px
|
||||
transform translate(-50%, -50%)
|
||||
padding 20px;
|
||||
padding 20px 40px;
|
||||
color #ffffff
|
||||
border-radius 10px;
|
||||
background rgba(255, 255, 255, 0.3)
|
||||
|
||||
.logo {
|
||||
text-align center
|
||||
|
||||
.el-image {
|
||||
width 120px;
|
||||
}
|
||||
|
||||
175
web/src/views/admin/Login.vue
Normal file
175
web/src/views/admin/Login.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="bg"></div>
|
||||
<div class="main">
|
||||
<div class="contain">
|
||||
<div class="logo">
|
||||
<el-image src="../images/logo.png" fit="cover"/>
|
||||
</div>
|
||||
<div class="header">{{ title }}</div>
|
||||
<div class="content">
|
||||
<div class="block">
|
||||
<el-input placeholder="请输入用户名" size="large" v-model="username" autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<UserFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
<el-input placeholder="请输入密码" size="large" v-model="password" show-password autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<Lock/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-row class="btn-row">
|
||||
<el-button class="login-btn" size="large" type="primary" @click="login">登录</el-button>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<footer-bar/>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {onMounted, ref} from "vue";
|
||||
import {Lock, UserFilled} from "@element-plus/icons-vue";
|
||||
import {httpPost} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {setLoginUser} from "@/utils/storage";
|
||||
import {useRouter} from "vue-router";
|
||||
import FooterBar from "@/components/FooterBar.vue";
|
||||
|
||||
const router = useRouter();
|
||||
const title = ref('ChatGPT-PLUS 控制台登录');
|
||||
const username = ref(process.env.VUE_APP_ADMIN_USER);
|
||||
const password = ref(process.env.VUE_APP_ADMIN_PASS);
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keyup', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
login();
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const login = function () {
|
||||
if (username.value === '') {
|
||||
return ElMessage.error('请输入用户名');
|
||||
}
|
||||
if (password.value.trim() === '') {
|
||||
return ElMessage.error('请输入密码');
|
||||
}
|
||||
|
||||
httpPost('/api/admin/login', {username: username.value.trim(), password: password.value.trim()}).then((res) => {
|
||||
setLoginUser(res.data)
|
||||
router.push("admin")
|
||||
}).catch((e) => {
|
||||
ElMessage.error('登录失败,' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.bg {
|
||||
position fixed
|
||||
left 0
|
||||
right 0
|
||||
top 0
|
||||
bottom 0
|
||||
background-color #313237
|
||||
background-image url("~@/assets/img/admin-login-bg.jpg")
|
||||
background-size cover
|
||||
background-position center
|
||||
background-repeat no-repeat
|
||||
filter: blur(10px); /* 调整模糊程度,可以根据需要修改值 */
|
||||
}
|
||||
|
||||
.main {
|
||||
.contain {
|
||||
position fixed
|
||||
left 50%
|
||||
top 40%
|
||||
width 90%
|
||||
max-width 400px;
|
||||
transform translate(-50%, -50%)
|
||||
padding 20px 40px;
|
||||
color #ffffff
|
||||
border-radius 10px;
|
||||
background rgba(255, 255, 255, 0.3)
|
||||
|
||||
.logo {
|
||||
text-align center
|
||||
|
||||
.el-image {
|
||||
width 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
width 100%
|
||||
margin-bottom 24px
|
||||
font-size 24px
|
||||
color $white_v1
|
||||
letter-space 2px
|
||||
text-align center
|
||||
}
|
||||
|
||||
.content {
|
||||
width 100%
|
||||
height: auto
|
||||
border-radius 3px
|
||||
|
||||
.block {
|
||||
margin-bottom 16px
|
||||
|
||||
.el-input__inner {
|
||||
border 1px solid $gray-v6 !important
|
||||
|
||||
.el-icon-user, .el-icon-lock {
|
||||
font-size 20px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-row {
|
||||
padding-top 10px;
|
||||
|
||||
.login-btn {
|
||||
width 100%
|
||||
font-size 16px
|
||||
letter-spacing 2px
|
||||
}
|
||||
}
|
||||
|
||||
.text-line {
|
||||
justify-content center
|
||||
padding-top 10px;
|
||||
font-size 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
color #ffffff;
|
||||
|
||||
.container {
|
||||
padding 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user