zant-admin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.en.md +36 -0
  2. package/README.md +248 -0
  3. package/SCAFFOLD_README.md +215 -0
  4. package/bin/cli.js +99 -0
  5. package/bin/generator.js +503 -0
  6. package/bin/prompts.js +159 -0
  7. package/bin/utils.js +134 -0
  8. package/package.json +74 -0
  9. package/public/logo.png +0 -0
  10. package/src/App.vue +16 -0
  11. package/src/api/methods/logError.js +8 -0
  12. package/src/api/methods/logOperation.js +8 -0
  13. package/src/api/methods/login.js +6 -0
  14. package/src/api/methods/quartz.js +36 -0
  15. package/src/api/methods/region.js +16 -0
  16. package/src/api/methods/sysAccount.js +30 -0
  17. package/src/api/methods/sysDict.js +29 -0
  18. package/src/api/methods/sysDictItem.js +26 -0
  19. package/src/api/methods/sysMenu.js +42 -0
  20. package/src/api/methods/sysRole.js +35 -0
  21. package/src/api/methods/sysUser.js +25 -0
  22. package/src/api/methods/system.js +16 -0
  23. package/src/api/request.js +225 -0
  24. package/src/assets/css/style.css +70 -0
  25. package/src/assets/css/zcui.css +340 -0
  26. package/src/assets/imgs/loginbackground.svg +69 -0
  27. package/src/assets/imgs/logo.png +0 -0
  28. package/src/assets/imgs/md/1.png +0 -0
  29. package/src/assets/imgs/md/10.png +0 -0
  30. package/src/assets/imgs/md/11.png +0 -0
  31. package/src/assets/imgs/md/2.png +0 -0
  32. package/src/assets/imgs/md/3.png +0 -0
  33. package/src/assets/imgs/md/4.png +0 -0
  34. package/src/assets/imgs/md/5.png +0 -0
  35. package/src/assets/imgs/md/6.png +0 -0
  36. package/src/assets/imgs/md/7.png +0 -0
  37. package/src/assets/imgs/md/8.png +0 -0
  38. package/src/assets/imgs/md/9.png +0 -0
  39. package/src/components/FormTable.vue +875 -0
  40. package/src/components/IconPicker.vue +344 -0
  41. package/src/components/MainPage.vue +957 -0
  42. package/src/components/details/logErrorDetails.vue +58 -0
  43. package/src/components/details/logOperationDetails.vue +76 -0
  44. package/src/components/edit/QuartzEdit.vue +221 -0
  45. package/src/components/edit/SysAccountEdit.vue +178 -0
  46. package/src/components/edit/SysDictEdit.vue +114 -0
  47. package/src/components/edit/SysDictItemEdit.vue +134 -0
  48. package/src/components/edit/SysRoleEdit.vue +109 -0
  49. package/src/components/edit/sysMenuEdit.vue +305 -0
  50. package/src/config/index.js +74 -0
  51. package/src/directives/permission.js +45 -0
  52. package/src/main.js +38 -0
  53. package/src/router/index.js +270 -0
  54. package/src/stores/config.js +37 -0
  55. package/src/stores/dict.js +33 -0
  56. package/src/stores/menu.js +57 -0
  57. package/src/stores/user.js +21 -0
  58. package/src/utils/baseEcharts.js +661 -0
  59. package/src/utils/dictTemplate.js +26 -0
  60. package/src/utils/regionUtils.js +169 -0
  61. package/src/utils/useFormCRUD.js +60 -0
  62. package/src/views/baiscstatis/center.vue +463 -0
  63. package/src/views/baiscstatis/iframePage.vue +31 -0
  64. package/src/views/baiscstatis/notFound.vue +192 -0
  65. package/src/views/console.vue +771 -0
  66. package/src/views/demo/importexport.vue +123 -0
  67. package/src/views/demo/region.vue +240 -0
  68. package/src/views/demo/statistics.vue +195 -0
  69. package/src/views/home.vue +7 -0
  70. package/src/views/login.vue +272 -0
  71. package/src/views/operations/log/logError.vue +78 -0
  72. package/src/views/operations/log/logLogin.vue +66 -0
  73. package/src/views/operations/log/logOperation.vue +103 -0
  74. package/src/views/operations/log/logQuartz.vue +57 -0
  75. package/src/views/operations/quartz.vue +181 -0
  76. package/src/views/operations/serviceMonitoring.vue +134 -0
  77. package/src/views/system/sysAccount.vue +123 -0
  78. package/src/views/system/sysDict.vue +156 -0
  79. package/src/views/system/sysDictItem.vue +118 -0
  80. package/src/views/system/sysMenu.vue +223 -0
  81. package/src/views/system/sysRole.vue +184 -0
  82. package/templates/env.production +2 -0
