zant-admin 1.0.0 → 1.0.4

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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +443 -247
  3. package/bin/cli.js +99 -99
  4. package/bin/generator.js +502 -502
  5. package/bin/prompts.js +158 -158
  6. package/bin/utils.js +133 -133
  7. package/package.json +2 -2
  8. package/src/App.vue +1 -1
  9. package/src/api/methods/sysAccount.js +0 -1
  10. package/src/api/methods/sysDictItem.js +3 -3
  11. package/src/api/methods/system.js +10 -11
  12. package/src/api/request.js +39 -39
  13. package/src/assets/css/style.css +0 -11
  14. package/src/assets/css/zcui.css +1002 -319
  15. package/src/components/FormTable.vue +50 -37
  16. package/src/components/IconPicker.vue +351 -344
  17. package/src/components/MainPage.vue +220 -339
  18. package/src/components/edit/QuartzEdit.vue +1 -1
  19. package/src/components/edit/SysAccountEdit.vue +15 -8
  20. package/src/components/edit/SysDictEdit.vue +6 -4
  21. package/src/components/edit/SysDictItemEdit.vue +8 -6
  22. package/src/components/edit/SysRoleEdit.vue +5 -3
  23. package/src/components/edit/sysMenuEdit.vue +10 -25
  24. package/src/config/index.js +74 -74
  25. package/src/directives/permission.js +49 -45
  26. package/src/main.js +2 -3
  27. package/src/router/index.js +46 -26
  28. package/src/stores/config.js +7 -1
  29. package/src/stores/menu.js +32 -8
  30. package/src/stores/user.js +17 -17
  31. package/src/utils/regionUtils.js +20 -16
  32. package/src/utils/useFormCRUD.js +59 -60
  33. package/src/views/baiscstatis/center.vue +53 -42
  34. package/src/views/baiscstatis/iframePage.vue +9 -11
  35. package/src/views/console.vue +92 -42
  36. package/src/views/demo/button.vue +269 -0
  37. package/src/views/demo/importexport.vue +8 -12
  38. package/src/views/demo/region.vue +103 -21
  39. package/src/views/demo/statistics.vue +38 -19
  40. package/src/views/home.vue +2 -3
  41. package/src/views/login.vue +1 -1
  42. package/src/views/operations/log/logQuartz.vue +0 -1
  43. package/src/views/operations/quartz.vue +22 -24
  44. package/src/views/system/sysAccount.vue +16 -11
  45. package/src/views/system/sysDict.vue +9 -6
  46. package/src/views/system/sysMenu.vue +17 -15
  47. package/src/views/system/sysRole.vue +44 -21
  48. package/SCAFFOLD_README.md +0 -215
@@ -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 },
@@ -64,7 +63,7 @@ let hasAddRoutes = false
64
63
  let routeLoadFailed = false
65
64
 
66
65
  // 组件加载器,带有错误处理
