@skyfox2000/webui 1.2.8 → 1.2.9

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 (72) hide show
  1. package/lib/assets/modules/_plugin-vue_export-helper-CHgC5LLL.js +9 -0
  2. package/lib/assets/modules/file-upload-BYIvmkmy.js +204 -0
  3. package/lib/assets/modules/form-excel-BUX2QW11.js +235 -0
  4. package/lib/assets/modules/{index-CTVMLeDF.js → index-DcRkhkn2.js} +1 -1
  5. package/lib/assets/modules/index-jl5Ie2tZ.js +112 -0
  6. package/lib/assets/modules/{menuTabs-BtOiocOC.js → menuTabs-DY1XBq16.js} +134 -139
  7. package/lib/assets/modules/{toolIcon-B9Mw9Ktm.js → toolIcon-BDIOj_3l.js} +1 -1
  8. package/lib/assets/modules/uploadList-BPG5whz7.js +369 -0
  9. package/lib/assets/modules/{index-D9kzQ23e.js → uploadList-D2Ux4h1N.js} +553 -513
  10. package/lib/components/common/index.d.ts +2 -0
  11. package/lib/components/common/loading/index.vue.d.ts +3 -0
  12. package/lib/components/content/dialog/index.vue.d.ts +1 -0
  13. package/lib/components/content/drawer/index.vue.d.ts +2 -0
  14. package/lib/components/content/form/formItem.vue.d.ts +2 -0
  15. package/lib/components/form/autoComplete/index.vue.d.ts +41 -4
  16. package/lib/components/form/cascader/index.vue.d.ts +13 -2
  17. package/lib/components/form/checkbox/index.vue.d.ts +13 -2
  18. package/lib/components/form/index.d.ts +1 -0
  19. package/lib/components/form/propEditor/index.vue.d.ts +10 -1
  20. package/lib/components/form/radio/index.vue.d.ts +13 -2
  21. package/lib/components/form/select/index.vue.d.ts +13 -2
  22. package/lib/components/form/upload/uploadList.vue.d.ts +14 -3
  23. package/lib/components/index.d.ts +2 -2
  24. package/lib/es/AceEditor/index.js +3 -3
  25. package/lib/es/BasicLayout/index.js +15 -15
  26. package/lib/es/Error403/index.js +1 -1
  27. package/lib/es/Error404/index.js +1 -1
  28. package/lib/es/ExcelForm/index.js +4 -4
  29. package/lib/es/UploadForm/index.js +60 -87
  30. package/lib/index.d.ts +2 -2
  31. package/lib/typings/form.d.ts +18 -2
  32. package/lib/typings/option.d.ts +16 -2
  33. package/lib/typings/page.d.ts +1 -0
  34. package/lib/utils/file-upload.d.ts +4 -2
  35. package/lib/utils/form-excel.d.ts +3 -0
  36. package/lib/webui.css +1 -1
  37. package/lib/webui.es.js +1085 -1063
  38. package/package.json +1 -1
  39. package/scripts/userInput.py +2 -0
  40. package/src/components/common/index.ts +3 -0
  41. package/src/components/common/loading/index.vue +11 -0
  42. package/src/components/content/dialog/index.vue +15 -8
  43. package/src/components/content/dialog/uploadForm.vue +38 -79
  44. package/src/components/content/drawer/index.vue +26 -6
  45. package/src/components/content/form/formItem.vue +21 -5
  46. package/src/components/content/form/index.vue +4 -2
  47. package/src/components/content/search/searchItem.vue +1 -1
  48. package/src/components/form/autoComplete/index.vue +12 -4
  49. package/src/components/form/cascader/index.vue +1 -1
  50. package/src/components/form/datePicker/index.vue +1 -1
  51. package/src/components/form/index.ts +1 -0
  52. package/src/components/form/input/inputIcon.vue +1 -1
  53. package/src/components/form/propEditor/index.vue +113 -33
  54. package/src/components/form/select/index.vue +27 -17
  55. package/src/components/form/upload/uploadList.vue +174 -34
  56. package/src/components/index.ts +13 -1
  57. package/src/directives/permission.ts +2 -2
  58. package/src/index.ts +3 -1
  59. package/src/typings/form.d.ts +18 -2
  60. package/src/typings/option.d.ts +16 -2
  61. package/src/typings/page.d.ts +1 -0
  62. package/src/utils/download.ts +1 -1
  63. package/src/utils/eventbus.ts +1 -1
  64. package/src/utils/file-upload.ts +75 -14
  65. package/src/utils/form-excel.ts +50 -1
  66. package/src/utils/form-validate.ts +18 -1
  67. package/src/utils/form.ts +3 -1
  68. package/src/utils/options.ts +38 -12
  69. package/lib/assets/modules/file-upload-CZO-pMJd.js +0 -176
  70. package/lib/assets/modules/form-excel-N-2OYqKv.js +0 -211
  71. package/lib/assets/modules/index-BnHnS9ug.js +0 -111
  72. package/lib/assets/modules/uploadList-B4LxzsC6.js +0 -210
