登录失效跳转修复

This commit is contained in:
2026-08-12 10:47:18 +08:00
parent 10097f3003
commit d29075e9b4
11 changed files with 2151 additions and 759 deletions

20
components.d.ts vendored Normal file
View File

@@ -0,0 +1,20 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
Chart: typeof import('./src/components/chart/index.vue')['default']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModalProvider: typeof import('naive-ui')['NModalProvider']
ProviderHelper: typeof import('./src/components/ProviderHelper.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}

2732
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,19 +15,22 @@
"echarts": "^5.4.3", "echarts": "^5.4.3",
"echarts-liquidfill": "^3.1.0", "echarts-liquidfill": "^3.1.0",
"jsencrypt": "^3.5.4", "jsencrypt": "^3.5.4",
"naive-ui": "^2.44.1",
"ol": "^7.4.0", "ol": "^7.4.0",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"prettier": "^3.0.0", "prettier": "^3.0.0",
"vue": "^3.2.47", "vue": "^3.5.39",
"vue-router": "^4.6.4" "vue-router": "^5.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^4.1.0", "@vicons/fluent": "^0.12.0",
"@vitejs/plugin-vue-jsx": "^1.3.3", "@vitejs/plugin-vue": "^6.0.8",
"@vitejs/plugin-vue-jsx": "^5.1.6",
"@vue/compiler-sfc": "^3.5.39",
"less": "^4.1.3", "less": "^4.1.3",
"typescript": "^4.9.3", "naive-ui": "^2.44.1",
"vite": "^4.2.0", "typescript": "^7.0.2",
"vue-tsc": "^1.2.0" "unplugin-vue-components": "^28.7.0",
"vite": "8.1.4",
"vue-tsc": "^3.3.9"
} }
} }

View File

@@ -43,7 +43,18 @@ onBeforeUnmount(() => {
<template> <template>
<div class="screen-adapter"> <div class="screen-adapter">
<div class="screen-adapter__inner" :style="adapterStyle"> <div class="screen-adapter__inner" :style="adapterStyle">
<RouterView /> <n-loading-bar-provider>
<n-modal-provider>
<n-dialog-provider>
<n-message-provider>
<n-message-provider>
<provider-helper />
<router-view />
</n-message-provider>
</n-message-provider>
</n-dialog-provider>
</n-modal-provider>
</n-loading-bar-provider>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -0,0 +1,21 @@
<template>
<div></div>
</template>
<script>
import { useLoadingBar, useMessage, useModal } from 'naive-ui'
/**
* naive-ui的弹窗类的都没有提供全局方法, 这里挂载到window对象上
*/
export default {
name: 'ProviderHelper',
setup() {
window.$message = useMessage()
window.$loadingBar = useLoadingBar()
window.$modal = useModal()
}
}
</script>
<style scoped></style>

View File

@@ -4,16 +4,12 @@ import App from "./App.vue";
import Chart from "./components/chart/index.vue"; import Chart from "./components/chart/index.vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
import echartsConfig from "./config/echarts.config"; import echartsConfig from "./config/echarts.config";
import { createDiscreteApi } from "naive-ui";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import router from "./router"; import router from "./router";
import './router/routerGuard'
echarts.registerTheme("t-theme", echartsConfig); echarts.registerTheme("t-theme", echartsConfig);
const { message, dialog } = createDiscreteApi(["message", "dialog"]);
window.$message = message;
window.$modal = dialog;
const app = createApp(App); const app = createApp(App);
app.use(createPinia()); app.use(createPinia());

View File

@@ -75,21 +75,6 @@ const router = createRouter({
routes, routes,
}); });
const whiteList = ["/login"];
router.beforeEach((to) => {
const hasToken = Boolean(getToken());
if (!hasToken && !whiteList.includes(to.path)) {
return {
path: "/login",
query: { redirect: to.fullPath },
};
}
return true;
});
export function resetRouter() { export function resetRouter() {
// 当前项目暂无动态 addRoute 路由,保留该方法兼容登出流程。 // 当前项目暂无动态 addRoute 路由,保留该方法兼容登出流程。
} }

60
src/router/routerGuard.js Normal file
View File

