create-young-proj 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.mjs +42 -2702
- package/package.json +1 -1
- package/template-vue-admin/Dockerfile +2 -2
- package/template-vue-admin/build/custom-plugin.ts +30 -3
- package/template-vue-admin/package.json +30 -29
- package/template-vue-admin/plugins/{env.ts → init.ts} +6 -1
- package/template-vue-admin/src/apis/get.ts +1 -2
- package/template-vue-admin/src/apis/patch.ts +0 -1
- package/template-vue-admin/src/apis/post.ts +1 -2
- package/template-vue-admin/src/auto-components.d.ts +4 -2
- package/template-vue-admin/src/auto-imports.d.ts +21 -1
- package/template-vue-admin/src/main.ts +2 -0
- package/template-vue-admin/src/modules/1-router.ts +4 -22
- package/template-vue-admin/src/modules/3-net.ts +6 -2
- package/template-vue-admin/src/modules/4-auth.ts +16 -18
- package/template-vue-admin/src/modules/5-checkupdate.ts +38 -0
- package/template-vue-admin/src/stores/local/index.ts +9 -1
- package/template-vue-admin/src/typings/index.ts +1 -38
- package/template-vue-admin/src/typings/system.d.ts +46 -0
- package/template-vue-admin/src/views/403.vue +2 -1
- package/template-vue-admin/src/views/[...all_404].vue +3 -2
- package/template-vue-admin/src/views/base/login.vue +2 -1
- package/template-vue-admin/src/views/dashboard/[name].vue +7 -2
- package/template-vue-admin/src/views/index.vue +7 -1
- package/template-vue-admin/src/views/system/api.vue +0 -1
- package/template-vue-admin/src/views/system/menuList.vue +1 -2
- package/template-vue-admin/src/views/system/role.vue +0 -1
- package/template-vue-admin/src/views/system/user.vue +0 -1
package/package.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# 拉取基础镜像
|
2
|
-
FROM node:
|
2
|
+
FROM node:18-alpine as builder
|
3
3
|
|
4
4
|
# 维护者
|
5
5
|
MAINTAINER BluesYoung "bluesyoung_web@163.com"
|
@@ -23,7 +23,7 @@ COPY . /app
|
|
23
23
|
RUN yarn build
|
24
24
|
|
25
25
|
# 打包完成,构建最终的极简镜像
|
26
|
-
FROM node:
|
26
|
+
FROM node:18-alpine
|
27
27
|
|
28
28
|
# 工作目录
|
29
29
|
WORKDIR /app
|
@@ -1,14 +1,41 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2023-01-10 14:43:13
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 15:55:37
|
5
5
|
* @Description:
|
6
6
|
*/
|
7
7
|
import { networkInterfaces } from 'node:os';
|
8
8
|
|
9
|
+
function getLocalIP(): string | undefined {
|
10
|
+
const ips = networkInterfaces();
|
11
|
+
|
12
|
+
function isPrivateIP(ip: string) {
|
13
|
+
return (
|
14
|
+
/^192\.168\.\d{1,3}\.\d{1,3}$/.test(ip) ||
|
15
|
+
/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(ip) ||
|
16
|
+
/^172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}$/.test(ip)
|
17
|
+
);
|
18
|
+
}
|
19
|
+
|
20
|
+
for (const name of Object.keys(ips)) {
|
21
|
+
const networkInterface = ips[name];
|
22
|
+
|
23
|
+
for (const interfaceInfo of networkInterface) {
|
24
|
+
if (
|
25
|
+
interfaceInfo.family === 'IPv4' &&
|
26
|
+
!interfaceInfo.internal &&
|
27
|
+
isPrivateIP(interfaceInfo.address)
|
28
|
+
) {
|
29
|
+
return interfaceInfo.address;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
return '127.0.0.1';
|
35
|
+
}
|
36
|
+
|
9
37
|
const virtualModuleId = 'virtual:local-server';
|
10
|
-
const
|
11
|
-
export const localServer = `http://${ips['eth0'][0].address}:3000`;
|
38
|
+
export const localServer = `http://${getLocalIP()}:3000`;
|
12
39
|
|
13
40
|
/**
|
14
41
|
* 获取本机 ip 地址,拼接开发时的服务地址
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"name": "
|
2
|
+
"name": "music_admin",
|
3
3
|
"private": true,
|
4
4
|
"version": "0.0.0",
|
5
5
|
"type": "module",
|
@@ -8,43 +8,44 @@
|
|
8
8
|
"dev:server": "nitropack dev",
|
9
9
|
"build": "vite build && nitropack build",
|
10
10
|
"preview": "vite preview --host",
|
11
|
-
"format": "rome format
|
12
|
-
"release": "changelogen && bumpp --no-push"
|
11
|
+
"format": "rome format .* --write",
|
12
|
+
"release": "changelogen && bumpp --commit --tag --no-push"
|
13
13
|
},
|
14
14
|
"dependencies": {
|
15
|
-
"@bluesyoung/http": "0.1
|
16
|
-
"@bluesyoung/ui-vue3": "0.0
|
17
|
-
"@bluesyoung/ui-vue3-element-plus": "0.
|
18
|
-
"@bluesyoung/utils": "0.0
|
19
|
-
"@vueuse/core": "^
|
20
|
-
"core-js": "^3.
|
15
|
+
"@bluesyoung/http": "0.2.1",
|
16
|
+
"@bluesyoung/ui-vue3": "0.1.0",
|
17
|
+
"@bluesyoung/ui-vue3-element-plus": "0.9.2",
|
18
|
+
"@bluesyoung/utils": "0.1.0",
|
19
|
+
"@vueuse/core": "^10.1.2",
|
20
|
+
"core-js": "^3.30.2",
|
21
21
|
"element-plus": "^2.2.28",
|
22
22
|
"pinia": "^2.0.23",
|
23
23
|
"regenerator-runtime": "^0.13.10",
|
24
|
+
"sortablejs": "^1.15.0",
|
24
25
|
"vue": "^3.2.41",
|
25
26
|
"vue-router": "^4.1.6"
|
26
27
|
},
|
27
28
|
"devDependencies": {
|
28
|
-
"@iconify/json": "^2.2.
|
29
|
+
"@iconify/json": "^2.2.66",
|
29
30
|
"@types/node": "16",
|
30
|
-
"@unocss/reset": "^0.
|
31
|
-
"@vitejs/plugin-legacy": "^
|
32
|
-
"@vitejs/plugin-vue": "^4.
|
33
|
-
"@vitejs/plugin-vue-jsx": "^3.0.
|
34
|
-
"bumpp": "^
|
35
|
-
"c12": "^1.1
|
36
|
-
"changelogen": "^0.
|
31
|
+
"@unocss/reset": "^0.51.13",
|
32
|
+
"@vitejs/plugin-legacy": "^4.0.3",
|
33
|
+
"@vitejs/plugin-vue": "^4.2.3",
|
34
|
+
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
35
|
+
"bumpp": "^9.1.0",
|
36
|
+
"c12": "^1.4.1",
|
37
|
+
"changelogen": "^0.5.3",
|
37
38
|
"less": "^4.1.3",
|
38
|
-
"nitropack": "^
|
39
|
-
"rome": "^
|
40
|
-
"sass": "^1.
|
41
|
-
"terser": "^5.
|
42
|
-
"typescript": "^
|
43
|
-
"unocss": "^0.
|
44
|
-
"unplugin-auto-import": "^0.
|
45
|
-
"unplugin-vue-components": "^0.
|
46
|
-
"vite": "^4.
|
47
|
-
"vite-plugin-pages": "^0.
|
48
|
-
"vite-plugin-vue-layouts": "^0.
|
39
|
+
"nitropack": "^2.4.1",
|
40
|
+
"rome": "^12.1.1",
|
41
|
+
"sass": "^1.62.1",
|
42
|
+
"terser": "^5.17.4",
|
43
|
+
"typescript": "^5.0.4",
|
44
|
+
"unocss": "^0.51.13",
|
45
|
+
"unplugin-auto-import": "^0.16.0",
|
46
|
+
"unplugin-vue-components": "^0.24.1",
|
47
|
+
"vite": "^4.3.7",
|
48
|
+
"vite-plugin-pages": "^0.29.1",
|
49
|
+
"vite-plugin-vue-layouts": "^0.8.0"
|
49
50
|
}
|
50
|
-
}
|
51
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2023-01-04 18:53:23
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:10:14
|
5
5
|
* @Description: 在插件中读取环境变量,避免重复的文件 io
|
6
6
|
*/
|
7
7
|
import { resolve } from 'node:path';
|
@@ -12,6 +12,11 @@ export default defineNitroPlugin(async (app) => {
|
|
12
12
|
const { config } = await loadConfig({
|
13
13
|
name: env,
|
14
14
|
cwd: resolve(process.cwd(), 'config'),
|
15
|
+
defaultConfig: {
|
16
|
+
// 由于频繁修改 package.json 会浪费 docker 性能,故将版本信息放于此处
|
17
|
+
// 优先读取环境变量中的版本信息(自己打的 Tag)
|
18
|
+
VITE_CURRENT_VERSION: process.env.PROJECT_VERSION || '0.5.5',
|
19
|
+
},
|
15
20
|
});
|
16
21
|
|
17
22
|
for (const key in config) {
|
@@ -1,12 +1,11 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2023-01-04 19:31:22
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:07:52
|
5
5
|
* @Description:
|
6
6
|
*/
|
7
7
|
import { http } from '@/modules/3-net';
|
8
8
|
import { useNavStore } from '@/stores';
|
9
|
-
import { ApiItem } from '@/typings';
|
10
9
|
|
11
10
|
const method = 'GET';
|
12
11
|
|
@@ -1,12 +1,11 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2023-01-04 11:33:12
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:14:20
|
5
5
|
* @Description:
|
6
6
|
*/
|
7
7
|
import { http } from '@/modules/3-net';
|
8
8
|
import { useUserStore } from '@/stores';
|
9
|
-
import type { ApiItem, RoleItem, UserItem } from '@/typings';
|
10
9
|
|
11
10
|
export const usePostReq = () => ({
|
12
11
|
/**
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/* eslint-disable */
|
2
|
+
/* prettier-ignore */
|
3
|
+
// @ts-nocheck
|
4
|
+
// Generated by unplugin-vue-components
|
3
5
|
// Read more: https://github.com/vuejs/core/pull/3399
|
4
6
|
import '@vue/runtime-core'
|
5
7
|
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
/* eslint-disable */
|
2
|
+
/* prettier-ignore */
|
3
|
+
// @ts-nocheck
|
4
|
+
// Generated by unplugin-auto-import
|
2
5
|
export {}
|
3
6
|
declare global {
|
4
7
|
const EffectScope: typeof import('vue')['EffectScope']
|
@@ -21,7 +24,9 @@ declare global {
|
|
21
24
|
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
|
22
25
|
const createPinia: typeof import('pinia')['createPinia']
|
23
26
|
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
|
27
|
+
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
|
24
28
|
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
|
29
|
+
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
|
25
30
|
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
|
26
31
|
const customRef: typeof import('vue')['customRef']
|
27
32
|
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
|
@@ -114,10 +119,14 @@ declare global {
|
|
114
119
|
const unrefElement: typeof import('@vueuse/core')['unrefElement']
|
115
120
|
const until: typeof import('@vueuse/core')['until']
|
116
121
|
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
122
|
+
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
123
|
+
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
117
124
|
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
|
118
125
|
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
|
119
126
|
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
|
120
127
|
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
|
128
|
+
const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast']
|
129
|
+
const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes']
|
121
130
|
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
|
122
131
|
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
|
123
132
|
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
|
@@ -204,14 +213,18 @@ declare global {
|
|
204
213
|
const useOnline: typeof import('@vueuse/core')['useOnline']
|
205
214
|
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
|
206
215
|
const useParallax: typeof import('@vueuse/core')['useParallax']
|
216
|
+
const useParentElement: typeof import('@vueuse/core')['useParentElement']
|
217
|
+
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
|
207
218
|
const usePermission: typeof import('@vueuse/core')['usePermission']
|
208
219
|
const usePointer: typeof import('@vueuse/core')['usePointer']
|
220
|
+
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
|
209
221
|
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
|
210
222
|
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
|
211
223
|
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
|
212
224
|
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
|
213
225
|
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
|
214
226
|
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
|
227
|
+
const usePrevious: typeof import('@vueuse/core')['usePrevious']
|
215
228
|
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
216
229
|
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
217
230
|
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
@@ -269,8 +282,10 @@ declare global {
|
|
269
282
|
const watchArray: typeof import('@vueuse/core')['watchArray']
|
270
283
|
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
|
271
284
|
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
|
285
|
+
const watchDeep: typeof import('@vueuse/core')['watchDeep']
|
272
286
|
const watchEffect: typeof import('vue')['watchEffect']
|
273
287
|
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
|
288
|
+
const watchImmediate: typeof import('@vueuse/core')['watchImmediate']
|
274
289
|
const watchOnce: typeof import('@vueuse/core')['watchOnce']
|
275
290
|
const watchPausable: typeof import('@vueuse/core')['watchPausable']
|
276
291
|
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
@@ -280,3 +295,8 @@ declare global {
|
|
280
295
|
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
|
281
296
|
const whenever: typeof import('@vueuse/core')['whenever']
|
282
297
|
}
|
298
|
+
// for type re-export
|
299
|
+
declare global {
|
300
|
+
// @ts-ignore
|
301
|
+
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
|
302
|
+
}
|
@@ -15,6 +15,7 @@ import 'element-plus/dist/index.css';
|
|
15
15
|
import { createApp } from 'vue';
|
16
16
|
import { server } from 'virtual:local-server';
|
17
17
|
import App from './App.vue';
|
18
|
+
import { CurrentVersion } from './stores';
|
18
19
|
|
19
20
|
(async () => {
|
20
21
|
// 获取环境变量
|
@@ -33,6 +34,7 @@ import App from './App.vue';
|
|
33
34
|
console.log('🚀 ~ file: main.ts ~ line 28 ~ viteEnv', viteEnv);
|
34
35
|
}
|
35
36
|
window.__YOUNG_VITE_ENV__ = viteEnv;
|
37
|
+
CurrentVersion.value = viteEnv.VITE_CURRENT_VERSION;
|
36
38
|
|
37
39
|
const app = createApp(App);
|
38
40
|
Object.values(
|
@@ -1,10 +1,10 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2023-01-04 10:15:03
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 15:45:18
|
5
5
|
* @Description: 路由模块
|
6
6
|
*/
|
7
|
-
import { createRouter, createWebHashHistory
|
7
|
+
import { createRouter, createWebHashHistory } from 'vue-router';
|
8
8
|
import { setupLayouts } from 'virtual:generated-layouts';
|
9
9
|
import routes from '~pages';
|
10
10
|
|
@@ -26,9 +26,9 @@ declare module 'vue-router' {
|
|
26
26
|
*/
|
27
27
|
noCache?: boolean;
|
28
28
|
/**
|
29
|
-
*
|
29
|
+
* 设置 false 不参与鉴权,否则鉴权路径为当前路由
|
30
30
|
*/
|
31
|
-
|
31
|
+
auth?: false;
|
32
32
|
/**
|
33
33
|
* 页面布局,对应 layouts 目录下的布局页面,不写默认为 default/index
|
34
34
|
*/
|
@@ -37,24 +37,6 @@ declare module 'vue-router' {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
export const finalRoutes = setupLayouts(routes);
|
40
|
-
export const navMap = new Map<string, string>();
|
41
|
-
|
42
|
-
/**
|
43
|
-
* 生成权限节点映射表
|
44
|
-
*/
|
45
|
-
const generateNavMap = (raw: RouteRecordRaw[], base = '') => {
|
46
|
-
for (const route of raw) {
|
47
|
-
if (route.children) {
|
48
|
-
generateNavMap(route.children, route.path);
|
49
|
-
} else {
|
50
|
-
const meta = route.meta;
|
51
|
-
if (meta && meta.authPath) {
|
52
|
-
navMap.set(meta.authPath, `${base}${route.path.startsWith('/') ? '' : '/'}${route.path}`);
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
56
|
-
};
|
57
|
-
generateNavMap(finalRoutes);
|
58
40
|
|
59
41
|
export const router = createRouter({
|
60
42
|
history: createWebHashHistory(),
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2022-03-01 14:01:31
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:21:55
|
5
5
|
* @Description: 网络请求
|
6
6
|
*/
|
7
7
|
import { useHttp } from '@bluesyoung/http';
|
@@ -27,8 +27,12 @@ export const http = useHttp<ResponseMsg>({
|
|
27
27
|
start: startLoading,
|
28
28
|
end: endLoading,
|
29
29
|
},
|
30
|
-
fail: (err) => {
|
30
|
+
fail: (err: any) => {
|
31
31
|
console.log('🚀 ~ file: 3-net.ts:60 ~ err', err, typeof err);
|
32
|
+
if (err?.response?.status === 401) {
|
33
|
+
ElMessage.error('无权限,请联系管理员');
|
34
|
+
}
|
35
|
+
|
32
36
|
if (typeof err === 'string') {
|
33
37
|
// 通用失败,弹出提示信息
|
34
38
|
ElMessage.error(err);
|
@@ -1,12 +1,12 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2022-03-01 19:40:13
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:17:02
|
5
5
|
* @Description: 权限校验
|
6
6
|
*/
|
7
7
|
import { router } from './1-router';
|
8
8
|
import type { RouteLocationNormalized } from 'vue-router';
|
9
|
-
import { useNavStore, useTagsStore, useUserStore, getToken } from '@/stores';
|
9
|
+
import { useNavStore, useTagsStore, useUserStore, getToken, getLoginInfo } from '@/stores';
|
10
10
|
import { apis } from './3-net';
|
11
11
|
|
12
12
|
const changeTitle = (route: RouteLocationNormalized) => {
|
@@ -49,17 +49,24 @@ export const clearChildren = <T extends Record<string, any>>(arr: T[]) => {
|
|
49
49
|
return arr;
|
50
50
|
};
|
51
51
|
|
52
|
-
export const generateNavData = async () => {
|
53
|
-
const info =
|
52
|
+
export const generateNavData = async (force = false) => {
|
53
|
+
const info = getLoginInfo();
|
54
54
|
|
55
55
|
if (!info) {
|
56
|
+
// 登录过期
|
57
|
+
ElMessage.error('登录过期,请重新登录!');
|
58
|
+
router.replace('/base/login');
|
56
59
|
return;
|
57
60
|
}
|
58
61
|
|
59
|
-
const menu = Object.values(await apis.get.getMenuTree());
|
60
|
-
CurrUserInfo.value = info;
|
62
|
+
const menu = Object.values(await apis.get.getMenuTree(force)) as any[];
|
61
63
|
RawNav.value = menu;
|
62
64
|
|
65
|
+
// 刷新右上角角色信息
|
66
|
+
apis.post.getCurrUserInfo().then((res) => {
|
67
|
+
CurrUserInfo.value = res;
|
68
|
+
});
|
69
|
+
|
63
70
|
// 后端获取用户可见节点
|
64
71
|
const navArr: NavArrItem[] = menu;
|
65
72
|
const routes: string[] = generateRoleRoute(menu, 1);
|
@@ -78,29 +85,20 @@ export const hasPermission = (path: string) => {
|
|
78
85
|
|
79
86
|
export const install: UserModule = (app) => {
|
80
87
|
router.beforeEach(async (to, from) => {
|
81
|
-
/* 授权登录,暂未启用
|
82
|
-
const { code, state } = Object.fromEntries(new URLSearchParams(location.search));
|
83
|
-
if (code && state) {
|
84
|
-
(await casdoorLogin(code, state)) as UserKey;
|
85
|
-
getToken() && (await generateNavData());
|
86
|
-
location.search = '';
|
87
|
-
return true;
|
88
|
-
} else
|
89
|
-
*/
|
90
88
|
if (to.path !== '/base/login') {
|
91
89
|
// 页面无需权限
|
92
|
-
if (
|
90
|
+
if (to.meta.auth === false) {
|
93
91
|
return true;
|
94
92
|
}
|
95
93
|
// 已登录
|
96
94
|
if (getToken()) {
|
97
95
|
// 生成权限树
|
98
96
|
await generateNavData();
|
99
|
-
if (hasPermission(to.
|
97
|
+
if (hasPermission(to.path)) {
|
100
98
|
// 拥有对应页面的权限
|
101
99
|
return true;
|
102
100
|
}
|
103
|
-
if (!hasPermission(to.
|
101
|
+
if (!hasPermission(to.path)) {
|
104
102
|
// 已登录,并且无权限
|
105
103
|
return '/403';
|
106
104
|
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
/*
|
2
|
+
* @Author: zhangyang
|
3
|
+
* @Date: 2023-03-02 16:50:48
|
4
|
+
* @LastEditTime: 2023-03-24 10:35:36
|
5
|
+
* @Description: 检查更新
|
6
|
+
*/
|
7
|
+
import { CurrentVersion } from '@/stores';
|
8
|
+
import { sleep } from '@bluesyoung/utils';
|
9
|
+
import { server } from 'virtual:local-server';
|
10
|
+
import { generateNavData } from './4-auth';
|
11
|
+
|
12
|
+
export const install: UserModule = (app) => {
|
13
|
+
let viteEnv: ImportMetaEnv;
|
14
|
+
// 每分钟一次,检查更新
|
15
|
+
setInterval(async () => {
|
16
|
+
if (import.meta.env.DEV) {
|
17
|
+
// 开发环境,局域网 ip
|
18
|
+
viteEnv = await (await fetch(server + '/get/env')).json(); // console.log('🚀 ~ file: 5-checkupdate.ts:187~ setInterval ~ viteEnv:"' viteEnv)
|
19
|
+
} else {
|
20
|
+
// 部署环境
|
21
|
+
viteEnv = await (await fetch(location.origin + location.pathname + `get/env`)).json();
|
22
|
+
// console.log('🚀 ~ file: 5-checkupdate.ts:231~ setInterval ~ viteEnv:', viteEnv);
|
23
|
+
}
|
24
|
+
|
25
|
+
const refresh = async () => {
|
26
|
+
await generateNavData(true);
|
27
|
+
await sleep(0.5);
|
28
|
+
location.reload();
|
29
|
+
};
|
30
|
+
|
31
|
+
if (viteEnv.VITE_CURRENT_VERSION !== CurrentVersion.value) {
|
32
|
+
setTimeout(refresh, 3e4);
|
33
|
+
ElMessageBox.alert('新版本已发布,点击立即重新加载(30s后自动刷新)', '温馨提示', {
|
34
|
+
type: 'warning',
|
35
|
+
}).then(() => refresh());
|
36
|
+
}
|
37
|
+
}, 6e4);
|
38
|
+
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2022-10-20 08:52:37
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:00:10
|
5
5
|
* @Description:
|
6
6
|
*/
|
7
7
|
import { YoungLocalStorage } from '@bluesyoung/utils';
|
@@ -10,6 +10,10 @@ export const YoungStorage = new YoungLocalStorage();
|
|
10
10
|
|
11
11
|
const TOKEN_KEY = 'bluesyoung-web.com/music/admin';
|
12
12
|
|
13
|
+
export const SaveFlag = useLocalStorage('n天免登', true);
|
14
|
+
|
15
|
+
export const CurrentVersion = useLocalStorage('当前版本', '');
|
16
|
+
|
13
17
|
export const getToken = () => {
|
14
18
|
return YoungStorage.get<UserKey>(TOKEN_KEY)?.token;
|
15
19
|
};
|
@@ -21,3 +25,7 @@ export const setToken = (data: UserKey) => {
|
|
21
25
|
export const removeToken = () => {
|
22
26
|
return YoungStorage.remove(TOKEN_KEY);
|
23
27
|
};
|
28
|
+
|
29
|
+
export const getLoginInfo = () => {
|
30
|
+
return YoungStorage.get<UserKey>(TOKEN_KEY);
|
31
|
+
};
|
@@ -1,35 +1,9 @@
|
|
1
1
|
/*
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2022-03-01 14:03:04
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 16:05:43
|
5
5
|
* @Description: 部分类型定义
|
6
6
|
*/
|
7
|
-
export type UserItem = {
|
8
|
-
id: number;
|
9
|
-
username: string;
|
10
|
-
nickname: string;
|
11
|
-
mobile: string;
|
12
|
-
roleId: number;
|
13
|
-
status: number;
|
14
|
-
role_name?: string;
|
15
|
-
creator?: string;
|
16
|
-
newPassword?: string;
|
17
|
-
initPassword?: string;
|
18
|
-
};
|
19
|
-
|
20
|
-
export type RoleItem = {
|
21
|
-
createdAt?: string;
|
22
|
-
creator?: string;
|
23
|
-
desc: string;
|
24
|
-
id: number;
|
25
|
-
keyword: string;
|
26
|
-
name: string;
|
27
|
-
not_dev?: number;
|
28
|
-
sort?: number;
|
29
|
-
status: number;
|
30
|
-
updatedAt?: string;
|
31
|
-
};
|
32
|
-
|
33
7
|
export const MethodObj = {
|
34
8
|
GET: 'info',
|
35
9
|
POST: 'success',
|
@@ -37,14 +11,3 @@ export const MethodObj = {
|
|
37
11
|
PUT: '',
|
38
12
|
DELETE: 'danger',
|
39
13
|
} as const;
|
40
|
-
|
41
|
-
export type ApiItem = {
|
42
|
-
id: number;
|
43
|
-
path: string;
|
44
|
-
desc: string;
|
45
|
-
category: string;
|
46
|
-
method: keyof typeof MethodObj;
|
47
|
-
roleIds: number[];
|
48
|
-
creator?: string;
|
49
|
-
title?: string;
|
50
|
-
};
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* @Author: zhangyang
|
3
|
+
* @Date: 2023-05-18 16:06:06
|
4
|
+
* @LastEditTime: 2023-05-18 16:06:07
|
5
|
+
* @Description:
|
6
|
+
*/
|
7
|
+
import { MethodObj } from '.';
|
8
|
+
|
9
|
+
declare global {
|
10
|
+
type UserItem = {
|
11
|
+
id: number;
|
12
|
+
username: string;
|
13
|
+
nickname: string;
|
14
|
+
mobile: string;
|
15
|
+
roleId: number;
|
16
|
+
status: number;
|
17
|
+
role_name?: string;
|
18
|
+
creator?: string;
|
19
|
+
newPassword?: string;
|
20
|
+
initPassword?: string;
|
21
|
+
};
|
22
|
+
|
23
|
+
type RoleItem = {
|
24
|
+
createdAt?: string;
|
25
|
+
creator?: string;
|
26
|
+
desc: string;
|
27
|
+
id: number;
|
28
|
+
keyword: string;
|
29
|
+
name: string;
|
30
|
+
not_dev?: number;
|
31
|
+
sort?: number;
|
32
|
+
status: number;
|
33
|
+
updatedAt?: string;
|
34
|
+
};
|
35
|
+
|
36
|
+
type ApiItem = {
|
37
|
+
id: number;
|
38
|
+
path: string;
|
39
|
+
desc: string;
|
40
|
+
category: string;
|
41
|
+
method: keyof typeof MethodObj;
|
42
|
+
roleIds: number[];
|
43
|
+
creator?: string;
|
44
|
+
title?: string;
|
45
|
+
};
|
46
|
+
}
|
@@ -1,12 +1,13 @@
|
|
1
1
|
<!--
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2022-10-27 11:32:57
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 15:49:39
|
5
5
|
* @Description:
|
6
6
|
-->
|
7
7
|
<route lang="yaml">
|
8
8
|
meta:
|
9
9
|
title: 403
|
10
|
+
auth: false
|
10
11
|
</route>
|
11
12
|
|
12
13
|
<script lang="ts" setup>
|
@@ -1,18 +1,19 @@
|
|
1
1
|
<!--
|
2
2
|
* @Author: zhangyang
|
3
3
|
* @Date: 2020-12-03 15:02:28
|
4
|
-
* @LastEditTime: 2023-
|
4
|
+
* @LastEditTime: 2023-05-18 15:49:25
|
5
5
|
* @Description: 404
|
6
6
|
-->
|
7
7
|
<route lang="yaml">
|
8
8
|
meta:
|
9
9
|
title: 页面不存在
|
10
10
|
layout: 'blank'
|
11
|
+
auth: false
|
11
12
|
</route>
|
12
13
|
<template>
|
13
14
|
<div>
|
14
15
|
<div class="g-container">
|
15
|
-
<div class="rail">
|
16
|
+
<div class="rail pointer-events-none">
|
16
17
|
<div class="stamp four">4</div>
|
17
18
|
<div class="stamp zero">0</div>
|
18
19
|
<div class="stamp four">4</div>
|