@skyfox2000/webui 1.0.14 → 1.2.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.
- package/lib/assets/modules/file-upload-CBUcsUnR.js +170 -0
- package/lib/assets/modules/form-validate-CgX7aR7T.js +297 -0
- package/lib/assets/modules/index-Civhd8xG.js +112 -0
- package/lib/assets/modules/index-DQMdt51R.js +726 -0
- package/lib/assets/modules/{index-BEWJ_qAH.js → index-DmWrkTXX.js} +1 -1
- package/lib/assets/modules/{menuTabs-BXdbFZor.js → menuTabs-BRYvFWA-.js} +131 -121
- package/lib/assets/modules/settingInfo-BZakNKIN.js +999 -0
- package/lib/assets/modules/uploadList-B7XoxGOh.js +278 -0
- package/lib/components/common/icon/index.vue.d.ts +1 -1
- package/lib/components/content/dialog/index.vue.d.ts +1 -1
- package/lib/components/content/drawer/index.vue.d.ts +1 -1
- package/lib/components/content/form/index.vue.d.ts +1 -1
- package/lib/components/content/search/index.vue.d.ts +1 -1
- package/lib/components/content/table/index.vue.d.ts +1 -1
- package/lib/components/content/table/tableOperate.vue.d.ts +1 -1
- package/lib/components/content/toolbar/icontool.vue.d.ts +1 -1
- package/lib/components/content/toolbar/index.vue.d.ts +1 -1
- package/lib/components/content/tree/index.vue.d.ts +1 -1
- package/lib/components/form/transfer/transferTable.vue.d.ts +1 -1
- package/lib/components/form/treeSelect/index.vue.d.ts +1 -1
- package/lib/components/form/upload/uploadList.vue.d.ts +1 -1
- package/lib/const/options.d.ts +32 -0
- package/lib/directives/enter-submit.d.ts +4 -0
- package/lib/directives/index.d.ts +2 -0
- package/lib/directives/permission.d.ts +5 -0
- package/lib/es/AceEditor/index.js +9 -8
- package/lib/es/BasicLayout/index.js +28 -24
- package/lib/es/Error403/index.js +15 -10
- package/lib/es/Error404/index.js +15 -10
- package/lib/es/ExcelForm/index.js +380 -175
- package/lib/es/UploadForm/index.js +23 -20
- package/lib/index.d.ts +42 -2
- package/lib/router/index.d.ts +16 -0
- package/lib/stores/appInfo.d.ts +34 -0
- package/lib/stores/hostInfo.d.ts +9 -0
- package/lib/stores/pageInfo.d.ts +18 -0
- package/lib/stores/pinia.d.ts +3 -0
- package/lib/stores/settingInfo.d.ts +8 -0
- package/lib/stores/userInfo.d.ts +21 -0
- package/lib/typings/data.d.ts +80 -0
- package/lib/typings/form.d.ts +171 -0
- package/lib/typings/menu.d.ts +7 -0
- package/lib/typings/option.d.ts +175 -0
- package/lib/typings/page.d.ts +69 -0
- package/lib/typings/table.d.ts +181 -0
- package/lib/typings/tools.d.ts +130 -0
- package/lib/typings/tree.d.ts +72 -0
- package/lib/typings/upload.d.ts +161 -0
- package/lib/typings/urls.d.ts +69 -0
- package/lib/utils/cache.d.ts +23 -0
- package/lib/utils/data.d.ts +6 -0
- package/lib/utils/download.d.ts +4 -0
- package/lib/utils/eventbus.d.ts +16 -0
- package/lib/utils/export-table.d.ts +12 -0
- package/lib/utils/file-upload.d.ts +15 -0
- package/lib/utils/form-excel.d.ts +30 -0
- package/lib/utils/form-validate.d.ts +29 -0
- package/lib/utils/form.d.ts +9 -0
- package/lib/utils/icon-loader.d.ts +125 -0
- package/lib/utils/isEmpty.d.ts +1 -0
- package/lib/utils/main-openapis.d.ts +9 -0
- package/lib/utils/menu.d.ts +6 -0
- package/lib/utils/options.d.ts +10 -0
- package/lib/utils/page.d.ts +25 -0
- package/lib/utils/table.d.ts +21 -0
- package/lib/utils/tools.d.ts +18 -0
- package/lib/utils/tree.d.ts +3 -0
- package/lib/vite-env.d.ts +8 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +890 -724
- package/package.json +7 -6
- package/src/components/common/icon/appicon.vue +1 -1
- package/src/components/common/icon/fullscreen.vue +2 -1
- package/src/components/common/icon/index.vue +1 -1
- package/src/components/common/icon/layoutIcon.vue +1 -1
- package/src/components/common/icon/projectIcon.vue +1 -1
- package/src/components/common/icon/toolIcon.vue +1 -1
- package/src/components/content/dialog/excelForm.vue +2 -2
- package/src/components/content/dialog/index.vue +1 -1
- package/src/components/content/dialog/uploadForm.vue +7 -6
- package/src/components/content/drawer/index.vue +43 -18
- package/src/components/content/form/formItem.vue +1 -1
- package/src/components/content/form/index.vue +1 -1
- package/src/components/content/search/index.vue +1 -1
- package/src/components/content/search/searchItem.vue +1 -1
- package/src/components/content/table/index.vue +3 -3
- package/src/components/content/table/tableOperate.vue +2 -2
- package/src/components/content/toolbar/icontool.vue +2 -2
- package/src/components/content/toolbar/index.vue +3 -2
- package/src/components/content/tree/index.vue +1 -1
- package/src/components/error/error403.vue +2 -2
- package/src/components/error/error404.vue +2 -2
- package/src/components/form/autoComplete/index.vue +1 -1
- package/src/components/form/cascader/index.vue +1 -2
- package/src/components/form/checkbox/index.vue +11 -5
- package/src/components/form/datePicker/index.vue +1 -1
- package/src/components/form/input/index.vue +1 -1
- package/src/components/form/input/inputNumber.vue +1 -1
- package/src/components/form/input/inputPassword.vue +1 -1
- package/src/components/form/radio/index.vue +1 -1
- package/src/components/form/radio/radioStatus.vue +1 -1
- package/src/components/form/rangePicker/index.vue +1 -1
- package/src/components/form/select/index.vue +1 -1
- package/src/components/form/switch/index.vue +7 -3
- package/src/components/form/textarea/index.vue +1 -1
- package/src/components/form/transfer/index.vue +1 -1
- package/src/components/form/transfer/transferTable.vue +42 -22
- package/src/components/form/treeSelect/index.vue +2 -3
- package/src/components/form/upload/uploadList.vue +1 -1
- package/src/components/layout/breadcrumb/index.vue +1 -1
- package/src/components/layout/header/headerExits.vue +1 -1
- package/src/components/layout/header/index.vue +1 -1
- package/src/components/layout/header/user.vue +2 -1
- package/src/components/layout/menu/index.vue +9 -3
- package/src/components/layout/menu/menuTabs.vue +10 -12
- package/src/components/layout/page/basicLayout.vue +1 -1
- package/src/const/options.ts +114 -0
- package/src/directives/enter-submit.ts +13 -0
- package/src/directives/index.ts +26 -0
- package/src/directives/permission.ts +144 -0
- package/src/index.ts +201 -0
- package/src/router/index.ts +196 -0
- package/src/stores/appInfo.ts +471 -0
- package/src/stores/hostInfo.ts +117 -0
- package/src/stores/pageInfo.ts +131 -0
- package/src/stores/pinia.ts +10 -0
- package/src/stores/settingInfo.ts +53 -0
- package/src/stores/userInfo.ts +392 -0
- package/src/typings/data.d.ts +81 -0
- package/src/typings/form.d.ts +172 -0
- package/src/typings/menu.d.ts +7 -0
- package/src/typings/option.d.ts +177 -0
- package/src/typings/page.d.ts +70 -0
- package/src/typings/table.d.ts +182 -0
- package/src/typings/tools.d.ts +131 -0
- package/src/typings/tree.d.ts +73 -0
- package/src/typings/upload.d.ts +162 -0
- package/src/typings/urls.d.ts +70 -0
- package/src/utils/cache.ts +175 -0
- package/src/utils/data.ts +189 -0
- package/src/utils/download.ts +80 -0
- package/src/utils/eventbus.ts +78 -0
- package/src/utils/export-table.ts +155 -0
- package/src/utils/file-upload.ts +304 -0
- package/src/utils/form-excel.ts +523 -0
- package/src/utils/form-validate.ts +368 -0
- package/src/utils/form.ts +188 -0
- package/src/utils/icon-loader.ts +412 -0
- package/src/utils/isEmpty.ts +18 -0
- package/src/utils/main-openapis.ts +72 -0
- package/src/utils/menu.ts +89 -0
- package/src/utils/options.ts +324 -0
- package/src/utils/page.ts +262 -0
- package/src/utils/table.ts +274 -0
- package/src/utils/tools.ts +362 -0
- package/src/utils/tree.ts +28 -0
- package/tsconfig.json +1 -8
- package/vite.config.ts +7 -4
- package/lib/assets/modules/index-BahGnrAq.js +0 -415
- package/lib/assets/modules/index-BoKIa2sr.js +0 -109
- package/lib/assets/modules/index-D47Ci-T3.js +0 -107
- package/lib/assets/modules/uploadList-Dzlg47V0.js +0 -182
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnyData,
|
|
3
|
+
ApiResponse,
|
|
4
|
+
fieldMapping,
|
|
5
|
+
httpPost,
|
|
6
|
+
IUrlInfo,
|
|
7
|
+
parseFieldTemplate,
|
|
8
|
+
ReqParams,
|
|
9
|
+
ResStatus,
|
|
10
|
+
} from '@skyfox2000/fapi';
|
|
11
|
+
import { inject, ref, Ref, watch } from 'vue';
|
|
12
|
+
import { OptionProps, OptionItemProps, SelectValue } from '@/typings/option.d';
|
|
13
|
+
import { InputFactoryItems } from '@/typings/form.d';
|
|
14
|
+
import { ProviderKeys } from '@/typings/page.d';
|
|
15
|
+
import message from 'vue-m-message';
|
|
16
|
+
import eventBus from './eventbus';
|
|
17
|
+
import { formValidate } from './form-validate';
|
|
18
|
+
import { combineParams } from '@skyfox2000/microbase';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 自动初始化选择项
|
|
22
|
+
* @param autoload 是否自动加载
|
|
23
|
+
* @param props 选项外部属性值
|
|
24
|
+
* @param options 实际选择项
|
|
25
|
+
* @param inputFactory 本地工厂,用于统一处理事件
|
|
26
|
+
* @param url 选项接口
|
|
27
|
+
* @param params 选择参数
|
|
28
|
+
*/
|
|
29
|
+
export const loadOption = (
|
|
30
|
+
autoload: boolean,
|
|
31
|
+
props: OptionProps,
|
|
32
|
+
options: Ref<OptionItemProps[]>,
|
|
33
|
+
inputFactory?: InputFactoryItems<any>,
|
|
34
|
+
url?: IUrlInfo,
|
|
35
|
+
// 自定义的额外参数
|
|
36
|
+
params?: ReqParams,
|
|
37
|
+
) => {
|
|
38
|
+
if (inputFactory && props.reloadEvent) {
|
|
39
|
+
/// 接收事件,联动显示或者重新加载数据
|
|
40
|
+
inputFactory.reloadHandler = (_event: string, data: Record<string, AnyData> | AnyData[]) => {
|
|
41
|
+
optionEventHandler(url!, props, data, options);
|
|
42
|
+
};
|
|
43
|
+
eventBus.on(props.reloadEvent, inputFactory.reloadHandler);
|
|
44
|
+
}
|
|
45
|
+
if (props.data) {
|
|
46
|
+
watch(
|
|
47
|
+
() => props.data,
|
|
48
|
+
() => {
|
|
49
|
+
updateOptions(props, props.data!, options, true);
|
|
50
|
+
},
|
|
51
|
+
{ deep: true, immediate: true },
|
|
52
|
+
);
|
|
53
|
+
} else if (url && url.url) {
|
|
54
|
+
if (autoload !== false) doQueryOptions(url, props, params ?? {}, options);
|
|
55
|
+
} else {
|
|
56
|
+
const labelText = ref<string>(inject(ProviderKeys.LabelText, ''));
|
|
57
|
+
message.error('`' + labelText.value + '` 未配置选项数据!', {
|
|
58
|
+
duration: 5000,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 组件选项数据更新
|
|
65
|
+
* @param props 选项外部属性值
|
|
66
|
+
* @param data 提供的下拉数据
|
|
67
|
+
* @param options 实际选择项
|
|
68
|
+
* @param mapping 是否需要转换字段
|
|
69
|
+
*/
|
|
70
|
+
const updateOptions = (
|
|
71
|
+
props: OptionProps,
|
|
72
|
+
data: Record<string, AnyData>[],
|
|
73
|
+
options: Ref<OptionItemProps[]>,
|
|
74
|
+
mapping: boolean,
|
|
75
|
+
) => {
|
|
76
|
+
if (!data || data.length === 0) {
|
|
77
|
+
options.value = [];
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (mapping) {
|
|
81
|
+
// 转换字段
|
|
82
|
+
const fieldMap = {
|
|
83
|
+
...props.fieldMap,
|
|
84
|
+
};
|
|
85
|
+
data = fieldMapping(fieldMap, data);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
data = JSON.parse(JSON.stringify(data));
|
|
89
|
+
if (props.all) {
|
|
90
|
+
data.unshift({
|
|
91
|
+
label: '全部',
|
|
92
|
+
value: undefined,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
options.value = data as OptionItemProps[];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 选项重载事件处理
|
|
101
|
+
* @param url 选项接口
|
|
102
|
+
* @param props 选项外部属性值
|
|
103
|
+
* @param data 提供的下拉数据
|
|
104
|
+
* @param options 实际选择项
|
|
105
|
+
*/
|
|
106
|
+
const optionEventHandler = (
|
|
107
|
+
url: IUrlInfo,
|
|
108
|
+
props: OptionProps,
|
|
109
|
+
data: Record<string, AnyData> | AnyData[],
|
|
110
|
+
options: Ref<OptionItemProps[]>,
|
|
111
|
+
) => {
|
|
112
|
+
if (Array.isArray(data)) {
|
|
113
|
+
updateOptions(props, data, options, true);
|
|
114
|
+
} else {
|
|
115
|
+
doQueryOptions(url, props, { Query: data }, options);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 卸载选择项
|
|
121
|
+
* @param props 选项外部属性值
|
|
122
|
+
* @param inputFactory 输入组件工厂
|
|
123
|
+
*/
|
|
124
|
+
export const unloadOption = (props: OptionProps, inputFactory?: InputFactoryItems<any>) => {
|
|
125
|
+
if (inputFactory && props.reloadEvent && inputFactory.reloadHandler)
|
|
126
|
+
eventBus.off(props.reloadEvent, inputFactory.reloadHandler);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
* @param url 选项接口
|
|
132
|
+
* @param props 选项外部属性值
|
|
133
|
+
* @param params 查询条件
|
|
134
|
+
* @param options 实际选择项
|
|
135
|
+
*/
|
|
136
|
+
const doQueryOptions = (url: IUrlInfo, props: OptionProps, params: ReqParams, options: Ref<OptionItemProps[]>) => {
|
|
137
|
+
const newParams: ReqParams = combineParams(url.params, params, props.params);
|
|
138
|
+
queryOptions(url, props.fieldMap, newParams).then((results) => {
|
|
139
|
+
// 使用url,由request负责转换,无需再次map转换
|
|
140
|
+
const data = results as OptionItemProps[];
|
|
141
|
+
updateOptions(props, data, options, false);
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 请求查询选项
|
|
147
|
+
* @param url 选项接口
|
|
148
|
+
* @param fieldMap 选项数据转换
|
|
149
|
+
* @param params 选择参数
|
|
150
|
+
* @returns 选项列表
|
|
151
|
+
* @default 默认设置
|
|
152
|
+
* - cacheTime: 60000
|
|
153
|
+
* - fieldMap:
|
|
154
|
+
** {
|
|
155
|
+
** title: "Name",
|
|
156
|
+
** label: "Name",
|
|
157
|
+
** value: "Id",
|
|
158
|
+
** key: "Id"
|
|
159
|
+
** }
|
|
160
|
+
*/
|
|
161
|
+
const queryOptions = <T>(
|
|
162
|
+
url: IUrlInfo,
|
|
163
|
+
fieldMap?: Record<string, string>,
|
|
164
|
+
params?: ReqParams,
|
|
165
|
+
): Promise<T[] | undefined> => {
|
|
166
|
+
// 排除 fieldMap 属性
|
|
167
|
+
const { fieldMap: _, ...rest } = url;
|
|
168
|
+
const defaultUrl: IUrlInfo = {
|
|
169
|
+
url: '',
|
|
170
|
+
cacheTime: 60000,
|
|
171
|
+
fieldMap: {
|
|
172
|
+
...fieldMap,
|
|
173
|
+
...url.fieldMap,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
const optionUrl = {
|
|
177
|
+
...defaultUrl,
|
|
178
|
+
...rest,
|
|
179
|
+
};
|
|
180
|
+
optionUrl.loadingText = false;
|
|
181
|
+
if (!params) params = {};
|
|
182
|
+
if (!params.Query) params.Query = {};
|
|
183
|
+
return httpPost<T>(optionUrl, params).then((result: ApiResponse<T> | null) => {
|
|
184
|
+
if (result?.status === ResStatus.SUCCESS) {
|
|
185
|
+
if (result.data) {
|
|
186
|
+
return result.data as T[];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return [];
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 获取选中的选项对象或对象数组
|
|
195
|
+
* @param values 当前选择的值
|
|
196
|
+
* @param options 所有选项对象数组
|
|
197
|
+
* @returns 选中的选项对象或对象数组
|
|
198
|
+
*/
|
|
199
|
+
export const getSelectedValues = (
|
|
200
|
+
values: undefined | string | number | (string | number | undefined)[],
|
|
201
|
+
options: OptionItemProps[],
|
|
202
|
+
): OptionItemProps | OptionItemProps[] | undefined => {
|
|
203
|
+
// 如果 values 为 undefined,直接返回 undefined
|
|
204
|
+
if (values === undefined) return undefined;
|
|
205
|
+
|
|
206
|
+
// 如果 values 是数组,返回所有匹配的选项对象数组
|
|
207
|
+
if (Array.isArray(values)) {
|
|
208
|
+
return options.filter((option) => values.includes(option.value));
|
|
209
|
+
}
|
|
210
|
+
// 如果 values 是单个值,返回匹配的单个选项对象
|
|
211
|
+
else {
|
|
212
|
+
return options.find((option) => option.value === values);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// 辅助函数:根据路径设置值
|
|
217
|
+
const setNestedValue = (obj: Record<string, any>, path: string, value: any) => {
|
|
218
|
+
const parts = path.split('.');
|
|
219
|
+
let current = obj;
|
|
220
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
221
|
+
const part = parts[i];
|
|
222
|
+
if (!current[part]) {
|
|
223
|
+
current[part] = {};
|
|
224
|
+
}
|
|
225
|
+
current = current[part];
|
|
226
|
+
}
|
|
227
|
+
current[parts[parts.length - 1]] = value;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 将选中的值根据 outFields 映射到 formData 上
|
|
232
|
+
* @param formData 需要更新的数据对象
|
|
233
|
+
* @param outFields 输出字段转换映射关系
|
|
234
|
+
* @param selectedValues 选中的选项对象或对象数组
|
|
235
|
+
*/
|
|
236
|
+
export const outFormDataFields = (
|
|
237
|
+
formData: Record<string, any>,
|
|
238
|
+
outFields: Record<string, string>,
|
|
239
|
+
selectedValues?: OptionItemProps | OptionItemProps[] | null,
|
|
240
|
+
) => {
|
|
241
|
+
// 如果 selectedValues 为 undefined,直接返回
|
|
242
|
+
if (selectedValues === undefined || selectedValues === null) {
|
|
243
|
+
Object.entries(outFields).forEach(([targetKey]) => {
|
|
244
|
+
setNestedValue(formData, targetKey, selectedValues);
|
|
245
|
+
});
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 如果 selectedValues 是数组
|
|
250
|
+
if (Array.isArray(selectedValues)) {
|
|
251
|
+
// selectedValues.forEach((selectedValue) => {
|
|
252
|
+
// Object.entries(outFields).forEach(([targetKey, sourceKey]) => {
|
|
253
|
+
// const value = selectedValue[sourceKey];
|
|
254
|
+
// setNestedValue(formData, targetKey, value);
|
|
255
|
+
// });
|
|
256
|
+
// });
|
|
257
|
+
}
|
|
258
|
+
// 如果 selectedValues 是单个对象
|
|
259
|
+
else {
|
|
260
|
+
Object.entries(outFields).forEach(([targetKey, sourceKey]) => {
|
|
261
|
+
if (sourceKey.includes('${')) {
|
|
262
|
+
const value = parseFieldTemplate(sourceKey, selectedValues);
|
|
263
|
+
setNestedValue(formData, targetKey, value);
|
|
264
|
+
} else {
|
|
265
|
+
setNestedValue(formData, targetKey, selectedValues[sourceKey]);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* 选项选中事件处理函数
|
|
273
|
+
* @param props 选项外部属性值
|
|
274
|
+
* @param values 选中的项目,支持单选或多项
|
|
275
|
+
* @param options 实际选择项
|
|
276
|
+
* @param inputFactory 输入组件工厂
|
|
277
|
+
*/
|
|
278
|
+
export const onOptionChanged = (
|
|
279
|
+
props: OptionProps,
|
|
280
|
+
values: undefined | SelectValue,
|
|
281
|
+
options: Ref<OptionItemProps[]>,
|
|
282
|
+
inputFactory: InputFactoryItems<any>,
|
|
283
|
+
): OptionItemProps | OptionItemProps[] | undefined => {
|
|
284
|
+
// 如果存在验证错误,重新检测
|
|
285
|
+
if (inputFactory.editorCtrl && inputFactory.errInfo?.value.errClass) {
|
|
286
|
+
formValidate(inputFactory.editorCtrl);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// 获取选中的选项对象或对象数组
|
|
290
|
+
const selectedValues = getSelectedValues(values, options.value);
|
|
291
|
+
|
|
292
|
+
// 如果配置了 formData 和 outFields,将选中的其它属性值映射到 formData 上
|
|
293
|
+
if (props.formData && props.outFields) {
|
|
294
|
+
outFormDataFields(props.formData, props.outFields, selectedValues);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (props.changeEvent) {
|
|
298
|
+
if (Array.isArray(props.changeEvent)) {
|
|
299
|
+
props.changeEvent.every((changeEvent: string) => {
|
|
300
|
+
eventBus.emit(changeEvent, values, selectedValues);
|
|
301
|
+
});
|
|
302
|
+
} else {
|
|
303
|
+
eventBus.emit(props.changeEvent, values, selectedValues);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// 触发 inputFactory 的 change 事件
|
|
307
|
+
if (inputFactory.inputEmit) {
|
|
308
|
+
inputFactory.inputEmit('change', values, selectedValues);
|
|
309
|
+
}
|
|
310
|
+
return selectedValues;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* 获取选中的选项文字内容
|
|
315
|
+
* @param selectedValues 选中的选项对象或对象数
|
|
316
|
+
* @returns 选中的选项文字内容
|
|
317
|
+
*/
|
|
318
|
+
export const getSelectedLabels = (selectedValues: OptionItemProps | OptionItemProps[] | undefined): string[] => {
|
|
319
|
+
if (selectedValues === undefined) return [];
|
|
320
|
+
if (Array.isArray(selectedValues)) {
|
|
321
|
+
return selectedValues.map((option) => option.label);
|
|
322
|
+
}
|
|
323
|
+
return [selectedValues.label];
|
|
324
|
+
};
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { ApiUrls } from '@/typings/urls.d';
|
|
2
|
+
import { ValidateRule } from '@/typings/form.d';
|
|
3
|
+
import { EditorControl, EditorControlOption } from '@/typings/form.d';
|
|
4
|
+
import { GridControl, GridControlOption } from '@/typings/table.d';
|
|
5
|
+
import { PageControl, PageControlOption } from '@/typings/page.d';
|
|
6
|
+
import { TreeControl, TreeControlOption } from '@/typings/tree.d';
|
|
7
|
+
import { ref, watch, shallowRef } from 'vue';
|
|
8
|
+
import { queryTree } from './tree';
|
|
9
|
+
import { gridQueryFind, gridQueryList } from './table';
|
|
10
|
+
|
|
11
|
+
const defaultOptions: {
|
|
12
|
+
PageOption: PageControlOption;
|
|
13
|
+
GridOption: GridControlOption;
|
|
14
|
+
EditorOption: EditorControlOption;
|
|
15
|
+
TreeOption: TreeControlOption;
|
|
16
|
+
} = {
|
|
17
|
+
PageOption: {
|
|
18
|
+
primaryKey: 'Id',
|
|
19
|
+
statusKey: 'Enabled',
|
|
20
|
+
},
|
|
21
|
+
GridOption: {
|
|
22
|
+
autoload: true,
|
|
23
|
+
primaryKey: 'Id',
|
|
24
|
+
statusKey: 'Enabled',
|
|
25
|
+
remotePage: true,
|
|
26
|
+
tableSize: ref('small'),
|
|
27
|
+
selectable: ref(false),
|
|
28
|
+
searchBar: ref(true),
|
|
29
|
+
pageSize: ref(10),
|
|
30
|
+
rowExpand: ref(false),
|
|
31
|
+
buttons: ref(['New']),
|
|
32
|
+
tools: ['Reload', 'RowHeight', 'TableHeadset'],
|
|
33
|
+
operates: ['Edit', 'Delete'],
|
|
34
|
+
},
|
|
35
|
+
EditorOption: {
|
|
36
|
+
primaryKey: 'Id',
|
|
37
|
+
autoClose: true,
|
|
38
|
+
autoDetail: false,
|
|
39
|
+
saveBtnVisible: true,
|
|
40
|
+
saveAsBtnVisible: true,
|
|
41
|
+
},
|
|
42
|
+
TreeOption: {
|
|
43
|
+
autoload: true,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 设置页面控制工厂默认参数
|
|
49
|
+
* @param options 修改默认参数
|
|
50
|
+
*/
|
|
51
|
+
export const initPageFactory = (options: {
|
|
52
|
+
pageOption?: PageControlOption;
|
|
53
|
+
gridOption?: GridControlOption;
|
|
54
|
+
editorOptions?: EditorControlOption;
|
|
55
|
+
treeOption?: TreeControlOption;
|
|
56
|
+
}) => {
|
|
57
|
+
defaultOptions.PageOption = {
|
|
58
|
+
...defaultOptions.PageOption,
|
|
59
|
+
...options.pageOption,
|
|
60
|
+
};
|
|
61
|
+
defaultOptions.GridOption = {
|
|
62
|
+
...defaultOptions.GridOption,
|
|
63
|
+
...options.gridOption,
|
|
64
|
+
};
|
|
65
|
+
defaultOptions.EditorOption = {
|
|
66
|
+
...defaultOptions.EditorOption,
|
|
67
|
+
...options.editorOptions,
|
|
68
|
+
};
|
|
69
|
+
defaultOptions.TreeOption = {
|
|
70
|
+
...defaultOptions.TreeOption,
|
|
71
|
+
...options.treeOption,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 编辑器工厂处理
|
|
77
|
+
*
|
|
78
|
+
* @param urls 接口地址
|
|
79
|
+
* @param pageCtrl 页面控制
|
|
80
|
+
* @param defaultData 默认数据
|
|
81
|
+
* @param formRules 表单验证规则
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
export const useEditorFactory = <T, E>(
|
|
85
|
+
urls: ApiUrls,
|
|
86
|
+
pageCtrl: PageControl<T>,
|
|
87
|
+
defaultData?: Partial<E>,
|
|
88
|
+
formRules?: Record<string, ValidateRule>,
|
|
89
|
+
) => {
|
|
90
|
+
/**
|
|
91
|
+
* 表单数据交互控制
|
|
92
|
+
*/
|
|
93
|
+
const editorCtrl: EditorControl<E> = {
|
|
94
|
+
...defaultOptions.EditorOption,
|
|
95
|
+
name: '',
|
|
96
|
+
default: defaultData ? JSON.parse(JSON.stringify(defaultData)) : undefined,
|
|
97
|
+
visible: ref(false),
|
|
98
|
+
page: pageCtrl,
|
|
99
|
+
formData: ref(defaultData ? JSON.parse(JSON.stringify(defaultData)) : undefined),
|
|
100
|
+
formRules: ref(formRules),
|
|
101
|
+
ruleResults: ref({}),
|
|
102
|
+
updateData: ref(undefined),
|
|
103
|
+
saveUrl: urls.urls.save,
|
|
104
|
+
detailUrl: urls.urls.detail,
|
|
105
|
+
isFormSaving: ref(false),
|
|
106
|
+
isFormLoading: ref(false),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
editorCtrl,
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 表格控制工厂处理
|
|
116
|
+
*
|
|
117
|
+
* @param urls 接口地址
|
|
118
|
+
* @param pageCtrl 页面控制
|
|
119
|
+
* @param columns 表格列配置
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
export const useGridFactory = <T, G>(urls: ApiUrls, pageCtrl: PageControl<T>, columns?: Record<string, any>[]) => {
|
|
123
|
+
/**
|
|
124
|
+
* 表格数据交互控制
|
|
125
|
+
*/
|
|
126
|
+
const gridCtrl: GridControl<G> = {
|
|
127
|
+
...defaultOptions.GridOption,
|
|
128
|
+
tableSize: ref(defaultOptions.GridOption.tableSize.value),
|
|
129
|
+
selectable: ref(defaultOptions.GridOption.selectable.value),
|
|
130
|
+
searchBar: ref(defaultOptions.GridOption.searchBar.value),
|
|
131
|
+
pageSize: ref(defaultOptions.GridOption.pageSize.value),
|
|
132
|
+
rowExpand: ref(defaultOptions.GridOption.rowExpand.value),
|
|
133
|
+
buttons: ref([...defaultOptions.GridOption.buttons.value]),
|
|
134
|
+
tools: [...defaultOptions.GridOption.tools],
|
|
135
|
+
operates: [...defaultOptions.GridOption.operates],
|
|
136
|
+
|
|
137
|
+
columns: ref(columns || []),
|
|
138
|
+
reload: ref(false),
|
|
139
|
+
pageNo: ref(1),
|
|
140
|
+
total: ref(0),
|
|
141
|
+
page: pageCtrl,
|
|
142
|
+
selectKeys: ref([]),
|
|
143
|
+
selectRows: ref([]),
|
|
144
|
+
rowData: ref(undefined),
|
|
145
|
+
gridQuery: {},
|
|
146
|
+
tableData: shallowRef(undefined),
|
|
147
|
+
expandRows: ref({}),
|
|
148
|
+
isGridLoading: ref(false),
|
|
149
|
+
isGridSaving: ref(false),
|
|
150
|
+
gridUrl: urls.urls.list || urls.urls.find,
|
|
151
|
+
updateUrl: urls.urls.update,
|
|
152
|
+
deleteUrl: urls.urls.delete,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// 监听重载状态
|
|
156
|
+
watch(
|
|
157
|
+
() => gridCtrl.reload.value,
|
|
158
|
+
(newVal) => {
|
|
159
|
+
if (newVal) {
|
|
160
|
+
// 使用 nextTick 或 setTimeout 延迟重置值
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
gridCtrl.reload.value = false;
|
|
163
|
+
}, 1);
|
|
164
|
+
|
|
165
|
+
if (gridCtrl.remotePage) gridQueryFind(gridCtrl);
|
|
166
|
+
else gridQueryList(gridCtrl);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
gridCtrl,
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 树控制工厂处理
|
|
178
|
+
*
|
|
179
|
+
* @param urls 接口地址
|
|
180
|
+
* @param pageCtrl 页面控制
|
|
181
|
+
* @returns
|
|
182
|
+
*/
|
|
183
|
+
export const useTreeFactory = <T>(urls: ApiUrls, pageCtrl: PageControl<T>) => {
|
|
184
|
+
/**
|
|
185
|
+
* 树数据交互控制
|
|
186
|
+
*/
|
|
187
|
+
const treeCtrl: TreeControl = {
|
|
188
|
+
...defaultOptions.TreeOption,
|
|
189
|
+
reload: ref(false),
|
|
190
|
+
page: pageCtrl,
|
|
191
|
+
node: ref(undefined),
|
|
192
|
+
url: urls.urls.tree,
|
|
193
|
+
data: shallowRef(undefined),
|
|
194
|
+
isTreeLoading: ref(false),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// 监听重载状态
|
|
198
|
+
watch(
|
|
199
|
+
() => treeCtrl.reload.value,
|
|
200
|
+
(newVal) => {
|
|
201
|
+
if (newVal) {
|
|
202
|
+
// 使用 nextTick 或 setTimeout 延迟重置值
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
treeCtrl.reload.value = false;
|
|
205
|
+
}, 1);
|
|
206
|
+
queryTree(treeCtrl);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
treeCtrl,
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 页面控制工厂处理
|
|
218
|
+
*
|
|
219
|
+
* @param urls 接口地址
|
|
220
|
+
* @param defaultData 默认数据
|
|
221
|
+
* @param formRules 表单验证规则
|
|
222
|
+
* @returns
|
|
223
|
+
*/
|
|
224
|
+
export const usePageFactory = <T>(
|
|
225
|
+
urls: ApiUrls,
|
|
226
|
+
defaultData?: Partial<T>,
|
|
227
|
+
formRules?: Record<string, ValidateRule>,
|
|
228
|
+
) => {
|
|
229
|
+
// urls 参数处理
|
|
230
|
+
// api 默认
|
|
231
|
+
// authorize 默认
|
|
232
|
+
for (const key in urls.urls) {
|
|
233
|
+
if (urls.urls[key]) {
|
|
234
|
+
if (!urls.urls[key].api) urls.urls[key].api = urls.api;
|
|
235
|
+
if (urls.urls[key].authorize === undefined) urls.urls[key].authorize = urls.authorize;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 页面交互主数据
|
|
241
|
+
* 通过统一的页面交互数据,能够更方便在页面组件中传递数据
|
|
242
|
+
*/
|
|
243
|
+
const pageCtrl: PageControl<T> = {
|
|
244
|
+
...defaultOptions.PageOption,
|
|
245
|
+
...urls,
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const { editorCtrl } = useEditorFactory<T, T>(urls, pageCtrl, defaultData, formRules);
|
|
249
|
+
const { gridCtrl } = useGridFactory<T, T>(urls, pageCtrl);
|
|
250
|
+
|
|
251
|
+
pageCtrl.editor = editorCtrl;
|
|
252
|
+
pageCtrl.grid = gridCtrl;
|
|
253
|
+
gridCtrl.editor = editorCtrl;
|
|
254
|
+
gridCtrl.tools = ['Reload', 'RowHeight', 'TableHeadset', 'Fullscreen'];
|
|
255
|
+
editorCtrl.grid = gridCtrl;
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
pageCtrl,
|
|
259
|
+
editorCtrl,
|
|
260
|
+
gridCtrl,
|
|
261
|
+
};
|
|
262
|
+
};
|