From 6314eaf3d1326847e8f8f5c67cd4b7821d08b895 Mon Sep 17 00:00:00 2001 From: chansee97 Date: Mon, 1 Apr 2024 12:38:30 +0800 Subject: [PATCH 01/35] chore: remove NProgress --- package.json | 2 - src/layouts/components/header/Breadcrumb.vue | 2 +- src/modules/nprogress.ts | 11 --- src/router/guard.ts | 8 +- src/store/app/index.ts | 1 - src/styles/index.css | 1 - src/styles/nprogress.css | 84 -------------------- src/typings/global.d.ts | 1 - 8 files changed, 5 insertions(+), 105 deletions(-) delete mode 100644 src/modules/nprogress.ts delete mode 100644 src/styles/nprogress.css diff --git a/package.json b/package.json index 3126e06..975af9d 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "chroma-js": "^2.4.2", "echarts": "^5.5.0", "md-editor-v3": "^4.11.3", - "nprogress": "^0.2.0", "performant-array-to-tree": "^1.11.0", "pinia": "^2.1.7", "pinia-plugin-persist": "^1.0.0", @@ -71,7 +70,6 @@ "@iconify/vue": "^4.1.1", "@types/chroma-js": "^2.4.4", "@types/node": "^20.11.28", - "@types/nprogress": "^0.2.3", "@types/qs": "^6.9.12", "@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue-jsx": "^3.1.0", diff --git a/src/layouts/components/header/Breadcrumb.vue b/src/layouts/components/header/Breadcrumb.vue index 9259981..ed4a96d 100644 --- a/src/layouts/components/header/Breadcrumb.vue +++ b/src/layouts/components/header/Breadcrumb.vue @@ -42,7 +42,7 @@ const appStore = useAppStore() .list-enter-from,.list-leave-to { opacity: 0; - transform: translateY(-30px); + transform: translateX(-30px); } .list-leave-active { diff --git a/src/modules/nprogress.ts b/src/modules/nprogress.ts deleted file mode 100644 index 0cf5a1d..0000000 --- a/src/modules/nprogress.ts +++ /dev/null @@ -1,11 +0,0 @@ -import NProgress from 'nprogress' -import { useAppStore } from '@/store' - -export function install() { - // 初始载入,初始化body的css变量 - const appStore = useAppStore() - appStore.setPrimaryColor(appStore.primaryColor) - - NProgress.configure({ easing: 'ease', speed: 500 }) - window.$NProgress = NProgress -} diff --git a/src/router/guard.ts b/src/router/guard.ts index 3023755..cc2d7dd 100644 --- a/src/router/guard.ts +++ b/src/router/guard.ts @@ -15,8 +15,8 @@ export function setupRouterGuard(router: Router) { window.open(to.meta.herf) return false } - // 开始 NProgress - appStore.showProgress && window.$NProgress?.start() + // 开始 loadingBar + appStore.showProgress && window.$loadingBar?.start() // 判断有无TOKEN,登录鉴权 const isLogin = Boolean(local.get('token')) @@ -67,7 +67,7 @@ export function setupRouterGuard(router: Router) { router.afterEach((to) => { // 修改网页标题 document.title = `${to.meta.title} - ${title}` - // 结束 NProgress - appStore.showProgress && window.$NProgress?.done() + // 结束 loadingBar + appStore.showProgress && window.$loadingBar?.finish() }) } diff --git a/src/store/app/index.ts b/src/store/app/index.ts index 4b98ab1..d0cf436 100644 --- a/src/store/app/index.ts +++ b/src/store/app/index.ts @@ -67,7 +67,6 @@ export const useAppStore = defineStore('app-store', { }, /* 设置主题色 */ setPrimaryColor(color: string) { - docEle.value.style.setProperty('--primary-color', color) const brightenColor = chroma(color).brighten(1).hex() const darkenColor = chroma(color).darken(1).hex() set(this.theme, 'common.primaryColor', color) diff --git a/src/styles/index.css b/src/styles/index.css index 7991a1f..c09a6a2 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -1,6 +1,5 @@ @import './reset.css'; @import './transition.css'; -@import './nprogress.css'; html, body, diff --git a/src/styles/nprogress.css b/src/styles/nprogress.css deleted file mode 100644 index c3ad48c..0000000 --- a/src/styles/nprogress.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Make clicks pass-through */ -#nprogress { - pointer-events: none; -} - -#nprogress .bar { - background: var(--primary-color); - - position: fixed; - z-index: 1031; - top: 0; - left: 0; - - width: 100%; - height: 2px; -} - -/* Fancy blur effect */ -#nprogress .peg { - display: block; - position: absolute; - right: 0px; - width: 100px; - height: 100%; - box-shadow: 0 0 10px var(--primary-color), 0 0 5px var(--primary-color); - opacity: 1.0; - - -webkit-transform: rotate(3deg) translate(0px, -4px); - -ms-transform: rotate(3deg) translate(0px, -4px); - transform: rotate(3deg) translate(0px, -4px); -} - -/* Remove these to get rid of the spinner */ -#nprogress .spinner { - display: block; - position: fixed; - z-index: 1031; - top: 15px; - right: 15px; -} - -#nprogress .spinner-icon { - width: 18px; - height: 18px; - box-sizing: border-box; - - border: solid 2px transparent; - border-top-color: var(--primary-color); - border-left-color: var(--primary-color); - border-radius: 50%; - - -webkit-animation: nprogress-spinner 400ms linear infinite; - animation: nprogress-spinner 400ms linear infinite; -} - -.nprogress-custom-parent { - overflow: hidden; - position: relative; -} - -.nprogress-custom-parent #nprogress .spinner, -.nprogress-custom-parent #nprogress .bar { - position: absolute; -} - -@-webkit-keyframes nprogress-spinner { - 0% { - -webkit-transform: rotate(0deg); - } - - 100% { - -webkit-transform: rotate(360deg); - } -} - -@keyframes nprogress-spinner { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} diff --git a/src/typings/global.d.ts b/src/typings/global.d.ts index 99650e4..e235773 100644 --- a/src/typings/global.d.ts +++ b/src/typings/global.d.ts @@ -3,7 +3,6 @@ interface Window { $dialog: import('naive-ui').DialogApi $message: import('naive-ui').MessageApi $notification: import('naive-ui').NotificationApi - $NProgress: import('NProgress').NProgress } declare const AMap: any From 18c1ffe8288d73b57405d5fcba6589d8fd48c10e Mon Sep 17 00:00:00 2001 From: Xou <1192158284@qq.com> Date: Mon, 1 Apr 2024 14:41:16 +0800 Subject: [PATCH 02/35] updata plugin layout --- src/views/plugin/fetch/index.vue | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/views/plugin/fetch/index.vue b/src/views/plugin/fetch/index.vue index 147b17f..7a9ce57 100644 --- a/src/views/plugin/fetch/index.vue +++ b/src/views/plugin/fetch/index.vue @@ -193,16 +193,20 @@ const downloadProcess = computed(() => { - -
文件大小:{{ downloading.total }}B
-
已下载:{{ downloading.loaded }}B
- - - 开始下载 - - - 中断下载 - + + +
文件大小:{{ downloading.total }}B
+
已下载:{{ downloading.loaded }}B
+ + + + 开始下载 + + + 中断下载 + + +
From 03ad287f43d59a423bc374561b20421a7995dc7e Mon Sep 17 00:00:00 2001 From: chansee97 Date: Mon, 1 Apr 2024 16:58:10 +0800 Subject: [PATCH 03/35] fix: fecth type error --- src/main.ts | 2 +- src/service/api/login.ts | 6 +++--- src/service/http/handle.ts | 5 +++-- src/store/auth.ts | 6 ++++-- src/store/route.ts | 4 ++++ src/typings/route.d.ts | 11 +++++++---- src/typings/service.d.ts | 15 ++++++++++++++- vercel.json | 3 --- 8 files changed, 36 insertions(+), 16 deletions(-) delete mode 100644 vercel.json diff --git a/src/main.ts b/src/main.ts index daa2839..16cb86a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -18,7 +18,7 @@ async function setupApp() { // 注册模块 Vue-router await installRouter(app) - /* 注册模块 Vue-router/Pinia */ + /* 注册模块 指令/静态资源 */ Object.values( import.meta.glob<{ install: (app: App) => void }>('./modules/*.ts', { eager: true, diff --git a/src/service/api/login.ts b/src/service/api/login.ts index 04c42c3..a877601 100644 --- a/src/service/api/login.ts +++ b/src/service/api/login.ts @@ -6,14 +6,14 @@ interface Ilogin { } export function fetchLogin(params: Ilogin) { - const methodInstance = alovaInstance.Post('/login', params) + const methodInstance = alovaInstance.Post>('/login', params) methodInstance.meta = { authRole: null, } return methodInstance } export function fetchUpdateToken(params: any) { - const method = alovaInstance.Post('/updateToken', params) + const method = alovaInstance.Post>('/updateToken', params) method.meta = { authRole: 'refreshToken', } @@ -21,5 +21,5 @@ export function fetchUpdateToken(params: any) { } export function fetchUserRoutes(params: { id: number }) { - return alovaInstance.Get('/getUserRoutes', { params }) + return alovaInstance.Get >('/getUserRoutes', { params }) } diff --git a/src/service/http/handle.ts b/src/service/http/handle.ts index b444d10..65532f9 100644 --- a/src/service/http/handle.ts +++ b/src/service/http/handle.ts @@ -56,11 +56,12 @@ export function handleBusinessError(data: Record, config: Required< * @return {*} result */ export function handleServiceResult(data: any, isSuccess: boolean = true) { - return { + const result = { isSuccess, errorType: null, ...data, } + return result } /** @@ -69,7 +70,7 @@ export function handleServiceResult(data: any, isSuccess: boolean = true) { */ export async function handleRefreshToken() { const authStore = useAuthStore() - const data = await fetchUpdateToken({ refreshToken: local.get('refreshToken') }) + const { data } = await fetchUpdateToken({ refreshToken: local.get('refreshToken') }) if (data) { local.set('token', data.accessToken) local.set('refreshToken', data.refreshToken) diff --git a/src/store/auth.ts b/src/store/auth.ts index 1c39f7a..764ef55 100644 --- a/src/store/auth.ts +++ b/src/store/auth.ts @@ -53,9 +53,11 @@ export const useAuthStore = defineStore('auth-store', { /* 用户登录 */ async login(username: string, password: string) { - const { error, data } = await fetchLogin({ username, password }) - if (error) + const { isSuccess, data } = await fetchLogin({ username, password }) + if (!isSuccess) { + window.$message.error('登录失败,请检查用户名和密码') return + } // 处理登录信息 await this.handleAfterLogin(data) diff --git a/src/store/route.ts b/src/store/route.ts index 8c61da6..75ea41d 100644 --- a/src/store/route.ts +++ b/src/store/route.ts @@ -181,6 +181,10 @@ export const useRouteStore = defineStore('route-store', { this.isInitAuthRoute = false // 初始化路由信息 const rowRoutes = await this.initRouteInfo() + if (!rowRoutes) { + window.$message.error('获取路由失败,请稍后再试') + return + } this.rowRoutes = rowRoutes // 生成真实路由并插入 this.createRoutes(rowRoutes) diff --git a/src/typings/route.d.ts b/src/typings/route.d.ts index 396135a..7c2edf8 100644 --- a/src/typings/route.d.ts +++ b/src/typings/route.d.ts @@ -1,5 +1,5 @@ declare namespace AppRoute { - /** 路由描述 */ + /** 单个路由所携带的meta标识 */ interface RouteMeta { /* 页面标题,通常必选。 */ title: string @@ -17,7 +17,7 @@ declare namespace AppRoute { order?: number /* 嵌套外链 */ herf?: string - /** 当前路由需要选中的菜单项(用于跳转至不在左侧菜单显示的路由且需要高亮某个菜单的情况) */ + /** 当前路由需要选中的菜单项,用于跳转至不在左侧菜单显示的路由且需要高亮某个菜单的情况 */ activeMenu?: string /** 当前路由是否会被添加到Tab中 */ withoutTab?: boolean @@ -34,9 +34,9 @@ declare namespace AppRoute { redirect?: string /* 页面组件地址 */ componentPath?: string | null - // 路由id + /* 路由id */ id: numnber - // 父级路由id,顶级页面为null + /* 父级路由id,顶级页面为null */ pid: number | null } @@ -44,6 +44,9 @@ declare namespace AppRoute { [K in keyof RouteMeta as `meta.${K}`]?: RouteMeta[K] } & baseRoute + /** + * 挂载到项目上的真实路由结构 + */ interface Route extends baseRoute { /** 子路由 */ children?: Route[] diff --git a/src/typings/service.d.ts b/src/typings/service.d.ts index 888fe56..3585416 100644 --- a/src/typings/service.d.ts +++ b/src/typings/service.d.ts @@ -20,7 +20,7 @@ declare namespace Service { successCode?: number | string } - type RequestErrorType = 'Response Error' | 'Business Error' + type RequestErrorType = 'Response Error' | 'Business Error' | null type RequestCode = string | number interface RequestError { @@ -33,4 +33,17 @@ declare namespace Service { /** 返回的数据 */ data?: any } + + interface ResponseResult extends RequestError { + /** 请求服务是否成功 */ + isSuccess: boolean + /** 请求服务的错误类型 */ + errorType: RequestErrorType + /** 错误码 */ + code: RequestCode + /** 错误信息 */ + msg: string + /** 返回的数据 */ + data: T + } } diff --git a/vercel.json b/vercel.json deleted file mode 100644 index afea4ae..0000000 --- a/vercel.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rewrites": [{ "source": "/:path*", "destination": "/index.html" }] -} From a2ed803a05ae453d4c0fccc3f900377ef74e8366 Mon Sep 17 00:00:00 2001 From: chansee97 Date: Mon, 1 Apr 2024 17:46:17 +0800 Subject: [PATCH 04/35] fix: modify to dynamic router --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index b48df03..77ad0d3 100644 --- a/.env +++ b/.env @@ -5,7 +5,7 @@ VITE_APP_NAME=Nova - Admin # 路由模式 VITE_ROUTE_MODE = web # 权限路由模式: static | dynamic -VITE_AUTH_ROUTE_MODE=static +VITE_AUTH_ROUTE_MODE=dynamic # 设置登陆后跳转地址 VITE_HOME_PATH = /dashboard/workbench From 98ed84b2b3aee6bf08e8bb4fcee65f705ab704c4 Mon Sep 17 00:00:00 2001 From: chansee97 Date: Mon, 1 Apr 2024 22:48:36 +0800 Subject: [PATCH 05/35] refactor: modify request name --- src/hooks/index.ts | 2 +- src/hooks/{useSystem.ts => usePermission.ts} | 0 src/service/api/list.ts | 4 +-- src/service/api/login.ts | 8 +++--- src/service/api/test.ts | 26 ++++++++++---------- src/service/http/index.ts | 2 +- src/store/route.ts | 1 + 7 files changed, 22 insertions(+), 21 deletions(-) rename src/hooks/{useSystem.ts => usePermission.ts} (100%) diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 2d9528c..e78b4c1 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,4 +1,4 @@ export * from './useBoolean' export * from './useLoading' export * from './useEcharts' -export * from './useSystem' +export * from './usePermission' diff --git a/src/hooks/useSystem.ts b/src/hooks/usePermission.ts similarity index 100% rename from src/hooks/useSystem.ts rename to src/hooks/usePermission.ts diff --git a/src/service/api/list.ts b/src/service/api/list.ts index ce33ebc..dca2205 100644 --- a/src/service/api/list.ts +++ b/src/service/api/list.ts @@ -1,5 +1,5 @@ -import { alovaInstance } from '../http' +import { request } from '../http' export function fetchUserList() { - return alovaInstance.Get('/userList') + return request.Get('/userList') } diff --git a/src/service/api/login.ts b/src/service/api/login.ts index a877601..595d923 100644 --- a/src/service/api/login.ts +++ b/src/service/api/login.ts @@ -1,4 +1,4 @@ -import { alovaInstance } from '../http' +import { request } from '../http' interface Ilogin { username: string @@ -6,14 +6,14 @@ interface Ilogin { } export function fetchLogin(params: Ilogin) { - const methodInstance = alovaInstance.Post>('/login', params) + const methodInstance = request.Post>('/login', params) methodInstance.meta = { authRole: null, } return methodInstance } export function fetchUpdateToken(params: any) { - const method = alovaInstance.Post>('/updateToken', params) + const method = request.Post>('/updateToken', params) method.meta = { authRole: 'refreshToken', } @@ -21,5 +21,5 @@ export function fetchUpdateToken(params: any) { } export function fetchUserRoutes(params: { id: number }) { - return alovaInstance.Get >('/getUserRoutes', { params }) + return request.Get >('/getUserRoutes', { params }) } diff --git a/src/service/api/test.ts b/src/service/api/test.ts index 9e9ab3c..b544c89 100644 --- a/src/service/api/test.ts +++ b/src/service/api/test.ts @@ -1,17 +1,17 @@ -import { alovaInstance, blankInstance } from '../http' +import { blankInstance, request } from '../http' /* get方法测试 */ export function fetachGet(params?: any) { - return alovaInstance.Get('/getAPI', { params }) + return request.Get('/getAPI', { params }) } /* post方法测试 */ export function fetchPost(data: any) { - return alovaInstance.Post('/postAPI', data) + return request.Post('/postAPI', data) } /* formPost方法测试 */ export function fetchFormPost(data: any) { - const methodInstance = alovaInstance.Post('/postFormAPI', data) + const methodInstance = request.Post('/postFormAPI', data) methodInstance.meta = { isFormPost: true, } @@ -19,15 +19,15 @@ export function fetchFormPost(data: any) { } /* delete方法测试 */ export function fetchDelete() { - return alovaInstance.Delete('/deleteAPI') + return request.Delete('/deleteAPI') } /* put方法测试 */ export function fetchPut(data: any) { - return alovaInstance.Put('/putAPI', data) + return request.Put('/putAPI', data) } /* 不携带token的接口 */ export function withoutToken() { - const methodInstance = alovaInstance.Get('/getAPI') + const methodInstance = request.Get('/getAPI') methodInstance.meta = { authRole: null, } @@ -35,7 +35,7 @@ export function withoutToken() { } /* 接口数据转换 */ export function dictData() { - return alovaInstance.Get('/getDictData', { + return request.Get('/getDictData', { transformData(rawData, _headers) { const { data } = rawData as any return { @@ -64,22 +64,22 @@ export function downloadFile(url: string) { } /* 测试状态码500失败 */ export function FailedRequest() { - return alovaInstance.Get('/serverError') + return request.Get('/serverError') } /* 测试业务码500失败 */ export function FailedResponse() { - return alovaInstance.Post('/businessError') + return request.Post('/businessError') } /* 测试业务码10000失败,无提示 */ export function FailedResponseWithoutTip() { - return alovaInstance.Post('/businessErrorWithoutTip') + return request.Post('/businessErrorWithoutTip') } /* token失效的接口 */ export function expiredTokenRequest() { - return alovaInstance.Get('/expiredToken') + return request.Get('/expiredToken') } /* 测试token刷新接口 */ export function refreshToken() { - return alovaInstance.Get('/updataToken') + return request.Get('/updataToken') } diff --git a/src/service/http/index.ts b/src/service/http/index.ts index 988ccf4..91192d0 100644 --- a/src/service/http/index.ts +++ b/src/service/http/index.ts @@ -6,7 +6,7 @@ const isHttpProxy = import.meta.env.VITE_HTTP_PROXY === 'Y' || false const { url } = generateProxyPattern(serviceConfig[import.meta.env.MODE]) -export const alovaInstance = createAlovaInstance({ +export const request = createAlovaInstance({ baseURL: isHttpProxy ? url.proxy : url.value, }) diff --git a/src/store/route.ts b/src/store/route.ts index 75ea41d..7b4582a 100644 --- a/src/store/route.ts +++ b/src/store/route.ts @@ -135,6 +135,7 @@ export const useRouteStore = defineStore('route-store', { }) resultRouter = arrayToTree(resultRouter) as AppRoute.Route[] + console.warn('🚀 ~ createRoutes ~ resultRouter:', resultRouter) this.setRedirect(resultRouter) const appRootRoute: RouteRecordRaw = { path: '/appRoot', From 609a26b8478620f02a74d8794cee50a9ae4d020d Mon Sep 17 00:00:00 2001 From: chansee97 Date: Tue, 2 Apr 2024 11:22:10 +0800 Subject: [PATCH 06/35] fix: fetch demo error --- src/service/api/test.ts | 17 ++++++++++---- src/store/route.ts | 1 - src/views/plugin/fetch/index.vue | 39 +++++++++++++++++++------------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/service/api/test.ts b/src/service/api/test.ts index b544c89..c224885 100644 --- a/src/service/api/test.ts +++ b/src/service/api/test.ts @@ -37,10 +37,14 @@ export function withoutToken() { export function dictData() { return request.Get('/getDictData', { transformData(rawData, _headers) { - const { data } = rawData as any + const response = rawData as any return { - gender: data.gender === 0 ? '男' : '女', - status: `状态是${data.status}`, + ...response, + data: { + ...response.data, + gender: response.data.gender === 0 ? '男' : '女', + status: `状态是${response.data.status}`, + }, } }, }) @@ -57,10 +61,15 @@ export function getBlob(url: string) { /* 带进度的下载文件 */ export function downloadFile(url: string) { - return blankInstance.Get(url, { + const methodInstance = blankInstance.Get(url, { // 开启下载进度 enableDownload: true, }) + methodInstance.meta = { + // 标识为bolb数据 + isBlob: true, + } + return methodInstance } /* 测试状态码500失败 */ export function FailedRequest() { diff --git a/src/store/route.ts b/src/store/route.ts index 7b4582a..75ea41d 100644 --- a/src/store/route.ts +++ b/src/store/route.ts @@ -135,7 +135,6 @@ export const useRouteStore = defineStore('route-store', { }) resultRouter = arrayToTree(resultRouter) as AppRoute.Route[] - console.warn('🚀 ~ createRoutes ~ resultRouter:', resultRouter) this.setRedirect(resultRouter) const appRootRoute: RouteRecordRaw = { path: '/appRoot', diff --git a/src/views/plugin/fetch/index.vue b/src/views/plugin/fetch/index.vue index 7a9ce57..3844b47 100644 --- a/src/views/plugin/fetch/index.vue +++ b/src/views/plugin/fetch/index.vue @@ -112,24 +112,16 @@ function getDictData() { msg.value = res }) } + +const filePath = ref('https://images.unsplash.com/photo-1663529628961-80aa6ebcd157?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80') // 模拟获取二进制文件 -const imagePath = ref('https://images.unsplash.com/photo-1663529628961-80aa6ebcd157?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80') function getBlobFile() { - getBlob(imagePath.value).then((res) => { - msg.value = 'this is blob!' - const link = URL.createObjectURL(res) - const eleLink = document.createElement('a') - eleLink.download = 'okk' - eleLink.style.display = 'none' - eleLink.href = link - document.body.appendChild(eleLink) - eleLink.click() - document.body.removeChild(eleLink) + getBlob(filePath.value).then((res) => { + downloadLink(res, 'BlobOk') }) } -// 下载大文件获取进度 -const downloadPath = ref('https://suqiqi.oss-cn-beijing.aliyuncs.com/test/video/1.mp4') -const { downloading, abort: abortDownloadFile, send: sendDownloadFile } = useRequest(downloadFile(downloadPath.value), { +// 下载文件获取进度 +const { downloading, abort: abortDownloadFile, send: sendDownloadFile } = useRequest(downloadFile(filePath.value), { // 当immediate为false时,默认不发出 immediate: false, }) @@ -138,6 +130,21 @@ const downloadProcess = computed(() => { return 0 return Math.floor(downloading.value.loaded / downloading.value.total * 100) }) +async function handleDownloadFile() { + const res = await sendDownloadFile() + downloadLink(res, 'fileOk') +} + +function downloadLink(data: Blob, name: string) { + const link = URL.createObjectURL(data) + const eleLink = document.createElement('a') + eleLink.download = name + eleLink.style.display = 'none' + eleLink.href = link + document.body.appendChild(eleLink) + eleLink.click() + document.body.removeChild(eleLink) +} diff --git a/src/components/custom/CopyText.vue b/src/components/custom/CopyText.vue index 2119255..92d8496 100644 --- a/src/components/custom/CopyText.vue +++ b/src/components/custom/CopyText.vue @@ -14,7 +14,7 @@ const text = useVModel(props, 'modelValue', emit) {{ text }} - + diff --git a/src/components/custom/IconSelect/index.vue b/src/components/custom/IconSelect/index.vue index 3750a40..66b5db6 100644 --- a/src/components/custom/IconSelect/index.vue +++ b/src/components/custom/IconSelect/index.vue @@ -18,7 +18,7 @@ function handleSelectIcon(icon: string) { @@ -33,7 +33,7 @@ function handleSelectIcon(icon: string) { class="border border-gray-200 m-2px p-5px flex-center" @click="handleSelectIcon(item)" > - + diff --git a/src/components/custom/EIcon.vue b/src/components/custom/NovaIcon.vue similarity index 79% rename from src/components/custom/EIcon.vue rename to src/components/custom/NovaIcon.vue index f3aee98..8fc1283 100644 --- a/src/components/custom/EIcon.vue +++ b/src/components/custom/NovaIcon.vue @@ -2,19 +2,23 @@ import { Icon } from '@iconify/vue' interface iconPorps { + /* 图标名称 */ icon?: string + /* 图标颜色 */ color?: string + /* 图标大小 */ size?: number + /* 图标深度 */ depth?: 1 | 2 | 3 | 4 | 5 } const props = withDefaults(defineProps(), { size: 18, - icon: 'icon-park-outline:baby-feet', }) diff --git a/src/layouts/components/header/FullScreen.vue b/src/layouts/components/header/FullScreen.vue index 3dd5f65..9409809 100644 --- a/src/layouts/components/header/FullScreen.vue +++ b/src/layouts/components/header/FullScreen.vue @@ -12,7 +12,7 @@ const appStore = useAppStore() - 全屏 + {{ $t('app.toggleFullScreen') }} diff --git a/src/layouts/components/header/Notices.vue b/src/layouts/components/header/Notices.vue index 78101e0..eacfab4 100644 --- a/src/layouts/components/header/Notices.vue +++ b/src/layouts/components/header/Notices.vue @@ -81,11 +81,10 @@ const MassageData = ref([ ]) const currentTab = ref(0) function handleRead(id: number) { - // MassageData.value[currentTab.value].list[index].isRead = true const data = MassageData.value.find(i => i.id === id) if (data) data.isRead = true - window.$message.success(`已读id: ${id}`) + window.$message.success(`id: ${id}`) } const massageCount = computed(() => { return MassageData.value.filter(i => !i.isRead).length @@ -106,14 +105,14 @@ const groupMessage = computed(() => { - 消息通知 + {{ $t('app.notificationsTips') }} @@ -122,7 +121,7 @@ const groupMessage = computed(() => { @@ -131,7 +130,7 @@ const groupMessage = computed(() => { diff --git a/src/layouts/components/header/Search.vue b/src/layouts/components/header/Search.vue index c844cc7..e840ec2 100644 --- a/src/layouts/components/header/Search.vue +++ b/src/layouts/components/header/Search.vue @@ -6,16 +6,18 @@ import { renderIcon } from '@/utils' const routeStore = useRouteStore() const searchValue = ref('') +const { t } = useI18n() + const options = computed(() => { return routeStore.rowRoutes.filter((item) => { const conditions = [ - item['meta.title']?.includes(searchValue.value), + t(`route.${String(item.name)}`, item['meta.title'] || item.name)?.includes(searchValue.value), item.path?.includes(searchValue.value), ] return conditions.some(condition => condition) }).map((item) => { return { - label: item['meta.title'], + label: t(`route.${String(item.name)}`, item['meta.title'] || item.name), value: item.path, icon: item['meta.icon'], } @@ -44,7 +46,7 @@ function handleSelect(value: string) { - 设置 + {{ $t('app.setting') }} - - diff --git a/src/layouts/components/header/UserCenter.vue b/src/layouts/components/header/UserCenter.vue index 71e02d1..9351fcb 100644 --- a/src/layouts/components/header/UserCenter.vue +++ b/src/layouts/components/header/UserCenter.vue @@ -2,46 +2,50 @@ import { renderIcon } from '@/utils/icon' import { useAuthStore } from '@/store' +const { t } = useI18n() + const { userInfo, resetAuthStore } = useAuthStore() const router = useRouter() -const options = [ - { - label: '个人中心', - key: 'userCenter', - icon: renderIcon('carbon:user-avatar-filled-alt'), - }, - { - type: 'divider', - key: 'd1', - }, - { - label: 'Github', - key: 'guthub', - icon: renderIcon('icon-park-outline:github'), - }, - { - label: 'gitee', - key: 'gitee', - icon: renderIcon('simple-icons:gitee'), - }, - { - type: 'divider', - key: 'd1', - }, - { - label: '退出登录', - key: 'loginOut', - icon: renderIcon('icon-park-outline:logout'), - }, -] +const options = computed(() => { + return [ + { + label: t('app.userCenter'), + key: 'userCenter', + icon: renderIcon('carbon:user-avatar-filled-alt'), + }, + { + type: 'divider', + key: 'd1', + }, + { + label: 'Github', + key: 'guthub', + icon: renderIcon('icon-park-outline:github'), + }, + { + label: 'Gitee', + key: 'gitee', + icon: renderIcon('simple-icons:gitee'), + }, + { + type: 'divider', + key: 'd1', + }, + { + label: t('app.loginOut'), + key: 'loginOut', + icon: renderIcon('icon-park-outline:logout'), + }, + ] +}) function handleSelect(key: string | number) { if (key === 'loginOut') { window.$dialog?.info({ - title: '退出登录', - content: '确认退出当前账号?', - positiveText: '确定', - negativeText: '取消', + title: t('app.loginOutTitle'), + content: t('app.loginOutContent'), + positiveText: t('common.confirm'), + negativeText: t('common.cancel'), onPositiveClick: () => { resetAuthStore() }, diff --git a/src/layouts/components/tab/DropTabs.vue b/src/layouts/components/tab/DropTabs.vue new file mode 100644 index 0000000..1335f02 --- /dev/null +++ b/src/layouts/components/tab/DropTabs.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/src/layouts/components/tab/Reload.vue b/src/layouts/components/tab/Reload.vue index 75631fe..aae2f83 100644 --- a/src/layouts/components/tab/Reload.vue +++ b/src/layouts/components/tab/Reload.vue @@ -21,7 +21,7 @@ function handleReload() { - 刷新页面 + {{ $t('common.reload') }} diff --git a/src/layouts/components/tab/TabBar.vue b/src/layouts/components/tab/TabBar.vue index 3855e4a..76e537f 100644 --- a/src/layouts/components/tab/TabBar.vue +++ b/src/layouts/components/tab/TabBar.vue @@ -1,6 +1,7 @@ - +./DropTabs.vue diff --git a/src/modules/i18n.ts b/src/modules/i18n.ts new file mode 100644 index 0000000..ed3e0c7 --- /dev/null +++ b/src/modules/i18n.ts @@ -0,0 +1,19 @@ +import { createI18n } from 'vue-i18n' +import type { App } from 'vue' +import en from '../../locales/en.json' +import zh from '../../locales/zh.json' +import { local } from '@/utils' + +export const i18n = createI18n({ + legacy: false, + locale: local.get('lang') || 'zh', // 默认显示语言 + fallbackLocale: 'en', + messages: { + zh, + en, + }, +}) + +export function install(app: App) { + app.use(i18n) +} diff --git a/src/router/routes.static.ts b/src/router/routes.static.ts index 3854085..9971d0a 100644 --- a/src/router/routes.static.ts +++ b/src/router/routes.static.ts @@ -10,7 +10,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': null, }, { - 'name': 'dashboard_workbench', + 'name': 'workbench', 'path': '/dashboard/workbench', 'meta.title': '工作台', 'meta.requiresAuth': true, @@ -21,7 +21,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 1, }, { - 'name': 'dashboard_monitor', + 'name': 'monitor', 'path': '/dashboard/monitor', 'meta.title': '监控页', 'meta.requiresAuth': true, @@ -51,7 +51,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 4, }, { - 'name': 'test2_detail', + 'name': 'test2Detail', 'path': '/test/test2/detail', 'meta.title': '多级菜单的详情页', 'meta.requiresAuth': true, @@ -93,7 +93,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': null, }, { - 'name': 'list_commonList', + 'name': 'commonList', 'path': '/list/commonList', 'meta.title': '常用列表', 'meta.requiresAuth': true, @@ -103,7 +103,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 10, }, { - 'name': 'list_cardList', + 'name': 'cardList', 'path': '/list/cardList', 'meta.title': '卡片列表', 'meta.requiresAuth': true, @@ -113,8 +113,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 10, }, { - 'name': 'plugin', - 'path': '/plugin', + 'name': 'demo', + 'path': '/demo', 'meta.title': '功能示例', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:application-one', @@ -124,38 +124,38 @@ export const staticRoutes: AppRoute.RowRoute[] = [ }, { 'name': 'fetch', - 'path': '/plugin/fetch', - 'meta.title': '接口功能测试', + 'path': '/demo/fetch', + 'meta.title': '请求示例', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:international', - 'componentPath': '/plugin/fetch/index.vue', + 'componentPath': '/demo/fetch/index.vue', 'id': 5, 'pid': 13, }, { - 'name': 'plugin_echarts', - 'path': '/plugin/echarts', + 'name': 'echarts', + 'path': '/demo/echarts', 'meta.title': 'ECharts', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:chart-proportion', - 'componentPath': '/plugin/echarts/index.vue', + 'componentPath': '/demo/echarts/index.vue', 'id': 15, 'pid': 13, }, { - 'name': 'PluginMap', - 'path': '/plugin/map', + 'name': 'map', + 'path': '/demo/map', 'meta.title': '地图', 'meta.requiresAuth': true, 'meta.icon': 'carbon:map', 'meta.keepAlive': true, - 'componentPath': '/plugin/map/index.vue', + 'componentPath': '/demo/map/index.vue', 'id': 17, 'pid': 13, }, { - 'name': 'plugin_editor', - 'path': '/plugin/editor', + 'name': 'editor', + 'path': '/demo/editor', 'meta.title': '编辑器', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:editor', @@ -164,52 +164,52 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 13, }, { - 'name': 'plugin_md', - 'path': '/plugin/editor/md', + 'name': 'editorMd', + 'path': '/demo/editor/md', 'meta.title': 'MarkDown', 'meta.requiresAuth': true, 'meta.icon': 'ri:markdown-line', - 'componentPath': '/plugin/editor/md/index.vue', + 'componentPath': '/demo/editor/md/index.vue', 'id': 19, 'pid': 18, }, { - 'name': 'plugin_rich', - 'path': '/plugin/editor/rich', + 'name': 'editorRich', + 'path': '/demo/editor/rich', 'meta.title': '富文本', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:edit-one', - 'componentPath': '/plugin/editor/rich/index.vue', + 'componentPath': '/demo/editor/rich/index.vue', 'id': 20, 'pid': 18, }, { - 'name': 'plugin_clipboard', - 'path': '/plugin/clipboard', + 'name': 'clipboard', + 'path': '/demo/clipboard', 'meta.title': '剪贴板', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:clipboard', - 'componentPath': '/plugin/clipboard/index.vue', + 'componentPath': '/demo/clipboard/index.vue', 'id': 21, 'pid': 13, }, { - 'name': 'plugin_icons', - 'path': '/plugin/icons', + 'name': 'icons', + 'path': '/demo/icons', 'meta.title': '图标', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:winking-face-with-open-eyes', - 'componentPath': '/plugin/icons/index.vue', + 'componentPath': '/demo/icons/index.vue', 'id': 22, 'pid': 13, }, { - 'name': 'plugin_QRCode', - 'path': '/plugin/QRCode', + 'name': 'QRCode', + 'path': '/demo/QRCode', 'meta.title': '二维码', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:two-dimensional-code', - 'componentPath': '/plugin/QRCode/index.vue', + 'componentPath': '/demo/QRCode/index.vue', 'id': 23, 'pid': 13, }, @@ -224,9 +224,9 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': null, }, { - 'name': 'docments_vue', + 'name': 'docmentsVue', 'path': '/docments/vue', - 'meta.title': 'vue', + 'meta.title': 'Vue', 'meta.requiresAuth': true, 'meta.icon': 'logos:vue', 'componentPath': '/docments/vue/index.vue', @@ -234,9 +234,9 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 24, }, { - 'name': 'docments_vite', + 'name': 'docmentsVite', 'path': '/docments/vite', - 'meta.title': 'vite', + 'meta.title': 'Vite', 'meta.requiresAuth': true, 'meta.icon': 'logos:vitejs', 'componentPath': '/docments/vite/index.vue', @@ -244,7 +244,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 24, }, { - 'name': 'docments_vueuse', + 'name': 'docmentsVueuse', 'path': '/docments/vueuse', 'meta.title': 'VueUse(外链)', 'meta.requiresAuth': true, @@ -257,7 +257,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ { 'name': 'permission', 'path': '/permission', - 'meta.title': '权限示例', + 'meta.title': '权限', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:people-safe', 'componentPath': null, @@ -265,7 +265,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': null, }, { - 'name': 'permission_permission', + 'name': 'permissionDemo', 'path': '/permission/permission', 'meta.title': '权限示例', 'meta.requiresAuth': true, @@ -275,9 +275,9 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 28, }, { - 'name': 'permission_justSuper', + 'name': 'justSuper', 'path': '/permission/justSuper', - 'meta.title': '超管super可见', + 'meta.title': 'super可见', 'meta.requiresAuth': true, 'meta.roles': [ 'super', @@ -300,7 +300,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ { 'name': 'demo403', 'path': '/error/403', - 'meta.title': '403页', + 'meta.title': '403', 'meta.requiresAuth': true, 'meta.icon': 'carbon:error', 'meta.order': 3, @@ -311,7 +311,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ { 'name': 'demo404', 'path': '/error/404', - 'meta.title': '404页', + 'meta.title': '404', 'meta.requiresAuth': true, 'meta.icon': 'icon-park-outline:error', 'meta.order': 2, @@ -322,7 +322,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ { 'name': 'demo500', 'path': '/error/500', - 'meta.title': '500页', + 'meta.title': '500', 'meta.requiresAuth': true, 'meta.icon': 'carbon:data-error', 'meta.order': 1, @@ -341,7 +341,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': null, }, { - 'name': 'setting_account', + 'name': 'accountSetting', 'path': '/setting/account', 'meta.title': '用户设置', 'meta.requiresAuth': true, @@ -351,7 +351,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 35, }, { - 'name': 'setting_dictionary', + 'name': 'dictionarySetting', 'path': '/setting/dictionary', 'meta.title': '字典设置', 'meta.requiresAuth': true, @@ -361,7 +361,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [ 'pid': 35, }, { - 'name': 'setting_menu', + 'name': 'menuSetting', 'path': '/setting/menu', 'meta.title': '菜单设置', 'meta.requiresAuth': true, diff --git a/src/store/app/index.ts b/src/store/app/index.ts index d0cf436..03bd8b0 100644 --- a/src/store/app/index.ts +++ b/src/store/app/index.ts @@ -2,6 +2,7 @@ import type { GlobalThemeOverrides } from 'naive-ui' import chroma from 'chroma-js' import { set } from 'radash' import themeConfig from './theme.json' +import { local, setLocale } from '@/utils' type TransitionAnimation = '' | 'fade-slide' | 'fade-bottom' | 'fade-scale' | 'zoom-fade' | 'zoom-out' @@ -17,6 +18,7 @@ export const useAppStore = defineStore('app-store', { state: () => { return { footerText: 'Copyright © 2024 chansee97', + lang: 'zh', theme: themeConfig as GlobalThemeOverrides, primaryColor: themeConfig.common.primaryColor, collapsed: false, @@ -65,6 +67,11 @@ export const useAppStore = defineStore('app-store', { // 重置所有配色 this.setPrimaryColor(this.primaryColor) }, + setAppLang(lang: App.lang) { + setLocale(lang) + local.set('lang', lang) + this.lang = lang + }, /* 设置主题色 */ setPrimaryColor(color: string) { const brightenColor = chroma(color).brighten(1).hex() diff --git a/src/store/route.ts b/src/store/route.ts index 75ea41d..4274b88 100644 --- a/src/store/route.ts +++ b/src/store/route.ts @@ -3,7 +3,7 @@ import { RouterLink } from 'vue-router' import { h } from 'vue' import { clone, construct, min } from 'radash' import type { RouteRecordRaw } from 'vue-router' -import { arrayToTree, local, renderIcon } from '@/utils' +import { $t, arrayToTree, local, renderIcon } from '@/utils' import { router } from '@/router' import { fetchUserRoutes } from '@/service' import { staticRoutes } from '@/router/routes.static' @@ -81,9 +81,9 @@ export const useRouteStore = defineStore('route-store', { path: item.path, }, }, - { default: () => item.meta.title }, + { default: () => $t(`route.${String(item.name)}`, item.meta.title) }, ) - : item.meta.title, + : $t(`route.${String(item.name)}`, item.meta.title), key: item.path, icon: item.meta.icon ? renderIcon(item.meta.icon) : undefined, } @@ -142,7 +142,7 @@ export const useRouteStore = defineStore('route-store', { redirect: import.meta.env.VITE_HOME_PATH, component: BasicLayout, meta: { - title: '首页', + title: '', icon: 'icon-park-outline:home', }, children: [], diff --git a/src/typings/global.d.ts b/src/typings/global.d.ts index af687ad..d2f4ed2 100644 --- a/src/typings/global.d.ts +++ b/src/typings/global.d.ts @@ -19,6 +19,13 @@ declare namespace NaiveUI { type ThemeColor = 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning' } +declare module '~icons/*' { + import type { FunctionalComponent, SVGAttributes } from 'vue' + + const component: FunctionalComponent + export default component +} + declare namespace Storage { interface Session { demoKey: string @@ -33,5 +40,11 @@ declare namespace Storage { refreshToken: string /* 存储登录账号 */ loginAccount: any + /* 存储当前语言 */ + lang: App.lang } } + +declare namespace App { + type lang = 'zh' | 'en' +} diff --git a/src/typings/route.d.ts b/src/typings/route.d.ts index 7c2edf8..85c4a22 100644 --- a/src/typings/route.d.ts +++ b/src/typings/route.d.ts @@ -23,6 +23,8 @@ declare namespace AppRoute { withoutTab?: boolean /** 当前路由是否会被固定在Tab中,用于一些常驻页面 */ pinTab?: boolean + /** 当前路由i18n标识 */ + i18nKey?: string } /** 单个路由的类型结构(动态路由模式:后端返回此类型结构的路由) */ interface baseRoute { diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..7cc9411 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,7 @@ +import { i18n } from '@/modules/i18n' + +export function setLocale(locale: App.lang) { + i18n.global.locale.value = locale +} + +export const $t = i18n.global.t diff --git a/src/utils/index.ts b/src/utils/index.ts index c8551d7..d9bedb9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,4 @@ export * from './icon' export * from './storage' export * from './array' +export * from './i18n' diff --git a/src/views/plugin/QRCode/index.vue b/src/views/demo/QRCode/index.vue similarity index 100% rename from src/views/plugin/QRCode/index.vue rename to src/views/demo/QRCode/index.vue diff --git a/src/views/plugin/clipboard/index.vue b/src/views/demo/clipboard/index.vue similarity index 100% rename from src/views/plugin/clipboard/index.vue rename to src/views/demo/clipboard/index.vue diff --git a/src/views/plugin/echarts/index.vue b/src/views/demo/echarts/index.vue similarity index 100% rename from src/views/plugin/echarts/index.vue rename to src/views/demo/echarts/index.vue diff --git a/src/views/plugin/editor/md/index.vue b/src/views/demo/editor/md/index.vue similarity index 100% rename from src/views/plugin/editor/md/index.vue rename to src/views/demo/editor/md/index.vue diff --git a/src/views/plugin/editor/rich/index.vue b/src/views/demo/editor/rich/index.vue similarity index 100% rename from src/views/plugin/editor/rich/index.vue rename to src/views/demo/editor/rich/index.vue diff --git a/src/views/plugin/fetch/components/Delete.vue b/src/views/demo/fetch/components/Delete.vue similarity index 100% rename from src/views/plugin/fetch/components/Delete.vue rename to src/views/demo/fetch/components/Delete.vue diff --git a/src/views/plugin/fetch/components/DownLoad.vue b/src/views/demo/fetch/components/DownLoad.vue similarity index 100% rename from src/views/plugin/fetch/components/DownLoad.vue rename to src/views/demo/fetch/components/DownLoad.vue diff --git a/src/views/plugin/fetch/components/DownLoadWithProgress.vue b/src/views/demo/fetch/components/DownLoadWithProgress.vue similarity index 100% rename from src/views/plugin/fetch/components/DownLoadWithProgress.vue rename to src/views/demo/fetch/components/DownLoadWithProgress.vue diff --git a/src/views/plugin/fetch/components/Env.vue b/src/views/demo/fetch/components/Env.vue similarity index 100% rename from src/views/plugin/fetch/components/Env.vue rename to src/views/demo/fetch/components/Env.vue diff --git a/src/views/plugin/fetch/components/FailedRequest.vue b/src/views/demo/fetch/components/FailedRequest.vue similarity index 100% rename from src/views/plugin/fetch/components/FailedRequest.vue rename to src/views/demo/fetch/components/FailedRequest.vue diff --git a/src/views/plugin/fetch/components/FailedResponse.vue b/src/views/demo/fetch/components/FailedResponse.vue similarity index 100% rename from src/views/plugin/fetch/components/FailedResponse.vue rename to src/views/demo/fetch/components/FailedResponse.vue diff --git a/src/views/plugin/fetch/components/FailedResponseWithoutTip.vue b/src/views/demo/fetch/components/FailedResponseWithoutTip.vue similarity index 100% rename from src/views/plugin/fetch/components/FailedResponseWithoutTip.vue rename to src/views/demo/fetch/components/FailedResponseWithoutTip.vue diff --git a/src/views/plugin/fetch/components/FormPost.vue b/src/views/demo/fetch/components/FormPost.vue similarity index 100% rename from src/views/plugin/fetch/components/FormPost.vue rename to src/views/demo/fetch/components/FormPost.vue diff --git a/src/views/plugin/fetch/components/Get.vue b/src/views/demo/fetch/components/Get.vue similarity index 100% rename from src/views/plugin/fetch/components/Get.vue rename to src/views/demo/fetch/components/Get.vue diff --git a/src/views/plugin/fetch/components/NoToken.vue b/src/views/demo/fetch/components/NoToken.vue similarity index 100% rename from src/views/plugin/fetch/components/NoToken.vue rename to src/views/demo/fetch/components/NoToken.vue diff --git a/src/views/plugin/fetch/components/Post.vue b/src/views/demo/fetch/components/Post.vue similarity index 100% rename from src/views/plugin/fetch/components/Post.vue rename to src/views/demo/fetch/components/Post.vue diff --git a/src/views/plugin/fetch/components/Put.vue b/src/views/demo/fetch/components/Put.vue similarity index 100% rename from src/views/plugin/fetch/components/Put.vue rename to src/views/demo/fetch/components/Put.vue diff --git a/src/views/plugin/fetch/components/RefreshToken.vue b/src/views/demo/fetch/components/RefreshToken.vue similarity index 100% rename from src/views/plugin/fetch/components/RefreshToken.vue rename to src/views/demo/fetch/components/RefreshToken.vue diff --git a/src/views/plugin/fetch/components/TokenExpiration.vue b/src/views/demo/fetch/components/TokenExpiration.vue similarity index 100% rename from src/views/plugin/fetch/components/TokenExpiration.vue rename to src/views/demo/fetch/components/TokenExpiration.vue diff --git a/src/views/plugin/fetch/components/Transform.vue b/src/views/demo/fetch/components/Transform.vue similarity index 100% rename from src/views/plugin/fetch/components/Transform.vue rename to src/views/demo/fetch/components/Transform.vue diff --git a/src/views/plugin/fetch/components/UseRequest.vue b/src/views/demo/fetch/components/UseRequest.vue similarity index 100% rename from src/views/plugin/fetch/components/UseRequest.vue rename to src/views/demo/fetch/components/UseRequest.vue diff --git a/src/views/plugin/fetch/index.vue b/src/views/demo/fetch/index.vue similarity index 100% rename from src/views/plugin/fetch/index.vue rename to src/views/demo/fetch/index.vue diff --git a/src/views/plugin/icons/index.vue b/src/views/demo/icons/index.vue similarity index 100% rename from src/views/plugin/icons/index.vue rename to src/views/demo/icons/index.vue diff --git a/src/views/plugin/map/components/AMap.vue b/src/views/demo/map/components/AMap.vue similarity index 100% rename from src/views/plugin/map/components/AMap.vue rename to src/views/demo/map/components/AMap.vue diff --git a/src/views/plugin/map/components/BMap.vue b/src/views/demo/map/components/BMap.vue similarity index 100% rename from src/views/plugin/map/components/BMap.vue rename to src/views/demo/map/components/BMap.vue diff --git a/src/views/plugin/map/index.vue b/src/views/demo/map/index.vue similarity index 100% rename from src/views/plugin/map/index.vue rename to src/views/demo/map/index.vue diff --git a/src/views/login/components/Login/index.vue b/src/views/login/components/Login/index.vue index 53cc8a9..b9276e2 100644 --- a/src/views/login/components/Login/index.vue +++ b/src/views/login/components/Login/index.vue @@ -10,18 +10,22 @@ const authStore = useAuthStore() function toOtherForm(type: any) { emit('update:modelValue', type) } -const rules = { - account: { - required: true, - trigger: 'blur', - message: '请输入账户', - }, - pwd: { - required: true, - trigger: 'blur', - message: '请输入密码', - }, -} + +const { t } = useI18n() +const rules = computed(() => { + return { + account: { + required: true, + trigger: 'blur', + message: t('login.accountRuleTip'), + }, + pwd: { + required: true, + trigger: 'blur', + message: t('login.passwordRuleTip'), + }, + } +}) const formValue = ref({ account: 'super', pwd: '123456', @@ -46,6 +50,9 @@ function handleLogin() { isLoading.value = false }) } +onMounted(() => { + checkUserAccount() +}) function checkUserAccount() { const loginAccount = local.get('loginAccount') if (!loginAccount) @@ -54,20 +61,19 @@ function checkUserAccount() { formValue.value = loginAccount isRemember.value = true } -checkUserAccount()