Merge pull request #616 from Ander-pixe/webui-new

fix:路由守卫
This commit is contained in:
手瓜一十雪
2024-12-12 09:33:23 +08:00
committed by GitHub
14 changed files with 59 additions and 34 deletions

View File

@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"event-source-polyfill": "^1.0.31", "event-source-polyfill": "^1.0.31",
"mitt": "^3.0.1",
"qrcode": "^1.5.4", "qrcode": "^1.5.4",
"tdesign-icons-vue-next": "^0.3.3", "tdesign-icons-vue-next": "^0.3.3",
"tdesign-vue-next": "^1.10.3", "tdesign-vue-next": "^1.10.3",

View File

@@ -1,7 +1,7 @@
export class githubApiManager { export class githubApiManager {
public async GetBaseData(): Promise<Response | null> { public async GetBaseData(): Promise<Response | null> {
try { try {
const ConfigResponse= await fetch('https://api.github.com/repos/NapNeko/NapCatQQ', { const ConfigResponse = await fetch('https://api.github.com/repos/NapNeko/NapCatQQ', {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@@ -1,3 +1,5 @@
import { request } from '@/utils/request.js';
import { EventSourcePolyfill } from 'event-source-polyfill'; import { EventSourcePolyfill } from 'event-source-polyfill';
type LogListItem = string; type LogListItem = string;
type LogListData = LogListItem[]; type LogListData = LogListItem[];
@@ -13,7 +15,7 @@ export class LogManager {
} }
public async GetLogList(): Promise<LogListData> { public async GetLogList(): Promise<LogListData> {
try { try {
const ConfigResponse = await fetch(`${this.apiPrefix}/Log/GetLogList`, { const ConfigResponse = await request(`${this.apiPrefix}/Log/GetLogList`, {
method: 'GET', method: 'GET',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -33,7 +35,7 @@ export class LogManager {
} }
public async GetLog(FileName: string): Promise<string> { public async GetLog(FileName: string): Promise<string> {
try { try {
const ConfigResponse = await fetch(`${this.apiPrefix}/Log/GetLog?id=${FileName}`, { const ConfigResponse = await request(`${this.apiPrefix}/Log/GetLog?id=${FileName}`, {
method: 'GET', method: 'GET',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,

View File

@@ -1,3 +1,4 @@
import { request } from '@/utils/request.js';
import { OneBotConfig } from '../../../src/onebot/config/config'; import { OneBotConfig } from '../../../src/onebot/config/config';
export class QQLoginManager { export class QQLoginManager {
@@ -13,7 +14,7 @@ export class QQLoginManager {
// TODO: // TODO:
public async GetOB11Config(): Promise<OneBotConfig> { public async GetOB11Config(): Promise<OneBotConfig> {
try { try {
const ConfigResponse = await fetch(`${this.apiPrefix}/OB11Config/GetConfig`, { const ConfigResponse = await request(`${this.apiPrefix}/OB11Config/GetConfig`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -34,7 +35,7 @@ export class QQLoginManager {
public async SetOB11Config(config: OneBotConfig): Promise<boolean> { public async SetOB11Config(config: OneBotConfig): Promise<boolean> {
try { try {
const ConfigResponse = await fetch(`${this.apiPrefix}/OB11Config/SetConfig`, { const ConfigResponse = await request(`${this.apiPrefix}/OB11Config/SetConfig`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -56,7 +57,7 @@ export class QQLoginManager {
public async checkQQLoginStatus(): Promise<boolean> { public async checkQQLoginStatus(): Promise<boolean> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, { const QQLoginResponse = await request(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -76,7 +77,7 @@ export class QQLoginManager {
} }
public async checkQQLoginStatusWithQrcode(): Promise<{ qrcodeurl: string; isLogin: string } | undefined> { public async checkQQLoginStatusWithQrcode(): Promise<{ qrcodeurl: string; isLogin: string } | undefined> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, { const QQLoginResponse = await request(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -97,7 +98,7 @@ export class QQLoginManager {
public async checkWebUiLogined(): Promise<boolean> { public async checkWebUiLogined(): Promise<boolean> {
try { try {
const LoginResponse = await fetch(`${this.apiPrefix}/auth/check`, { const LoginResponse = await request(`${this.apiPrefix}/auth/check`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -118,7 +119,7 @@ export class QQLoginManager {
public async loginWithToken(token: string): Promise<string | null> { public async loginWithToken(token: string): Promise<string | null> {
try { try {
const loginResponse = await fetch(`${this.apiPrefix}/auth/login`, { const loginResponse = await request(`${this.apiPrefix}/auth/login`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -139,7 +140,7 @@ export class QQLoginManager {
public async getQQLoginQrcode(): Promise<string> { public async getQQLoginQrcode(): Promise<string> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/GetQQLoginQrcode`, { const QQLoginResponse = await request(`${this.apiPrefix}/QQLogin/GetQQLoginQrcode`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -160,7 +161,7 @@ export class QQLoginManager {
public async getQQQuickLoginList(): Promise<string[]> { public async getQQQuickLoginList(): Promise<string[]> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/GetQuickLoginList`, { const QQLoginResponse = await request(`${this.apiPrefix}/QQLogin/GetQuickLoginList`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,
@@ -181,7 +182,7 @@ export class QQLoginManager {
public async setQuickLogin(uin: string): Promise<{ result: boolean; errMsg: string }> { public async setQuickLogin(uin: string): Promise<{ result: boolean; errMsg: string }> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/SetQuickLogin`, { const QQLoginResponse = await request(`${this.apiPrefix}/QQLogin/SetQuickLogin`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: 'Bearer ' + this.retCredential, Authorization: 'Bearer ' + this.retCredential,

View File

@@ -33,7 +33,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, defineProps, onMounted, watch } from 'vue'; import { ref, onMounted, watch } from 'vue';
import emitter from '@/ts/event-bus'; import emitter from '@/ts/event-bus';
type MenuItem = { type MenuItem = {

View File

@@ -1,5 +1,5 @@
<template> <template>
<t-head-menu theme="light" class="bottom-menu"> <t-head-menu theme="light" class="bottom-menu">
<router-link v-for="item in menuItems" :key="item.value" :to="item.route"> <router-link v-for="item in menuItems" :key="item.value" :to="item.route">
<t-tooltip :content="item.label" placement="top"> <t-tooltip :content="item.label" placement="top">
<t-menu-item :value="item.value" :disabled="item.disabled" class="menu-item"> <t-menu-item :value="item.value" :disabled="item.disabled" class="menu-item">
@@ -7,15 +7,13 @@
<t-icon :name="item.icon" /> <t-icon :name="item.icon" />
</template> </template>
<!-- {{item.label}}--> <!-- {{item.label}}-->
</t-menu-item> </t-menu-item>
</t-tooltip> </t-tooltip>
</router-link> </router-link>
</t-head-menu> </t-head-menu>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from 'vue';
type MenuItem = { type MenuItem = {
value: string; value: string;
label: string; label: string;

View File

@@ -46,7 +46,7 @@ import {
Loading as TLoading, Loading as TLoading,
HeadMenu as THeadMenu HeadMenu as THeadMenu
} from 'tdesign-vue-next'; } from 'tdesign-vue-next';
import { router } from './router'; import router from './router';
import 'tdesign-vue-next/es/style/index.css'; import 'tdesign-vue-next/es/style/index.css';
const app = createApp(App); const app = createApp(App);
app.use(router); app.use(router);

View File

@@ -24,7 +24,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { HttpClientConfig } from '../../../../src/onebot/config/config'; import { HttpClientConfig } from '../../../../src/onebot/config/config';
const props = defineProps<{ const props = defineProps<{

View File

@@ -30,7 +30,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { HttpServerConfig } from '../../../../src/onebot/config/config'; import { HttpServerConfig } from '../../../../src/onebot/config/config';
const props = defineProps<{ const props = defineProps<{

View File

@@ -27,7 +27,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { WebsocketClientConfig } from '../../../../src/onebot/config/config'; import { WebsocketClientConfig } from '../../../../src/onebot/config/config';
const props = defineProps<{ const props = defineProps<{

View File

@@ -33,7 +33,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { WebsocketServerConfig } from '../../../../src/onebot/config/config'; import { WebsocketServerConfig } from '../../../../src/onebot/config/config';
const props = defineProps<{ const props = defineProps<{

View File

@@ -7,6 +7,7 @@ import NetWork from '../pages/NetWork.vue';
import QQLogin from '../components/QQLogin.vue'; import QQLogin from '../components/QQLogin.vue';
import WebUiLogin from '../components/WebUiLogin.vue'; import WebUiLogin from '../components/WebUiLogin.vue';
import OtherConfig from '../pages/OtherConfig.vue'; import OtherConfig from '../pages/OtherConfig.vue';
import { MessagePlugin } from 'tdesign-vue-next';
const routes: Array<RouteRecordRaw> = [ const routes: Array<RouteRecordRaw> = [
{ path: '/', redirect: '/webui' }, { path: '/', redirect: '/webui' },
@@ -26,7 +27,22 @@ const routes: Array<RouteRecordRaw> = [
}, },
]; ];
export const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes, routes,
}); });
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('auth');
if (!token && to.path !== '/webui' && to.path !== '/qqlogin') {
MessagePlugin.error('Token 过期啦, 重新登录吧');
localStorage.clear();
setTimeout(() => {
next('/webui');
}, 500);
} else {
next();
}
});
export default router;

View File

@@ -0,0 +1,14 @@
import { MessagePlugin } from 'tdesign-vue-next';
import router from '@/router/index.js';
export const request = async (input: RequestInfo | URL, init?: RequestInit) => {
const res = await fetch(input, init);
const json = await res.json();
if (json.message.includes('Unauthorized')) {
MessagePlugin.error('Token 过期啦, 重新登录吧');
localStorage.clear();
router.push('/webui');
}
res.json = async () => json;
return res;
};

View File

@@ -3,22 +3,15 @@
"target": "ESNext", "target": "ESNext",
"jsx": "preserve", "jsx": "preserve",
"jsxImportSource": "vue", "jsxImportSource": "vue",
"lib": [ "lib": ["DOM", "DOM.Iterable", "ES2022"],
"DOM",
"DOM.Iterable"
],
"baseUrl": ".", "baseUrl": ".",
"module": "esnext", "module": "esnext",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"paths": { "paths": {
"@/*": [ "@/*": ["src/*"]
"src/*"
]
}, },
"resolveJsonModule": true, "resolveJsonModule": true,
"types": [ "types": ["vite/client"],
"vite/client"
],
"strict": true, "strict": true,
"strictNullChecks": true, "strictNullChecks": true,
"noUnusedLocals": true, "noUnusedLocals": true,
@@ -30,5 +23,5 @@
}, },
"include": ["src"], "include": ["src"],
"exclude": ["node_modules"], "exclude": ["node_modules"],
"references": [{"path": "./tsconfig.node.json"}] "references": [{ "path": "./tsconfig.node.json" }]
} }