67
- const loadComponent = (path) => {
66
+ const loadComponent = path => {
68
67
  const possiblePaths = [
69
68
  `/src/views${path}.vue`,
70
69
  `./views${path}.vue`,
@@ -90,7 +89,7 @@ async function loadDynamicRoutes() {
90
89
  const dynamicBtns = resbtn.data || []
91
90
  menu.setMenus(dynamicRoutes)
92
91
  menu.setPermissions(dynamicBtns)
93
- dynamicRoutes.forEach((route) => {
92
+ dynamicRoutes.forEach(route => {
94
93
  if (route.type === 1) {
95
94
  // 目录类型
96
95
  const parentRoute = {
@@ -103,13 +102,13 @@ async function loadDynamicRoutes() {
103
102
  if (children && children.length > 0) {
104
103
  parentRoute.children = children.map(child => {
105
104
  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, },
105
+ path: child.path,
106
+ meta: { title: child.title },
107
+ name: child.path.replace(/\//g, '-').substring(1),
108
+ meta: { 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()
@@ -158,7 +157,7 @@ router.beforeEach(async (to, from, next) => {
158
157
  document.title = config.projectName
159
158
  const user = useUserStore()
160
159
 
161
- // 如果目标路由在白名单中,直接放行
160
+ // 如果目标路由在白名单中,直接放行
162
161
  if (publicRoutes.includes(to.path)) {
163
162
  next()
164
163
  return
@@ -173,26 +172,41 @@ router.beforeEach(async (to, from, next) => {
173
172
  if (user.token && !hasAddRoutes && !routeLoadFailed) {
174
173
  try {
175
174
  await loadDynamicRoutes()
176
-
175
+
177
176
  // 检查是否有持久化的路由状态需要恢复
178
177
  const menu = menuStore()
179
- if (menu.selectmenuKey && menu.selectmenuKey.length > 0 && to.path === '/console') {
178
+ if (
179
+ menu.selectmenuKey &&
180
+ menu.selectmenuKey.length > 0 &&
181
+ to.path === '/console'
182
+ ) {
180
183
  // 如果当前是跳转到首页,但有持久化的选中菜单,尝试恢复路由
181
- const selectedMenu = menu.tagmenus.find(tag => tag.key === menu.selectmenuKey[0])
182
- if (selectedMenu && selectedMenu.path && selectedMenu.path !== '/console') {
184
+ const selectedMenu = menu.tagmenus.find(
185
+ tag => tag.key === menu.selectmenuKey[0],
186
+ )
187
+ if (
188
+ selectedMenu &&
189
+ selectedMenu.path &&
190
+ selectedMenu.path !== '/console'
191
+ ) {
183
192
  // 检查路由是否存在
184
- const routeExists = router.getRoutes().some((r) => r.path === selectedMenu.path)
193
+ const routeExists = router
194
+ .getRoutes()
195
+ .some(r => r.path === selectedMenu.path)
185
196
  if (routeExists) {
186
197
  next({ path: selectedMenu.path, replace: true })
187
198
  return
188
199
  }
189
200
  }
190
201
  }
191
-
202
+
192
203
  next({ ...to, replace: true })
193
204
  } catch (error) {
194
205
  // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
195
- if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
206
+ if (
207
+ error.code === 401 ||
208
+ (error.errors && error.errors.includes('登录'))
209
+ ) {
196
210
  return
197
211
  }
198
212
  // 其他错误跳转到404页面
@@ -216,7 +230,7 @@ router.beforeEach(async (to, from, next) => {
216
230
  }
217
231
 
218
232
  // 路由存在性检查
219
- const routeExists = router.getRoutes().some((r) => r.path === to.path)
233
+ const routeExists = router.getRoutes().some(r => r.path === to.path)
220
234
  if (!routeExists && !publicRoutes.includes(to.path)) {
221
235
  // 如果路由不存在且不在白名单中,检查是否是动态路由还未加载
222
236
  if (user.token && !hasAddRoutes && !routeLoadFailed) {
@@ -227,7 +241,10 @@ router.beforeEach(async (to, from, next) => {
227
241
  return
228
242
  } catch (error) {
229
243
  // 如果是401错误,已经在loadDynamicRoutes中处理了跳转
230
- if (error.code === 401 || (error.errors && error.errors.includes('登录'))) {
244
+ if (
245
+ error.code === 401 ||
246
+ (error.errors && error.errors.includes('登录'))
247
+ ) {
231
248
  return
232
249
  }
233
250
  // 其他错误跳转到404页面
@@ -243,7 +260,7 @@ router.beforeEach(async (to, from, next) => {
243
260
  next()
244
261
  })
245
262
 
246
- router.onError((error) => {
263
+ router.onError(error => {
247
264
  console.error('🚨 路由错误:', error)
248
265
  })
249
266
 
@@ -253,12 +270,15 @@ export async function refreshRoutes() {
253
270
  // 清空旧的菜单,避免重复
254
271
  const menu = menuStore()
255
272
  menu.setMenus([])
256
- menu.setPermissions([])
257
- // 移除之前添加的动态路由
273
+ menu.setPermissions([])
274
+ // 移除之前添加的动态路由
258
275
  const routes = router.getRoutes()
259
276
  routes.forEach(route => {
260
277
  // 只移除动态添加的路由,保留静态路由
261
- if (route.path && !['/login', '/', '/console', '/notFound', '/center'].includes(route.path)) {
278
+ if (
279
+ route.path &&
280
+ !['/login', '/', '/console', '/notFound', '/center'].includes(route.path)
281
+ ) {
262
282
  router.removeRoute(route.name)
263
283
  }
264
284
  })
@@ -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
+ }