@@ -0,0 +1,270 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+ import home from '../views/home.vue'
3
+ import { useUserStore } from '@/stores/user'
4
+ import sysMenu from '@/api/methods/sysMenu'
5
+ import { menuStore } from '@/stores/menu'
6
+ import { configStore } from '@/stores/config'
7
+ // 定义不需要 token 的路由白名单
8
+ //const publicRoutes = ['/login', '/Userreport', '/deviceError']
9
+ const publicRoutes = []
10
+
11
+ // 静态路由
12
+ const routes = [
13
+ {
14
+ path: '/login',
15
+ component: () => import('../views/login.vue'),
16
+ meta: { title: '登录', cache: false },
17
+ },
18
+ {
19
+ path: '/',
20
+ component: home,
21
+ children: [
22
+ {
23
+ path: '',
24
+ name: 'home',
25
+ meta: { title: '', cache: true },
26
+ component: () => import('../views/console.vue'), // 默认主页
27
+ },
28
+ {
29
+ path: 'console',
30
+ name: 'console',
31
+ meta: { title: '主页', cache: true },
32
+ component: () => import('../views/console.vue'),
33
+ },
34
+ {
35
+ path: 'center',
36
+ name: 'center',
37
+ meta: { title: '个人中心', cache: true },
38
+ component: () => import('../views/baiscstatis/center.vue'),
39
+ },
40
+
41
+
42
+ {
43
+ path: 'iframePage',
44
+ meta: { cache: false },
45
+ component: () => import('../views/baiscstatis/iframePage.vue'),
46
+ },
47
+ {
48
+ path: 'notFound',
49
+ component: () => import('../views/baiscstatis/notFound.vue'),
50
+ },
51
+ ],
52
+ },
53
+ ]
54
+ const router = createRouter({
55
+ history: createWebHistory(import.meta.env.BASE_URL),
56
+ routes,
57
+ })
58
+
59
+ // 动态导入所有视图组件
60
+ const modules = import.meta.glob('@/views/**/*.vue')
61
+
62
+ // 标记动态路由加载状态
63
+ let hasAddRoutes = false
64
+ let routeLoadFailed = false
65
+
66
+ // 组件加载器,带有错误处理
67
+ const loadComponent = (path) => {
68
+ const possiblePaths = [
69
+ `/src/views${path}.vue`,
70
+ `./views${path}.vue`,
71
+ `../views${path}.vue`,
72
+ `@/views${path}.vue`,
73
+ ]
74
+
75
+ for (const tryPath of possiblePaths) {
76
+ if (modules[tryPath]) {
77
+ return modules[tryPath]
78
+ }
79
+ }
80
+
81
+ return () => import('../views/baiscstatis/notFound.vue')
82
+ }
83
+
84
+ async function loadDynamicRoutes() {
85
+ try {
86
+ const menu = menuStore()
87
+ const res = await sysMenu.getRoutesMenu()
88
+ const resbtn = await sysMenu.getMenuBtn()
89
+ const dynamicRoutes = res.data || []
90
+ const dynamicBtns = resbtn.data || []
91
+ menu.setMenus(dynamicRoutes)
92
+ menu.setPermissions(dynamicBtns)
93
+ dynamicRoutes.forEach((route) => {
94
+ if (route.type === 1) {
95
+ // 目录类型
96
+ const parentRoute = {
97
+ path: route.path,
98
+ component: home,
99
+ // meta: { title: route.title },
100
+ // children: [],
101
+ }
102
+ const addRoutes = (parentRoute, children) => {
103
+ if (children && children.length > 0) {
104
+ parentRoute.children = children.map(child => {
105
+ const childRoute = {
106
+ path: child.path,
107
+ meta: { title: child.title },
108
+ name: child.path.replace(/\//g, '-').substring(1),
109
+ meta: { cache: child.cache,fullPath: child.path, },
110
+ }
111
+ if(child.type!=1){
112
+ childRoute.component = loadComponent(child.path)
113
+ }
114
+ // 递归处理多级子路由
115
+ if (child.children) {
116
+ addRoutes(childRoute, child.children)
117
+ }
118
+ return childRoute
119
+ })
120
+ }
121
+ }
122
+ addRoutes(parentRoute, route.children)
123
+ router.addRoute(parentRoute)
124
+ } else {
125
+ // 页面类型
126
+ const pageRoute = {
127
+ path: route.path,
128
+ name: route.path.replace(/\//g, '-').substring(1),
129
+ component: loadComponent(route.path),
130
+ meta: {
131
+ title: route.title,
132
+ cache: route.cache,
133
+ },
134
+ }
135
+
136
+ router.addRoute(pageRoute)
137
+ }
138
+ })
139
+ hasAddRoutes = true
140
+ } catch (error) {
141
+ console.error('❌ 动态路由加载失败:', error)
142
+ routeLoadFailed = true
143
+ // 如果是401错误(令牌过期),清除用户信息并跳转到登录页
144
+ if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
145
+ const user = useUserStore()
146
+ user.clearUserInfo()
147
+ router.push('/login')
148
+ }
149
+ throw error
150
+ }
151
+ }
152
+
153
+ // 全局前置守卫
154
+ router.beforeEach(async (to, from, next) => {
155
+ // document.title = to.meta.title || 'ZCloudVue'
156
+ // document.title = 'ZCloudVue'
157
+ const config = configStore()
158
+ document.title = config.projectName
159
+ const user = useUserStore()
160
+
161
+ // 如果目标路由在白名单中,直接放行
162
+ if (publicRoutes.includes(to.path)) {
163
+ next()
164
+ return
165
+ }
166
+
167
+ if (!user.token && to.path !== '/login') {
168
+ next('/login')
169
+ return
170
+ }
171
+
172
+ // 动态路由加载
173
+ if (user.token && !hasAddRoutes && !routeLoadFailed) {
174
+ try {
175
+ await loadDynamicRoutes()
176
+
177
+ // 检查是否有持久化的路由状态需要恢复
178
+ const menu = menuStore()
179
+ if (menu.selectmenuKey && menu.selectmenuKey.length > 0 && to.path === '/console') {
180
+ // 如果当前是跳转到首页,但有持久化的选中菜单,尝试恢复路由
181
+ const selectedMenu = menu.tagmenus.find(tag => tag.key === menu.selectmenuKey[0])
182
+ if (selectedMenu && selectedMenu.path && selectedMenu.path !== '/console') {
183
+ // 检查路由是否存在
184
+ const routeExists = router.getRoutes().some((r) => r.path === selectedMenu.path)
185
+ if (routeExists) {
186
+ next({ path: selectedMenu.path, replace: true })
187
+ return
188
+ }
189
+ }
190
+ }
191
+
192
+ next({ ...to, replace: true })
193
+ } catch (error) {
194
+ // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
195
+ if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
196
+ return
197
+ }
198
+ // 其他错误跳转到404页面
199
+ next('/notFound')
200
+ }
201
+ return
202
+ }
203
+
204
+ // 如果接口已经失败过,避免死循环
205
+ if (user.token && routeLoadFailed && !hasAddRoutes) {
206
+ if (to.path !== '/notFound') {
207
+ next('/notFound')
208
+ return
209
+ }
210
+ }
211
+
212
+ // 根路径重定向
213
+ if (to.path === '/') {
214
+ next('/console')
215
+ return
216
+ }
217
+
218
+ // 路由存在性检查
219
+ const routeExists = router.getRoutes().some((r) => r.path === to.path)
220
+ if (!routeExists && !publicRoutes.includes(to.path)) {
221
+ // 如果路由不存在且不在白名单中,检查是否是动态路由还未加载
222
+ if (user.token && !hasAddRoutes && !routeLoadFailed) {
223
+ // 动态路由还未加载,等待加载完成
224
+ try {
225
+ await loadDynamicRoutes()
226
+ next({ ...to, replace: true })
227
+ return
228
+ } catch (error) {
229
+ // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
230
+ if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
231
+ return
232
+ }
233
+ // 其他错误跳转到404页面
234
+ next('/notFound')
235
+ return
236
+ }
237
+ }
238
+ // 如果动态路由已加载但路由仍不存在,跳转到404
239
+ next('/notFound')
240
+ return
241
+ }
242
+
243
+ next()
244
+ })
245
+
246
+ router.onError((error) => {
247
+ console.error('🚨 路由错误:', error)
248
+ })
249
+
250
+ export async function refreshRoutes() {
251
+ hasAddRoutes = false
252
+ routeLoadFailed = false
253
+ // 清空旧的菜单,避免重复
254
+ const menu = menuStore()
255
+ menu.setMenus([])
256
+ menu.setPermissions([])
257
+ // 移除之前添加的动态路由
258
+ const routes = router.getRoutes()
259
+ routes.forEach(route => {
260
+ // 只移除动态添加的路由,保留静态路由
261
+ if (route.path && !['/login', '/', '/console', '/notFound', '/center'].includes(route.path)) {
262
+ router.removeRoute(route.name)
263
+ }
264
+ })
265
+
266
+ // 重新加载动态路由
267
+ await loadDynamicRoutes()
268
+ }
269
+
270
+ export default router
@@ -0,0 +1,37 @@
1
+ import { defineStore } from 'pinia'
2
+ import dayjs from 'dayjs'
3
+ import zhCN from 'ant-design-vue/es/locale/zh_CN'
4
+ import enUS from 'ant-design-vue/es/locale/en_US'
5
+ import 'dayjs/locale/zh-cn' // 中文
6
+ import 'dayjs/locale/en' // 英文
7
+ import { appConfig } from '@/config' // 导入全局配置
8
+
9
+ export const configStore = defineStore({
10
+ id: 'CONFIG',
11
+ state: () => ({
12
+ themeClass: appConfig.defaultTheme,
13
+ navigationMode: appConfig.defaultNavigationMode,
14
+ tableSize: appConfig.defaultTableSize,
15
+ tableBordered: appConfig.defaultTableBordered,
16
+ locale: zhCN,
17
+ dayjsLocale: appConfig.defaultLanguage,
18
+ projectName: appConfig.title, // 使用全局配置中的项目名称
19
+ }),
20
+ actions: {
21
+ setLocale(locale) {
22
+ this.locale = locale
23
+ this.dayjsLocale = locale === zhCN ? 'zh-cn' : 'en'
24
+ dayjs.locale(this.dayjsLocale)
25
+ },
26
+ },
27
+ persist: {
28
+ enabled: true,
29
+ strategies: [
30
+ {
31
+ key: 'CONFIG',
32
+ storage: localStorage,
33
+ paths: ['themeClass','navigationMode', 'tableSize', 'tableBordered', 'locale'],
34
+ },
35
+ ],
36
+ },
37
+ })
@@ -0,0 +1,33 @@
1
+ import { defineStore } from 'pinia'
2
+ import sysDict from '@/api/methods/sysDict'
3
+ export const dictStore = defineStore({
4
+ id: 'SYS_DICT',
5
+ state: () => ({
6
+ items: {},
7
+ }),
8
+ actions: {
9
+ initDictList() {
10
+ sysDict
11
+ .getDictList()
12
+ .then(res => {
13
+ res.data.forEach(item => {
14
+ this.items[item.type] = item.sysDictItem
15
+ })
16
+ })
17
+ .catch()
18
+ },
19
+ getDictItems(type) {
20
+ return this.items[type]
21
+ },
22
+ },
23
+ persist: {
24
+ enabled: true,
25
+ strategies: [
26
+ {
27
+ key: 'SYS_DICT',
28
+ storage: localStorage,
29
+ paths: ['items'],
30
+ },
31
+ ],
32
+ },
33
+ })
@@ -0,0 +1,57 @@
1
+ import { defineStore } from 'pinia'
2
+
3
+ export const menuStore = defineStore({
4
+ id: 'MENU_RESULT',
5
+ state: () => {
6
+ return {
7
+ openmenuKey: [],
8
+ selectmenuKey: [],
9
+ tagmenus: [
10
+ {
11
+ key: 0,
12
+ parentId: '0',
13
+ title: `控制台`,
14
+ closable: false,
15
+ path: '/console',
16
+ },
17
+ ],
18
+ menus: [],
19
+ permissions: []
20
+ }
21
+ },
22
+ actions: {
23
+ setSelectmenuKey(keys) {
24
+ this.selectmenuKey = keys
25
+ },
26
+ setOpenmenuKey(keys) {
27
+ this.openmenuKey = keys
28
+ },
29
+ setMenus(menus) { this.menus = menus },
30
+ setPermissions(permissions) { this.permissions = permissions },
31
+ // 检查是否有指定权限
32
+ hasPermission(permission) {
33
+ if (!permission) return true
34
+ return this.permissions.includes(permission)
35
+ },
36
+ // 检查是否有多个权限中的任意一个
37
+ hasAnyPermission(permissions) {
38
+ if (!permissions || !Array.isArray(permissions) || permissions.length === 0) return true
39
+ return permissions.some(permission => this.permissions.includes(permission))
40
+ },
41
+ // 检查是否拥有所有权限
42
+ hasAllPermissions(permissions) {
43
+ if (!permissions || !Array.isArray(permissions) || permissions.length === 0) return true
44
+ return permissions.every(permission => this.permissions.includes(permission))
45
+ },
46
+ },
47
+ persist: {
48
+ enabled: true,
49
+ strategies: [
50
+ {
51
+ key: 'MENU_RESULT',
52
+ storage: localStorage,
53
+ paths: ['menus', 'openmenuKey', 'selectmenuKey', 'tagmenus', 'permissions'],
54
+ },
55
+ ],
56
+ },
57
+ })
@@ -0,0 +1,21 @@
1
+ import { defineStore } from 'pinia'
2
+ export const useUserStore = defineStore({
3
+ id: 'TOKEN_USER_INFO',
4
+ state: () => {
5
+ return {
6
+ token: '',
7
+ userInfo: {},
8
+ }
9
+ },
10
+ actions: {
11
+
12
+ },
13
+ persist: {
14
+ enabled: true,
15
+ strategies: [{
16
+ key: 'TOKEN_USER_INFO',
17
+ storage: localStorage,
18
+ paths: ['token', 'userInfo' ],
19
+ }]
20
+ }
21
+ })