zant-admin 1.0.1 → 2.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +414 -25
  3. package/README.md +426 -277
  4. package/bin/cli.js +99 -99
  5. package/bin/generator.js +502 -502
  6. package/bin/prompts.js +158 -158
  7. package/bin/utils.js +133 -133
  8. package/package.json +3 -3
  9. package/public/logo.png +0 -0
  10. package/src/App.vue +1 -1
  11. package/src/api/methods/sysAccount.js +0 -1
  12. package/src/api/methods/sysDictItem.js +3 -3
  13. package/src/api/methods/system.js +10 -11
  14. package/src/api/request.js +39 -39
  15. package/src/assets/css/style.css +0 -11
  16. package/src/assets/css/zcui.css +1002 -319
  17. package/src/assets/imgs/logo.png +0 -0
  18. package/src/assets/imgs/md/console.png +0 -0
  19. package/src/assets/imgs/md/login.png +0 -0
  20. package/src/assets/imgs/md/menu.png +0 -0
  21. package/src/assets/imgs/md/serviceMonitoring.png +0 -0
  22. package/src/assets/imgs/md/statistics.png +0 -0
  23. package/src/components/FormTable.vue +50 -37
  24. package/src/components/IconPicker.vue +351 -344
  25. package/src/components/MainPage.vue +220 -339
  26. package/src/components/edit/QuartzEdit.vue +1 -1
  27. package/src/components/edit/SysAccountEdit.vue +15 -8
  28. package/src/components/edit/SysDictEdit.vue +6 -4
  29. package/src/components/edit/SysDictItemEdit.vue +8 -6
  30. package/src/components/edit/SysRoleEdit.vue +5 -3
  31. package/src/components/edit/sysMenuEdit.vue +10 -25
  32. package/src/config/index.js +74 -74
  33. package/src/directives/permission.js +49 -45
  34. package/src/main.js +2 -3
  35. package/src/router/index.js +48 -30
  36. package/src/stores/config.js +7 -1
  37. package/src/stores/menu.js +32 -8
  38. package/src/stores/user.js +17 -17
  39. package/src/utils/regionUtils.js +20 -16
  40. package/src/utils/useFormCRUD.js +59 -60
  41. package/src/views/baiscstatis/center.vue +53 -42
  42. package/src/views/baiscstatis/iframePage.vue +9 -11
  43. package/src/views/console.vue +92 -42
  44. package/src/views/demo/button.vue +269 -0
  45. package/src/views/demo/importexport.vue +8 -12
  46. package/src/views/demo/region.vue +103 -21
  47. package/src/views/demo/statistics.vue +38 -19
  48. package/src/views/home.vue +2 -3
  49. package/src/views/login.vue +254 -149
  50. package/src/views/operations/log/logQuartz.vue +0 -1
  51. package/src/views/operations/quartz.vue +22 -24
  52. package/src/views/system/sysAccount.vue +16 -11
  53. package/src/views/system/sysDict.vue +9 -6
  54. package/src/views/system/sysMenu.vue +17 -15
  55. package/src/views/system/sysRole.vue +44 -21
  56. package/SCAFFOLD_README.md +0 -215
  57. package/src/assets/imgs/md/1.png +0 -0
  58. package/src/assets/imgs/md/10.png +0 -0
  59. package/src/assets/imgs/md/11.png +0 -0
  60. package/src/assets/imgs/md/2.png +0 -0
  61. package/src/assets/imgs/md/3.png +0 -0
  62. package/src/assets/imgs/md/4.png +0 -0
  63. package/src/assets/imgs/md/5.png +0 -0
  64. package/src/assets/imgs/md/6.png +0 -0
  65. package/src/assets/imgs/md/7.png +0 -0
  66. package/src/assets/imgs/md/8.png +0 -0
  67. package/src/assets/imgs/md/9.png +0 -0
@@ -31,14 +31,13 @@ const routes = [
31
31
  meta: { title: '主页', cache: true },
32
32
  component: () => import('../views/console.vue'),
33
33
  },