@@ -0,0 +1,60 @@
import router from './index'
import { getToken } from '@/utils/auth'
import { useUserStore } from '@/store/modules/user.js'
const whiteList = ['/login'] // no redirect whitelist
// const setPageTitle = function (meta) {
// let title = '海灵标'
// if (meta && meta.title) {
// title = `${meta.title}`
// }
// document.title = title
// }
// 路由守卫
router.beforeEach(async (to, from, next) => {
$loadingBar.start()
// setPageTitle(to.meta)
const hasToken = getToken()
const userStore = useUserStore()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
$loadingBar.finish()
} else {
const hasGetUserInfo = userStore.name
if (hasGetUserInfo !== '') {
next()
} else {
try {
// get user info
const infoVO = await userStore.getInfo()
next({ ...to, replace: true })
} catch (error) {
await userStore.resetToken()
next(`/login?redirect=${to.path}`)
// remove token and go to login page to re-login
console.error(error)
$loadingBar.error()
}
}
}
} else {
/* has no token */
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
next(`/login?redirect=${to.path}`)
$loadingBar.finish()
}
}
})
router.afterEach((to) => {
if (to.matched.length === 0) {
router.push('/404')
// fixme 不能自动跳转404, 需要引导
}
$loadingBar.finish()
})

View File

@@ -58,9 +58,8 @@ service.interceptors.response.use(
window.$message.error(error.response.data.msg, { window.$message.error(error.response.data.msg, {
duration: 5 * 1000, duration: 5 * 1000,
}); });
} else {
handleNoLogin();
} }
handleNoLogin();
} else { } else {
handleNoLogin(); handleNoLogin();
} }

View File

@@ -1624,19 +1624,19 @@ function getStatusClass(status: DeviceItem["status"]) {
</div> </div>
<div class="video-panel"> <div class="video-panel">
<div class="video-screen"> <div class="video-screen">
<img src="/image.png" alt="" class="monitor-video"> <!-- <img src="/image.png" alt="" class="monitor-video"> -->
<!-- <video v-if="currentMonitorVideo" ref="monitorVideoRef" :key="currentMonitorVideo" <video v-if="currentMonitorVideo" ref="monitorVideoRef" :key="currentMonitorVideo"
:class="['monitor-video', { infrared: activeCameraMode === 'infrared' }]" autoplay muted :class="['monitor-video', { infrared: activeCameraMode === 'infrared' }]" autoplay muted
playsinline></video> --> playsinline></video>
<div class="scan-line"></div> <div class="scan-line"></div>
<!-- <div class="video-overlay top-left">实时视频流</div> <div class="video-overlay top-left">实时视频流</div>
<div class="video-overlay top-right"> <div class="video-overlay top-right">
{{ activeCameraMode === "white" ? "白光镜头" : "红外镜头" }} {{ activeCameraMode === "white" ? "白光镜头" : "红外镜头" }}
</div> --> </div>
<div class="video-overlay bottom-left">{{ currentRobot.id }}</div> <div class="video-overlay bottom-left">{{ currentRobot.id }}</div>
<!-- <div v-if="streamLoading" class="video-empty">视频流连接中...</div> <div v-if="streamLoading" class="video-empty">视频流连接中...</div>
<div v-else-if="streamError" class="video-empty">{{ streamError }}</div> <div v-else-if="streamError" class="video-empty">{{ streamError }}</div>
<div v-else-if="!currentMonitorVideo" class="video-empty">当前机器人暂无视频地址</div> --> <div v-else-if="!currentMonitorVideo" class="video-empty">当前机器人暂无视频地址</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,8 @@
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx' import vueJsx from '@vitejs/plugin-vue-jsx'
import { resolve } from 'path' import { resolve } from 'path'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
// import { viteSingleFile } from 'vite-plugin-singlefile' // import { viteSingleFile } from 'vite-plugin-singlefile'
@@ -11,6 +13,9 @@ export default ({ command }) => {
plugins: [ plugins: [
vue(), vue(),
vueJsx(), vueJsx(),
Components({
resolvers: [NaiveUiResolver()]
}),
], ],
define: { define: {
__VUE_OPTIONS_API__: false // 关闭 Vue2 中的 options选项API __VUE_OPTIONS_API__: false // 关闭 Vue2 中的 options选项API
@@ -25,7 +30,7 @@ export default ({ command }) => {
host: true, host: true,
proxy: { proxy: {
'/api': { '/api': {
target: `http://192.168.3.110:16003/`, target: `http://127.0.0.1:16003/`,
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
}, },