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.
- package/LICENSE +21 -0
- package/README.md +443 -247
- package/bin/cli.js +99 -99
- package/bin/generator.js +502 -502
- package/bin/prompts.js +158 -158
- package/bin/utils.js +133 -133
- package/package.json +2 -2
- package/src/App.vue +1 -1
- package/src/api/methods/sysAccount.js +0 -1
- package/src/api/methods/sysDictItem.js +3 -3
- package/src/api/methods/system.js +10 -11
- package/src/api/request.js +39 -39
- package/src/assets/css/style.css +0 -11
- package/src/assets/css/zcui.css +1002 -319
- package/src/components/FormTable.vue +50 -37
- package/src/components/IconPicker.vue +351 -344
- package/src/components/MainPage.vue +220 -339
- package/src/components/edit/QuartzEdit.vue +1 -1
- package/src/components/edit/SysAccountEdit.vue +15 -8
- package/src/components/edit/SysDictEdit.vue +6 -4
- package/src/components/edit/SysDictItemEdit.vue +8 -6
- package/src/components/edit/SysRoleEdit.vue +5 -3
- package/src/components/edit/sysMenuEdit.vue +10 -25
- package/src/config/index.js +74 -74
- package/src/directives/permission.js +49 -45
- package/src/main.js +2 -3
- package/src/router/index.js +46 -26
- package/src/stores/config.js +7 -1
- package/src/stores/menu.js +32 -8
- package/src/stores/user.js +17 -17
- package/src/utils/regionUtils.js +20 -16
- package/src/utils/useFormCRUD.js +59 -60
- package/src/views/baiscstatis/center.vue +53 -42
- package/src/views/baiscstatis/iframePage.vue +9 -11
- package/src/views/console.vue +92 -42
- package/src/views/demo/button.vue +269 -0
- package/src/views/demo/importexport.vue +8 -12
- package/src/views/demo/region.vue +103 -21
- package/src/views/demo/statistics.vue +38 -19
- package/src/views/home.vue +2 -3
- package/src/views/login.vue +1 -1
- package/src/views/operations/log/logQuartz.vue +0 -1
- package/src/views/operations/quartz.vue +22 -24
- package/src/views/system/sysAccount.vue +16 -11
- package/src/views/system/sysDict.vue +9 -6
- package/src/views/system/sysMenu.vue +17 -15
- package/src/views/system/sysRole.vue +44 -21
- package/SCAFFOLD_README.md +0 -215
package/src/router/index.js
CHANGED
|
@@ -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 =
|
|
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(
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
178
|
+
if (
|
|
179
|
+
menu.selectmenuKey &&
|
|
180
|
+
menu.selectmenuKey.length > 0 &&
|
|
181
|
+
to.path === '/console'
|
|
182
|
+
) {
|
|
180
183
|
// 如果当前是跳转到首页,但有持久化的选中菜单,尝试恢复路由
|
|
181
|
-
const selectedMenu = menu.tagmenus.find(
|
|
182
|
-
|
|
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
|
|
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 (
|
|
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(
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
257
|
-
|
|
273
|
+
menu.setPermissions([])
|
|
274
|
+
// 移除之前添加的动态路由
|
|
258
275
|
const routes = router.getRoutes()
|
|
259
276
|
routes.forEach(route => {
|
|
260
277
|
// 只移除动态添加的路由,保留静态路由
|
|
261
|
-
if (
|
|
278
|
+
if (
|
|
279
|
+
route.path &&
|
|
280
|
+
!['/login', '/', '/console', '/notFound', '/center'].includes(route.path)
|
|
281
|
+
) {
|
|
262
282
|
router.removeRoute(route.name)
|
|
263
283
|
}
|
|
264
284
|
})
|
package/src/stores/config.js
CHANGED
|
@@ -30,7 +30,13 @@ export const configStore = defineStore({
|
|
|
30
30
|
{
|
|
31
31
|
key: 'CONFIG',
|
|
32
32
|
storage: localStorage,
|
|
33
|
-
paths: [
|
|
33
|
+
paths: [
|
|
34
|
+
'themeClass',
|
|
35
|
+
'navigationMode',
|
|
36
|
+
'tableSize',
|
|
37
|
+
'tableBordered',
|
|
38
|
+
'locale',
|
|
39
|
+
],
|
|
34
40
|
},
|
|
35
41
|
],
|
|
36
42
|
},
|
package/src/stores/menu.js
CHANGED
|
@@ -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) {
|
|
30
|
-
|
|
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 (
|
|
39
|
-
|
|
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 (
|
|
44
|
-
|
|
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: [
|
|
71
|
+
paths: [
|
|
72
|
+
'menus',
|
|
73
|
+
'openmenuKey',
|
|
74
|
+
'selectmenuKey',
|
|
75
|
+
'tagmenus',
|
|
76
|
+
'permissions',
|
|
77
|
+
],
|
|
54
78
|
},
|
|
55
79
|
],
|
|
56
80
|
},
|
package/src/stores/user.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
2
|
export const useUserStore = defineStore({
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
+
})
|
package/src/utils/regionUtils.js
CHANGED
|
@@ -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 =
|
|
60
|
+
const getCitiesByProvinceCode = provinceCode => {
|
|
61
61
|
if (!provinceCode || !cityData.value.length) return []
|
|
62
|
-
return cityData.value
|
|
63
|
-
|
|
64
|
-
|
|
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 =
|
|
75
|
+
const getAreasByCityCode = cityCode => {
|
|
74
76
|
if (!cityCode || !areaData.value.length) return []
|
|
75
|
-
return areaData.value
|
|
76
|
-
|
|
77
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
}
|
package/src/utils/useFormCRUD.js
CHANGED
|
@@ -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(
|
|
13
|
-
|
|
14
|
-
updateMethod = 'update',
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* @param {Object}
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {Function} [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
onError
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
}
|