34
- {
34
+ {
35
35
  path: 'center',
36
36
  name: 'center',
37
37
  meta: { title: '个人中心', cache: true },
38
38
  component: () => import('../views/baiscstatis/center.vue'),
39
39
  },
40
40
 
41
-
42
41
  {
43
42
  path: 'iframePage',
44
43
  meta: { cache: false },
@@ -46,6 +45,7 @@ const routes = [
46
45
  },
47
46
  {
48
47
  path: 'notFound',
48
+ meta: { title: '404 Not Found', cache: true },
49
49
  component: () => import('../views/baiscstatis/notFound.vue'),
50
50
  },
51
51
  ],
@@ -64,7 +64,7 @@ let hasAddRoutes = false
64
64
  let routeLoadFailed = false
65
65
 
66
66
  // 组件加载器,带有错误处理
67
- const loadComponent = (path) => {
67
+ const loadComponent = path => {
68
68
  const possiblePaths = [
69
69
  `/src/views${path}.vue`,
70
70
  `./views${path}.vue`,
@@ -90,26 +90,25 @@ async function loadDynamicRoutes() {
90
90
  const dynamicBtns = resbtn.data || []
91
91
  menu.setMenus(dynamicRoutes)
92
92
  menu.setPermissions(dynamicBtns)
93
- dynamicRoutes.forEach((route) => {
93
+ dynamicRoutes.forEach(route => {
94
94
  if (route.type === 1) {
95
95
  // 目录类型
96
96
  const parentRoute = {
97
97
  path: route.path,
98
98
  component: home,
99
- // meta: { title: route.title },
99
+ meta: { title: route.title },
100
100
  // children: [],
101
101
  }
102
102
  const addRoutes = (parentRoute, children) => {
103
103
  if (children && children.length > 0) {
104
104
  parentRoute.children = children.map(child => {
105
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, },
106
+ path: child.path,
107
+ name: child.path.replace(/\//g, '-').substring(1),
108
+ meta: { title: child.title, cache: child.cache, fullPath: child.path },
110
109
  }
111
- if(child.type!=1){
112
- childRoute.component = loadComponent(child.path)
110
+ if (child.type != 1) {
111
+ childRoute.component = loadComponent(child.path)
113
112
  }
114
113
  // 递归处理多级子路由
115
114
  if (child.children) {
@@ -126,7 +125,7 @@ async function loadDynamicRoutes() {
126
125
  const pageRoute = {
127
126
  path: route.path,
128
127
  name: route.path.replace(/\//g, '-').substring(1),
129
- component: loadComponent(route.path),
128
+ component: loadComponent(route.path),
130
129
  meta: {
131
130
  title: route.title,
132
131
  cache: route.cache,
@@ -140,7 +139,7 @@ async function loadDynamicRoutes() {
140
139
  } catch (error) {
141
140
  console.error('❌ 动态路由加载失败:', error)
142
141
  routeLoadFailed = true
143
- // 如果是401错误(令牌过期),清除用户信息并跳转到登录页
142
+ // 如果是401错误(令牌过期),清除用户信息并跳转到登录页
144
143
  if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
145
144
  const user = useUserStore()
146
145
  user.clearUserInfo()
@@ -152,13 +151,11 @@ async function loadDynamicRoutes() {
152
151
 
153
152
  // 全局前置守卫
154
153
  router.beforeEach(async (to, from, next) => {
155
- // document.title = to.meta.title || 'ZCloudVue'
156
- // document.title = 'ZCloudVue'
157
154
  const config = configStore()
158
- document.title = config.projectName
155
+ document.title = to.meta.title ? to.meta.title + ' - ' + config.projectName : config.projectName
159
156
  const user = useUserStore()
160
157
 
161
- // 如果目标路由在白名单中,直接放行
158
+ // 如果目标路由在白名单中,直接放行
162
159
  if (publicRoutes.includes(to.path)) {
163
160
  next()
164
161
  return
@@ -173,26 +170,41 @@ router.beforeEach(async (to, from, next) => {
173
170
  if (user.token && !hasAddRoutes && !routeLoadFailed) {
174
171
  try {
175
172
  await loadDynamicRoutes()
176
-
173
+
177
174
  // 检查是否有持久化的路由状态需要恢复
178
175
  const menu = menuStore()
179
- if (menu.selectmenuKey && menu.selectmenuKey.length > 0 && to.path === '/console') {
176
+ if (
177
+ menu.selectmenuKey &&
178
+ menu.selectmenuKey.length > 0 &&
179
+ to.path === '/console'
180
+ ) {
180
181
  // 如果当前是跳转到首页,但有持久化的选中菜单,尝试恢复路由
181
- const selectedMenu = menu.tagmenus.find(tag => tag.key === menu.selectmenuKey[0])
182
- if (selectedMenu && selectedMenu.path && selectedMenu.path !== '/console') {
182
+ const selectedMenu = menu.tagmenus.find(
183
+ tag => tag.key === menu.selectmenuKey[0],
184
+ )
185
+ if (
186
+ selectedMenu &&
187
+ selectedMenu.path &&
188
+ selectedMenu.path !== '/console'
189
+ ) {
183
190
  // 检查路由是否存在
184
- const routeExists = router.getRoutes().some((r) => r.path === selectedMenu.path)
191
+ const routeExists = router
192
+ .getRoutes()
193
+ .some(r => r.path === selectedMenu.path)
185
194
  if (routeExists) {
186
195
  next({ path: selectedMenu.path, replace: true })
187
196
  return
188
197
  }
189
198
  }
190
199
  }
191
-
200
+
192
201
  next({ ...to, replace: true })
193
202
  } catch (error) {
194
203
  // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
195
- if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
204
+ if (
205
+ error.code === 401 ||
206
+ (error.errors && error.errors.includes('登录'))
207
+ ) {
196
208
  return
197
209
  }
198
210
  // 其他错误跳转到404页面
@@ -216,7 +228,7 @@ router.beforeEach(async (to, from, next) => {
216
228
  }
217
229
 
218
230
  // 路由存在性检查
219
- const routeExists = router.getRoutes().some((r) => r.path === to.path)
231
+ const routeExists = router.getRoutes().some(r => r.path === to.path)
220
232
  if (!routeExists && !publicRoutes.includes(to.path)) {
221
233
  // 如果路由不存在且不在白名单中,检查是否是动态路由还未加载
222
234
  if (user.token && !hasAddRoutes && !routeLoadFailed) {
@@ -227,7 +239,10 @@ router.beforeEach(async (to, from, next) => {
227
239
  return
228
240
  } catch (error) {
229
241
  // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
230
- if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
242
+ if (
243
+ error.code === 401 ||
244
+ (error.errors && error.errors.includes('登录'))
245
+ ) {
231
246
  return
232
247
  }
233
248
  // 其他错误跳转到404页面
@@ -243,7 +258,7 @@ router.beforeEach(async (to, from, next) => {
243
258
  next()
244
259
  })
245
260
 
246
- router.onError((error) => {
261
+ router.onError(error => {
247
262
  console.error('🚨 路由错误:', error)
248
263
  })
249
264
 
@@ -253,12 +268,15 @@ export async function refreshRoutes() {
253
268
  // 清空旧的菜单,避免重复
254
269
  const menu = menuStore()
255
270
  menu.setMenus([])
256
- menu.setPermissions([])
257
- // 移除之前添加的动态路由
271
+ menu.setPermissions([])
272
+ // 移除之前添加的动态路由
258
273
  const routes = router.getRoutes()
259
274
  routes.forEach(route => {
260
275
  // 只移除动态添加的路由,保留静态路由
261
- if (route.path && !['/login', '/', '/console', '/notFound', '/center'].includes(route.path)) {
276
+ if (
277
+ route.path &&
278
+ !['/login', '/', '/console', '/notFound', '/center'].includes(route.path)
279
+ ) {
262
280
  router.removeRoute(route.name)
263
281
  }
264
282
  })
@@ -30,7 +30,13 @@ export const configStore = defineStore({
30
30
  {
31
31
  key: 'CONFIG',
32
32
  storage: localStorage,
33
- paths: ['themeClass','navigationMode', 'tableSize', 'tableBordered', 'locale'],
33
+ paths: [
34
+ 'themeClass',
35
+ 'navigationMode',
36
+ 'tableSize',
37
+ 'tableBordered',
38
+ 'locale',
39
+ ],
34
40
  },
35
41
  ],
36
42
  },
@@ -16,7 +16,7 @@ export const menuStore = defineStore({
16
16
  },
17
17
  ],
18
18
  menus: [],
19
- permissions: []
19
+ permissions: [],
20
20
  }
21
21
  },
22
22
  actions: {
@@ -26,8 +26,12 @@ export const menuStore = defineStore({
26
26
  setOpenmenuKey(keys) {
27
27
  this.openmenuKey = keys
28
28
  },
29
- setMenus(menus) { this.menus = menus },
30
- setPermissions(permissions) { this.permissions = permissions },
29
+ setMenus(menus) {
30
+ this.menus = menus
31
+ },
32
+ setPermissions(permissions) {
33
+ this.permissions = permissions
34
+ },
31
35
  // 检查是否有指定权限
32
36
  hasPermission(permission) {
33
37
  if (!permission) return true
@@ -35,13 +39,27 @@ export const menuStore = defineStore({
35
39
  },
36
40
  // 检查是否有多个权限中的任意一个
37
41
  hasAnyPermission(permissions) {
38
- if (!permissions || !Array.isArray(permissions) || permissions.length === 0) return true
39
- return permissions.some(permission => this.permissions.includes(permission))
42
+ if (
43
+ !permissions ||
44
+ !Array.isArray(permissions) ||
45
+ permissions.length === 0
46
+ )
47
+ return true
48
+ return permissions.some(permission =>
49
+ this.permissions.includes(permission),
50
+ )
40
51
  },
41
52
  // 检查是否拥有所有权限
42
53
  hasAllPermissions(permissions) {
43
- if (!permissions || !Array.isArray(permissions) || permissions.length === 0) return true
44
- return permissions.every(permission => this.permissions.includes(permission))
54
+ if (
55
+ !permissions ||
56
+ !Array.isArray(permissions) ||
57
+ permissions.length === 0
58
+ )
59
+ return true
60
+ return permissions.every(permission =>
61
+ this.permissions.includes(permission),
62
+ )
45
63
  },
46
64
  },
47
65
  persist: {
@@ -50,7 +68,13 @@ export const menuStore = defineStore({
50
68
  {
51
69
  key: 'MENU_RESULT',
52
70
  storage: localStorage,
53
- paths: ['menus', 'openmenuKey', 'selectmenuKey', 'tagmenus', 'permissions'],
71
+ paths: [
72
+ 'menus',
73
+ 'openmenuKey',
74
+ 'selectmenuKey',
75
+ 'tagmenus',
76
+ 'permissions',
77
+ ],
54
78
  },
55
79
  ],
56
80
  },
@@ -1,21 +1,21 @@
1
1
  import { defineStore } from 'pinia'
2
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: [{
3
+ id: 'TOKEN_USER_INFO',
4
+ state: () => {
5
+ return {
6
+ token: '',
7
+ userInfo: {},
8
+ }
9
+ },
10
+ actions: {},
11
+ persist: {
12
+ enabled: true,
13
+ strategies: [
14
+ {
16
15
  key: 'TOKEN_USER_INFO',
17
16
  storage: localStorage,
18
- paths: ['token', 'userInfo' ],
19
- }]
20
- }
21
- })
17
+ paths: ['token', 'userInfo'],
18
+ },
19
+ ],
20
+ },
21
+ })
@@ -18,7 +18,7 @@ const fetchAllAddressData = async () => {
18
18
  const [provinceRes, cityRes, areaRes] = await Promise.all([
19
19
  region.getAllProvince(),
20
20
  region.getAllCity(),
21
- region.getAllAreas()
21
+ region.getAllAreas(),
22
22
  ])
23
23
 
24
24
  // 存储原始数据
@@ -44,7 +44,7 @@ const fetchAllAddressData = async () => {
44
44
  value: item.adcode,
45
45
  })),
46
46
  cities: allCity.value,
47
- areas: allAreas.value
47
+ areas: allAreas.value,
48
48
  }
49
49
  } catch (error) {
50
50
  console.error('获取省市区数据失败:', error)
@@ -57,12 +57,14 @@ const fetchAllAddressData = async () => {
57
57
  * @param {string} provinceCode - 省份代码(adcode)
58
58
  * @returns {Array} 城市数据数组
59
59
  */
60
- const getCitiesByProvinceCode = (provinceCode) => {
60
+ const getCitiesByProvinceCode = provinceCode => {
61
61
  if (!provinceCode || !cityData.value.length) return []
62
- return cityData.value.filter(city => city.parentAdcode === provinceCode).map(city => ({
63
- label: city.name,
64
- value: city.adcode,
65
- }))
62
+ return cityData.value
63
+ .filter(city => city.parentAdcode === provinceCode)
64
+ .map(city => ({
65
+ label: city.name,
66
+ value: city.adcode,
67
+ }))
66
68
  }
67
69
 
68
70
  /**
@@ -70,12 +72,14 @@ const getCitiesByProvinceCode = (provinceCode) => {
70
72
  * @param {string} cityCode - 城市代码(adcode)
71
73
  * @returns {Array} 区域数据数组
72
74
  */
73
- const getAreasByCityCode = (cityCode) => {
75
+ const getAreasByCityCode = cityCode => {
74
76
  if (!cityCode || !areaData.value.length) return []
75
- return areaData.value.filter(area => area.parentAdcode === cityCode).map(area => ({
76
- label: area.name,
77
- value: area.adcode,
78
- }))
77
+ return areaData.value
78
+ .filter(area => area.parentAdcode === cityCode)
79
+ .map(area => ({
80
+ label: area.name,
81
+ value: area.adcode,
82
+ }))
79
83
  }
80
84
 
81
85
  /**
@@ -110,7 +114,7 @@ const getAllAreas = () => {
110
114
  * @param {string} adcode - 省份adcode
111
115
  * @returns {Object} 省份信息对象
112
116
  */
113
- const getProvinceByAdcode = (adcode) => {
117
+ const getProvinceByAdcode = adcode => {
114
118
  if (!adcode || !provinceData.value.length) return null
115
119
  return provinceData.value.find(province => province.adcode === adcode)
116
120
  }
@@ -120,7 +124,7 @@ const getProvinceByAdcode = (adcode) => {
120
124
  * @param {string} adcode - 城市adcode
121
125
  * @returns {Object} 城市信息对象
122
126
  */
123
- const getCityByAdcode = (adcode) => {
127
+ const getCityByAdcode = adcode => {
124
128
  if (!adcode || !cityData.value.length) return null
125
129
  return cityData.value.find(city => city.adcode === adcode)
126
130
  }
@@ -130,7 +134,7 @@ const getCityByAdcode = (adcode) => {
130
134
  * @param {string} adcode - 区域adcode
131
135
  * @returns {Object} 区域信息对象
132
136
  */
133
- const getAreaByAdcode = (adcode) => {
137
+ const getAreaByAdcode = adcode => {
134
138
  if (!adcode || !areaData.value.length) return null
135
139
  return areaData.value.find(area => area.adcode === adcode)
136
140
  }
@@ -165,5 +169,5 @@ export default {
165
169
  getProvinceByAdcode,
166
170
  getCityByAdcode,
167
171
  getAreaByAdcode,
168
- getFullAddressName
172
+ getFullAddressName,
169
173
  }
@@ -1,60 +1,59 @@
1
- import { ref } from 'vue'
2
- import { message } from 'ant-design-vue'
3
-
4
- /**
5
- * 通用表单 CRUD Hook
6
- * @param {Object} api - API对象,例如 sysRole
7
- * @param {Object} [options] - 配置
8
- * @param {string} [options.addMethod='add'] - 新增方法名
9
- * @param {string} [options.updateMethod='update'] - 修改方法名
10
- * @param {boolean} [options.autoMessage=true] - 是否自动提示
11
- */
12
- export default function useFormCRUD(api, {
13
- addMethod = 'add',
14
- updateMethod = 'update',
15
- autoMessage = true
16
- } = {}) {
17
- const loading = ref(false)
18
-
19
- /**
20
- * 保存表单
21
- * @param {Object} formRef - 表单 ref
22
- * @param {Object} formData - 表单数据
23
- * @param {Function} [onSuccess] - 成功回调
24
- * @param {Function} [onError] - 错误回调
25
- */
26
- const save = async (formRef, formData, { onSuccess, onError } = {}) => {
27
- try {
28
- // 校验表单
29
- await formRef?.validate()
30
- loading.value = true
31
-
32
- const method = (formData.id) ? updateMethod : addMethod
33
- const result = await api[method](formData)
34
- // 先显示提示,再执行回调
35
- if (autoMessage) {
36
- message.success(formData.id ? '修改成功' : '新增成功', 1, () => {
37
- onSuccess?.(result)
38
- })
39
- } else {
40
- onSuccess?.(result)
41
- }
42
-
43
- return result
44
- } catch (err) {
45
- if (err?.errorFields) {
46
- message.warning('请完善表单信息')
47
- } else {
48
- onError?.(err)
49
- if (autoMessage && onError) {
50
- message.error('操作失败,请重试')
51
- }
52
- }
53
- throw err
54
- } finally {
55
- loading.value = false
56
- }
57
- }
58
-
59
- return { loading, save }
60
- }
1
+ import { ref } from 'vue'
2
+ import { message } from 'ant-design-vue'
3
+
4
+ /**
5
+ * 通用表单 CRUD Hook
6
+ * @param {Object} api - API对象,例如 sysRole
7
+ * @param {Object} [options] - 配置
8
+ * @param {string} [options.addMethod='add'] - 新增方法名
9
+ * @param {string} [options.updateMethod='update'] - 修改方法名
10
+ * @param {boolean} [options.autoMessage=true] - 是否自动提示
11
+ */
12
+ export default function useFormCRUD(
13
+ api,
14
+ { addMethod = 'add', updateMethod = 'update', autoMessage = true } = {},
15
+ ) {
16
+ const loading = ref(false)
17
+
18
+ /**
19
+ * 保存表单
20
+ * @param {Object} formRef - 表单 ref
21
+ * @param {Object} formData - 表单数据
22
+ * @param {Function} [onSuccess] - 成功回调
23
+ * @param {Function} [onError] - 错误回调
24
+ */
25
+ const save = async (formRef, formData, { onSuccess, onError } = {}) => {
26
+ try {
27
+ // 校验表单
28
+ await formRef?.validate()
29
+ loading.value = true
30
+
31
+ const method = formData.id ? updateMethod : addMethod
32
+ const result = await api[method](formData)
33
+ // 先显示提示,再执行回调
34
+ if (autoMessage) {
35
+ message.success(formData.id ? '修改成功' : '新增成功', 1, () => {
36
+ onSuccess?.(result)
37
+ })
38
+ } else {
39
+ onSuccess?.(result)
40
+ }
41
+
42
+ return result
43
+ } catch (err) {
44
+ if (err?.errorFields) {
45
+ message.warning('请完善表单信息')
46
+ } else {
47
+ onError?.(err)
48
+ if (autoMessage && onError) {
49
+ message.error('操作失败,请重试')
50
+ }
51
+ }
52
+ throw err
53
+ } finally {
54
+ loading.value = false
55
+ }
56
+ }
57
+
58
+ return { loading, save }
59
+ }