@@ -99,6 +99,22 @@ export type EditorControl<T> = EditorControlOption & {
99
99
  ruleValidator?: Validator;
100
100
  /**
101
101
  * 验证结果
102
+ * @example
103
+ * ```ts
104
+ * const ruleResults: Record<string, ValidateError[]> = {};
105
+ * fieldNames.forEach((fieldName) => {
106
+ * const rule = formRules[fieldName];
107
+ * if (rule) {
108
+ * ruleResults[fieldName] = [
109
+ * {
110
+ * field: fieldName,
111
+ * fieldValue: fieldValue,
112
+ * message: `数据重复`,
113
+ * },
114
+ * ];
115
+ * }
116
+ * });
117
+ * ```
102
118
  */
103
119
  ruleResults: Ref<Record<string, ValidateError[]> | undefined>;
104
120
  /**
@@ -156,10 +172,10 @@ export interface InputFactoryItems<T> {
156
172
  /**
157
173
  * 输入项reload事件处理
158
174
  * @param event 事件名
159
- * @param data 参数
175
+ * @param params 参数
160
176
  * @returns
161
177
  */
162
- reloadHandler?: (event: string, data: Record<string, AnyData> | AnyData[]) => void;
178
+ reloadHandler?: (event: string, params: Record<string, AnyData> | AnyData[]) => void;
163
179
  /**
164
180
  * 输入项事件
165
181
  * @param evt 事件
@@ -43,6 +43,10 @@ export interface OptionProps {
43
43
  * 接口定义
44
44
  */
45
45
  url?: IUrlInfo;
46
+ /**
47
+ * 重载接口,默认false
48
+ */
49
+ reload?: boolean;
46
50
  /**
47
51
  * 接口自定义QOD参数
48
52
  */
@@ -73,8 +77,9 @@ export interface OptionProps {
73
77
  * - eventBus.emit(changeEvent, { Q参数 } | 数据[])
74
78
  * - 数据组仅用于联动显示
75
79
  * - 其它情况使用Query参数
80
+ * - 第一个参数为事件名,第二个参数为事件参数模板,支持模板 ${selectedValues}
76
81
  */
77
- changeEvent?: string | string[];
82
+ changeEvent?: [string | string[], string];
78
83
  }
79
84
 
80
85
  import type { PropType } from 'vue';
@@ -124,6 +129,14 @@ export const OptionCommProps = {
124
129
  type: Object as PropType<IUrlInfo>,
125
130
  required: false,
126
131
  },
132
+ /**
133
+ * 重载接口,默认false
134
+ */
135
+ reload: {
136
+ type: Boolean as PropType<boolean>,
137
+ required: false,
138
+ default: false,
139
+ },
127
140
  /**
128
141
  * 接口自定义QOD参数
129
142
  */
@@ -169,9 +182,10 @@ export const OptionCommProps = {
169
182
  * - eventBus.emit(changeEvent, { Q参数 } | 数据[])
170
183
  * - 数据组仅用于联动显示
171
184
  * - 其它情况使用Query参数
185
+ * - 第一个参数为事件名,第二个参数为事件参数模板,支持模板 ${selectedValues}
172
186
  */
173
187
  changeEvent: {
174
- type: [String, Array] as PropType<string | string[]>,
188
+ type: Array as PropType<[string | string[], string]>,
175
189
  required: false,
176
190
  },
177
191
  };
@@ -17,6 +17,7 @@ export enum ProviderKeys {
17
17
  'EditorControl' = 'Page.EditorControl',
18
18
  'GridControl' = 'Page.GridControl',
19
19
  'LabelText' = 'FormItem.LabelText',
20
+ 'LabelWidth' = 'FormItem.LabelWidth',
20
21
  'RuleKey' = 'FormItem.RuleKey',
21
22
  'ErrInfo' = 'FormItem.ErrInfo',
22
23
  }
@@ -51,7 +51,7 @@ export const donwloadFromMinio = <T>(url: IUrlInfo, params?: ReqParams, pageCtrl
51
51
  const minioFile: MinioFile = result.data as unknown as MinioFile;
52
52
  // 提取内容和文件名
53
53
  const base64String = minioFile.Content!;
54
- const fileName = minioFile.FileName!;
54
+ const fileName = minioFile.Key.split('/').pop()!;
55
55
 
56
56
  // 解码 Base64 字符串
57
57
  const byteCharacters = atob(base64String);
@@ -25,7 +25,7 @@ class EventBus {
25
25
  */
26
26
  on(event: string, listener: (...args: any[]) => void) {
27
27
  if (!this.isValidPrefix(event)) {
28
- console.error(`事件前缀不正确: ${event}`);
28
+ console.error(`事件前缀不正确: ${event}, 事件名必须以 ${Object.values(EventPrefix).join(', ')} 开头`);
29
29
  return;
30
30
  }
31
31
 
@@ -3,6 +3,8 @@ import { hostUrl, IUrlInfo } from '@skyfox2000/fapi';
3
3
  import { getToken } from '@/utils/main-openapis';
4
4
  import { UploadFile, UploadStatus } from '@/typings/upload.d';
5
5
  import dayjs from 'dayjs';
6
+ import message from 'vue-m-message';
7
+ import { Ref } from 'vue';
6
8
 
7
9
  export class path {
8
10
  /**
@@ -44,18 +46,70 @@ export class AsyncUploader {
44
46
  * @param urlInfo 文件上传的 API 配置(IUrlInfo 对象)
45
47
  * @param maxConcurrent 最大允许并发上传的文件数量
46
48
  */
47
- constructor(urlInfo: IUrlInfo, maxConcurrent: number) {
49
+ constructor(urlInfo: IUrlInfo, maxConcurrent: number = 3) {
48
50
  this.urlInfo = urlInfo;
49
51
  this.maxConcurrent = maxConcurrent;
50
52
  }
51
53
 
54
+ /**
55
+ * 执行上传
56
+ * @param fileList 文件列表
57
+ * @param loading 加载状态
58
+ * @param continueOnError 错误时是否继续上传
59
+ * @param onComplete 上传完成回调
60
+ * @param onProgress 上传进度回调
61
+ * @returns 上传结果
62
+ */
63
+ public async doUpload(
64
+ fileList: UploadFile[],
65
+ loading: Ref<boolean>,
66
+ continueOnError: boolean,
67
+ onComplete?: (result: boolean, files: UploadFile[]) => void,
68
+ onProgress?: (file: UploadFile) => void,
69
+ ): Promise<void> {
70
+ if (!fileList.length) return;
71
+
72
+ if (fileList.length === 0) {
73
+ message.warning('请选择上传的文件!');
74
+ return;
75
+ }
76
+
77
+ loading.value = true;
78
+
79
+ // 开始上传文件
80
+ await this.uploadFiles(fileList, onProgress, (files) => {
81
+ let result = false;
82
+ let err_count = 0;
83
+ for (const file of files) {
84
+ if (file.status === UploadStatus.Error) {
85
+ err_count++;
86
+ }
87
+ }
88
+ if (!err_count) {
89
+ message.success('全部文件上传成功!');
90
+ result = true;
91
+ } else if (err_count < files.length) {
92
+ if (continueOnError) {
93
+ message.error('上传结束,部分文件上传失败!');
94
+ message.warning('保存上传成功的文件!');
95
+ result = true;
96
+ } else {
97
+ message.error('上传结束,部分文件上传失败,取消保存!');
98
+ }
99
+ } else message.error('上传结束,所有文件上传失败!');
100
+
101
+ loading.value = false;
102
+ onComplete?.(result, files);
103
+ });
104
+ }
105
+
52
106
  /**
53
107
  * 上传多个文件,控制并发数量
54
108
  * @param files 文件列表(File[] 或 FileList)
55
109
  * @param onProgress 上传进度回调
56
110
  * @param onComplete 上传完成回调
57
111
  */
58
- public async uploadFiles(
112
+ private async uploadFiles(
59
113
  fileList: UploadFile[],
60
114
  onProgress?: (file: UploadFile) => void,
61
115
  onComplete?: (files: UploadFile[]) => void,
@@ -93,7 +147,6 @@ export class AsyncUploader {
93
147
 
94
148
  // 等待所有上传任务完成
95
149
  await Promise.all(activeUploads);
96
- onComplete?.(fileList);
97
150
  } catch (error) {
98
151
  console.error('上传失败:', error);
99
152
  fileList.forEach((file) => {
@@ -101,6 +154,7 @@ export class AsyncUploader {
101
154
  file.error = error instanceof Error ? error : new Error('上传失败');
102
155
  onProgress?.(file);
103
156
  });
157
+ } finally {
104
158
  onComplete?.(fileList);
105
159
  }
106
160
  }
@@ -119,19 +173,11 @@ export class AsyncUploader {
119
173
  onProgress?: (file: UploadFile) => void,
120
174
  ): Promise<void> {
121
175
  try {
122
- // 更新文件状态为"正在上传"
123
- file.status = UploadStatus.Uploading;
124
-
125
176
  await this.uploadFile(file, this.abortController!.signal, (percent) => {
126
177
  file.percent = percent;
127
178
  onProgress?.(file);
128
179
  });
129
-
130
- // 更新文件状态为"上传成功"
131
- file.status = UploadStatus.Success;
132
180
  } catch (error) {
133
- // 更新文件状态为"上传失败"
134
- file.status = UploadStatus.Error;
135
181
  file.error = error instanceof Error ? error : new Error('上传失败');
136
182
  console.error(file.error);
137
183
  } finally {
@@ -156,6 +202,9 @@ export class AsyncUploader {
156
202
  signal: AbortSignal,
157
203
  onProgress: (percent: number) => void,
158
204
  ): Promise<UploadFile> {
205
+ // 更新文件状态为"正在上传"
206
+ file.status = UploadStatus.Uploading;
207
+
159
208
  // 以 Promise 化的方式处理上传请求
160
209
  return new Promise((resolve, reject) => {
161
210
  // 创建表单数据
@@ -172,7 +221,7 @@ export class AsyncUploader {
172
221
  // 创建 XMLHttpRequest 对象
173
222
  const xhr = new XMLHttpRequest();
174
223
  const url = hostUrl(this.urlInfo);
175
- if (url === false) return Promise.resolve(null);
224
+ if (url === false) return Promise.resolve(file);
176
225
  xhr.open('POST', url, true);
177
226
 
178
227
  // 设置请求头
@@ -222,22 +271,32 @@ export class AsyncUploader {
222
271
  file.minioFile = {
223
272
  ETag: res.data.ETag,
224
273
  Bucket: res.data.Bucket,
274
+ FileName: file.fileName,
225
275
  Key: res.data.Key,
226
276
  Size: res.data.Size,
277
+ Type: file.type,
227
278
  UpdateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
228
- Status: UploadStatus.Online,
279
+ Status: UploadStatus.Success,
229
280
  };
281
+ // 更新文件状态为"上传成功"
282
+ file.status = UploadStatus.Success;
230
283
  resolve(file); // 上传成功,返回解析后的 JSON 数据
231
284
  } else {
232
285
  // 如果 status 不是 success,则视为失败,提取 msg 作为错误信息
233
286
  const error = res.msg;
287
+ // 更新文件状态为"上传失败"
288
+ file.status = UploadStatus.Error;
234
289
  reject(new Error(error));
235
290
  }
236
291
  } catch (error) {
292
+ // 更新文件状态为"上传失败"
293
+ file.status = UploadStatus.Error;
237
294
  // 如果 JSON 格式无效,抛出错误
238
295
  reject(new Error('无法解析返回的 JSON 数据: ' + error));
239
296
  }
240
297
  } else {
298
+ // 更新文件状态为"上传失败"
299
+ file.status = UploadStatus.Error;
241
300
  // 根据 HTTP 状态码判断上传失败的原因
242
301
  reject(new Error(`上传失败,状态码:${xhr.status}`));
243
302
  }
@@ -245,6 +304,8 @@ export class AsyncUploader {
245
304
 
246
305
  // 监听网络错误事件
247
306
  xhr.addEventListener('error', () => {
307
+ // 更新文件状态为"上传失败"
308
+ file.status = UploadStatus.Error;
248
309
  reject(new Error('上传失败,网络异常'));
249
310
  });
250
311
 
@@ -268,7 +329,6 @@ export class AsyncUploader {
268
329
  }
269
330
  }
270
331
  }
271
-
272
332
  // // 使用示例
273
333
  // (async () => {
274
334
  // // 创建上传器实例,指定 API 配置和最大并发数
@@ -302,3 +362,4 @@ export class AsyncUploader {
302
362
  // console.error('上传错误:', error);
303
363
  // }
304
364
  // })();
365
+
@@ -6,6 +6,7 @@ import { isEmpty } from './isEmpty';
6
6
  import message from 'vue-m-message';
7
7
  import { ValidateRule } from '@/typings/form';
8
8
  import { validMessages } from './form-validate';
9
+ import { UploadFile } from '@/typings/upload';
9
10
 
10
11
  /**
11
12
  * Excel数据处理需要标记的单元格
@@ -44,7 +45,10 @@ export const processExcelFile = async (excelBuffer: ArrayBuffer) => {
44
45
 
45
46
  // 提取表头和数据
46
47
  const headers: string[] = [];
48
+ // 表头对象数据行
47
49
  const excelData: Record<string, any>[] = [];
50
+ // 纯数据行
51
+ const excelRows: any[][] = [];
48
52
 
49
53
  // 提取表头(第一行)
50
54
  worksheet.getRow(1).eachCell((cell) => {
@@ -86,6 +90,7 @@ export const processExcelFile = async (excelBuffer: ArrayBuffer) => {
86
90
  if (rowNumber > 1) {
87
91
  // 跳过表头
88
92
  const rowData: Record<string, any> = {};
93
+ const rowDataArray: any[] = [];
89
94
  headers.forEach((header, idx) => {
90
95
  if (header) {
91
96
  const cell = row.getCell(idx + 1);
@@ -116,13 +121,15 @@ export const processExcelFile = async (excelBuffer: ArrayBuffer) => {
116
121
  } else {
117
122
  rowData[header] = null;
118
123
  }
124
+ rowDataArray.push(rowData[header]);
119
125
  }
120
126
  });
121
127
  excelData.push(rowData);
128
+ excelRows.push(rowDataArray);
122
129
  }
123
130
  });
124
131
 
125
- return { workbook, worksheet, headers, excelData };
132
+ return { workbook, worksheet, headers, excelData, excelRows };
126
133
  };
127
134
 
128
135
  /**
@@ -521,3 +528,45 @@ export const checkExcelDuplicates = async (
521
528
 
522
529
  return { hasError: false }; // 没有重复数据
523
530
  };
531
+
532
+ /**
533
+ * 将Excel数据追加到fileData中
534
+ * @param fileInfo 文件信息
535
+ * @param fileData 文件数据
536
+ * @param key 文件数据对象的键
537
+ * @param fields 需要追加的字段
538
+ * @returns
539
+ */
540
+ export const appendExcelData = async (fileInfo: UploadFile, fileData: Record<string, any>, fields?: string[]) => {
541
+ const file = fileInfo.originFileObj as File;
542
+ if (file) {
543
+ // 使用ArrayBuffer读取文件
544
+ const buffer = await file.arrayBuffer();
545
+ // 获取Excel数据,并转换成指定数据对象结构
546
+ const excelFileData = await processExcelFile(buffer);
547
+ if (!excelFileData) {
548
+ message.error('上传的文件不是Excel文件');
549
+ return;
550
+ }
551
+ const { headers, excelRows, excelData } = excelFileData;
552
+ if (fields && fields.length > 0) {
553
+ fields.forEach((field) => {
554
+ switch (field) {
555
+ case 'Headers':
556
+ fileData.Headers = headers;
557
+ break;
558
+ case 'RawRows':
559
+ fileData.RawRows = excelRows;
560
+ break;
561
+ case 'Records':
562
+ fileData.Records = excelData;
563
+ break;
564
+ }
565
+ });
566
+ } else {
567
+ fileData.Headers = headers;
568
+ fileData.RawRows = excelRows;
569
+ fileData.Records = excelData;
570
+ }
571
+ }
572
+ };
@@ -2,7 +2,7 @@ import { inject, toRaw, ref, provide, watch, Ref } from 'vue';
2
2
  import Validator from 'async-validator';
3
3
  import { EditorControl, InputFactoryItems, ValidateError, ValidateRule } from '@/typings/form.d';
4
4
  import { ProviderKeys } from '@/typings/page.d';
5
- import { AnyData} from '@skyfox2000/fapi';
5
+ import { AnyData } from '@skyfox2000/fapi';
6
6
  import { isEmpty } from './isEmpty';
7
7
 
8
8
  export let validMessages: Validator;
@@ -171,6 +171,23 @@ export const getRuleTexts = (rules?: Record<string, ValidateRule>) => {
171
171
  /**
172
172
  * 表单数据验证
173
173
  * @param editorCtrl 表单控制对象
174
+ * @example 规则示例
175
+ * {
176
+ * Name: {
177
+ * required: true,
178
+ * message: '请输入站点名称',
179
+ * },
180
+ * Files: {
181
+ * type: 'object',
182
+ * fields: {
183
+ * dev_list: {
184
+ * type: 'array',
185
+ * min: 1,
186
+ * message: '请上传端口配置表',
187
+ * },
188
+ * },
189
+ * },
190
+ * }
174
191
  */
175
192
  export const formValidate = async <T>(editorCtrl: EditorControl<T>) => {
176
193
  const formData: Record<string, AnyData> = editorCtrl.formData.value as Record<string, AnyData>;
package/src/utils/form.ts CHANGED
@@ -29,6 +29,7 @@ export const onFormSaveAs = <T>(editorCtrl: EditorControl<T>) => {
29
29
  * @param pageCtrl 页面控制对象
30
30
  */
31
31
  export const onFormClose = <T>(editorCtrl: EditorControl<T>) => {
32
+ resetForm(editorCtrl);
32
33
  editorCtrl.visible.value = false;
33
34
  };
34
35
 
@@ -174,7 +175,8 @@ export const openNewForm = <T>(editorCtrl: EditorControl<T>) => {
174
175
  */
175
176
  export const setFormData = <T>(editorCtrl: EditorControl<T>, formData?: T) => {
176
177
  resetForm(editorCtrl);
177
- editorCtrl.formData.value = { ...editorCtrl.formData.value, ...formData } as T;
178
+ const newFormData = { ...editorCtrl.formData.value, ...formData };
179
+ editorCtrl.formData.value = JSON.parse(JSON.stringify(newFormData)) as T;
178
180
  };
179
181
 
180
182
  /**
@@ -37,11 +37,12 @@ export const loadOption = (
37
37
  ) => {
38
38
  if (inputFactory && props.reloadEvent) {
39
39
  /// 接收事件,联动显示或者重新加载数据
40
- inputFactory.reloadHandler = (_event: string, data: Record<string, AnyData> | AnyData[]) => {
41
- optionEventHandler(url!, props, data, options);
40
+ inputFactory.reloadHandler = (_event: string, params: Record<string, AnyData> | AnyData[]) => {
41
+ optionEventHandler(url!, props, params, options);
42
42
  };
43
43
  eventBus.on(props.reloadEvent, inputFactory.reloadHandler);
44
44
  }
45
+
45
46
  if (props.data) {
46
47
  watch(
47
48
  () => props.data,
@@ -106,13 +107,15 @@ const updateOptions = (
106
107
  const optionEventHandler = (
107
108
  url: IUrlInfo,
108
109
  props: OptionProps,
109
- data: Record<string, AnyData> | AnyData[],
110
+ params_data: Record<string, AnyData> | AnyData[],
110
111
  options: Ref<OptionItemProps[]>,
111
112
  ) => {
112
- if (Array.isArray(data)) {
113
- updateOptions(props, data, options, true);
113
+ if (Array.isArray(params_data)) {
114
+ // 数据组仅用于联动显示
115
+ updateOptions(props, params_data, options, true);
114
116
  } else {
115
- doQueryOptions(url, props, { Query: data }, options);
117
+ // 其它情况使用Query参数
118
+ doQueryOptions(url, props, params_data, options);
116
119
  }
117
120
  };
118
121
 
@@ -134,7 +137,7 @@ export const unloadOption = (props: OptionProps, inputFactory?: InputFactoryItem
134
137
  * @param options 实际选择项
135
138
  */
136
139
  const doQueryOptions = (url: IUrlInfo, props: OptionProps, params: ReqParams, options: Ref<OptionItemProps[]>) => {
137
- const newParams: ReqParams = combineParams(url.params, params, props.params);
140
+ const newParams: ReqParams = combineParams(url.params, props.params, params);
138
141
  queryOptions(url, props.fieldMap, newParams).then((results) => {
139
142
  // 使用url,由request负责转换,无需再次map转换
140
143
  const data = results as OptionItemProps[];
@@ -295,12 +298,35 @@ export const onOptionChanged = (
295
298
  }
296
299
 
297
300
  if (props.changeEvent) {
298
- if (Array.isArray(props.changeEvent)) {
299
- props.changeEvent.every((changeEvent: string) => {
300
- eventBus.emit(changeEvent, values, selectedValues);
301
- });
301
+ const [eventNames, eventParams] = props.changeEvent;
302
+ if (eventParams) {
303
+ if (Array.isArray(eventNames)) {
304
+ eventNames.every((eventName: string) => {
305
+ const eventParamsValue = parseFieldTemplate(eventParams, { selectedValues: values });
306
+ try {
307
+ const eventJsonValue = JSON.parse(eventParamsValue);
308
+ eventBus.emit(eventName, eventJsonValue, values, selectedValues);
309
+ } catch (error) {
310
+ console.error('eventParamsValue: ', eventParamsValue, error);
311
+ }
312
+ });
313
+ } else {
314
+ const eventParamsValue = parseFieldTemplate(eventParams, { selectedValues: values });
315
+ try {
316
+ const eventJsonValue = JSON.parse(eventParamsValue);
317
+ eventBus.emit(eventNames, eventJsonValue, values, selectedValues);
318
+ } catch (error) {
319
+ console.error('eventParamsValue: ', eventParamsValue, error);
320
+ }
321
+ }
302
322
  } else {
303
- eventBus.emit(props.changeEvent, values, selectedValues);
323
+ if (Array.isArray(eventNames)) {
324
+ eventNames.every((eventName: string) => {
325
+ eventBus.emit(eventName, selectedValues, values);
326
+ });
327
+ } else {
328
+ eventBus.emit(eventNames, selectedValues, values);
329
+ }
304
330
  }
305
331
  }
306
332
  // 触发 inputFactory 的 change 事件