@skyfox2000/webui 1.3.1 → 1.3.3

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 (37) hide show
  1. package/lib/assets/modules/{file-upload-Ce5MFm6o.js → file-upload-D4Pqs8h3.js} +1 -1
  2. package/lib/assets/modules/{form-excel-Bq-9rkHa.js → form-excel-D1vXB4c4.js} +1 -1
  3. package/lib/assets/modules/{index-B8uZAVPS.js → index-CSnwbbQT.js} +2 -2
  4. package/lib/assets/modules/{index-CrAJ72MK.js → index-V1j9haWy.js} +1 -1
  5. package/lib/assets/modules/{menuTabs-DEq88ENK.js → menuTabs-e8XoJN7m.js} +2 -2
  6. package/lib/assets/modules/{toolIcon-OGhmNg0x.js → toolIcon-BSF7eiPf.js} +1 -1
  7. package/lib/assets/modules/uploadList-Bcf7g1bf.js +382 -0
  8. package/lib/assets/modules/{uploadList-BzBJXttS.js → uploadList-DA4TRDWR.js} +686 -712
  9. package/lib/components/form/autoComplete/index.vue.d.ts +10 -48
  10. package/lib/components/form/upload/uploadList.vue.d.ts +1 -0
  11. package/lib/es/AceEditor/index.js +3 -3
  12. package/lib/es/BasicLayout/index.js +3 -3
  13. package/lib/es/Error403/index.js +1 -1
  14. package/lib/es/Error404/index.js +1 -1
  15. package/lib/es/ExcelForm/index.js +4 -4
  16. package/lib/es/UploadForm/index.js +4 -4
  17. package/lib/index.d.ts +1 -1
  18. package/lib/typings/option.d.ts +3 -2
  19. package/lib/utils/download.d.ts +2 -0
  20. package/lib/utils/options.d.ts +1 -1
  21. package/lib/webui.css +1 -1
  22. package/lib/webui.es.js +275 -273
  23. package/package.json +1 -1
  24. package/src/components/content/table/index.vue +22 -10
  25. package/src/components/form/autoComplete/index.vue +29 -60
  26. package/src/components/form/cascader/index.vue +1 -1
  27. package/src/components/form/checkbox/index.vue +1 -1
  28. package/src/components/form/radio/index.vue +1 -1
  29. package/src/components/form/select/index.vue +1 -9
  30. package/src/components/form/switch/index.vue +1 -1
  31. package/src/components/form/upload/uploadList.vue +50 -11
  32. package/src/index.ts +1 -1
  33. package/src/typings/option.d.ts +3 -2
  34. package/src/utils/download.ts +31 -0
  35. package/src/utils/options.ts +15 -26
  36. package/src/utils/page.ts +39 -4
  37. package/lib/assets/modules/uploadList-DzK2YNwb.js +0 -327
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyfox2000/webui",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "后台前端通用组件定义",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -67,7 +67,7 @@ const curPageSize = ref(gridCtrl.pageSize.value);
67
67
  const curPageNo = ref(gridCtrl.pageNo.value);
68
68
 
69
69
  const dataList = ref<Record<string, AnyData>[]>([]);
70
- const pagination: Ref<TablePaginationConfig> = ref<TablePaginationConfig>({
70
+ const pagination: Ref<false | TablePaginationConfig> = ref<false | TablePaginationConfig>({
71
71
  ...{
72
72
  total: 0,
73
73
  current: 1,
@@ -76,8 +76,10 @@ const pagination: Ref<TablePaginationConfig> = ref<TablePaginationConfig>({
76
76
  return `共 ${total} 条记录`;
77
77
  },
78
78
  onChange: (page: number, pageSize: number) => {
79
- pagination.value.current = page;
80
- pagination.value.pageSize = pageSize;
79
+ if (pagination.value !== false) {
80
+ pagination.value.current = page;
81
+ pagination.value.pageSize = pageSize;
82
+ }
81
83
  curPageSize.value = pageSize;
82
84
  curPageNo.value = page;
83
85
  if (gridCtrl) {
@@ -90,14 +92,20 @@ const pagination: Ref<TablePaginationConfig> = ref<TablePaginationConfig>({
90
92
  ...props.pagination,
91
93
  });
92
94
 
95
+ if (props.pagination === false) {
96
+ pagination.value = false;
97
+ }
98
+
93
99
  watch(
94
100
  () => gridCtrl.tableData.value,
95
101
  (newVal) => {
96
102
  if (newVal) {
97
103
  dataList.value = newVal;
98
- pagination.value.total = gridCtrl.total.value ?? 0;
99
- pagination.value.current = gridCtrl.pageNo.value ?? 1;
100
- pagination.value.pageSize = gridCtrl.pageSize.value ?? 10;
104
+ if (pagination.value !== false) {
105
+ pagination.value.total = gridCtrl.total.value ?? 0;
106
+ pagination.value.current = gridCtrl.pageNo.value ?? 1;
107
+ pagination.value.pageSize = gridCtrl.pageSize.value ?? 10;
108
+ }
101
109
  }
102
110
  },
103
111
  { immediate: true },
@@ -108,9 +116,11 @@ watch(
108
116
  (newVal) => {
109
117
  if (newVal) {
110
118
  dataList.value = newVal;
111
- pagination.value.total = newVal.length;
112
- pagination.value.current = gridCtrl.pageNo.value ?? 1;
113
- pagination.value.pageSize = gridCtrl.pageSize.value ?? 10;
119
+ if (pagination.value !== false) {
120
+ pagination.value.total = newVal.length;
121
+ pagination.value.current = gridCtrl.pageNo.value ?? 1;
122
+ pagination.value.pageSize = gridCtrl.pageSize.value ?? 10;
123
+ }
114
124
  }
115
125
  },
116
126
  { immediate: true },
@@ -162,7 +172,9 @@ onMounted(async () => {
162
172
  if (gridCtrl.tableData.value) {
163
173
  dataList.value = gridCtrl.tableData.value;
164
174
  gridCtrl.total.value = dataList.value.length;
165
- pagination.value.total = gridCtrl.total.value ?? 0;
175
+ if (pagination.value !== false) {
176
+ pagination.value.total = gridCtrl.total.value ?? 0;
177
+ }
166
178
  } else if (gridCtrl.autoload !== false) {
167
179
  if (gridCtrl.remotePage) {
168
180
  dataList.value = (await gridQueryFind(gridCtrl)).rows;
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, useAttrs, watch, shallowRef } from 'vue';
2
+ import { ref, onUnmounted, useAttrs, watch, shallowRef, PropType } from 'vue';
3
3
  import { AutoComplete } from 'ant-design-vue';
4
4
  import {
5
5
  useInputFactory,
@@ -13,35 +13,23 @@ import {
13
13
  formValidate,
14
14
  outFormDataFields,
15
15
  } from '@/index';
16
- import { ReqParams, IUrlInfo } from '@skyfox2000/fapi';
16
+ import { ReqParams } from '@skyfox2000/fapi';
17
17
  import { useOptionFactory } from '@/utils/page';
18
+ import { combineParams } from '@skyfox2000/microbase';
18
19
 
19
20
  const props = defineProps({
20
21
  ...OptionCommProps,
21
22
  value: {
22
- type: [String, Number, null, Array],
23
+ type: [String, Number, Array, null] as PropType<string | number | string[] | null>,
23
24
  default: undefined,
24
25
  },
25
- /**
26
- * 查询字段
27
- * - 模糊查询
28
- */
29
- searchField: {
30
- type: [String, Array<string>],
31
- },
32
- /**
33
- * 自定义查询参数
34
- * - 查询参数
35
- * - query参数
36
- */
37
- onsearch: {
38
- type: Function,
39
- },
40
26
  /**
41
27
  * 修改输入数据则自动清空关联数据
28
+ * - FormData: 表单数据
29
+ * - outFields: 输出字段
42
30
  */
43
31
  autoClean: {
44
- type: Boolean,
32
+ type: Boolean as PropType<boolean>,
45
33
  default: true,
46
34
  },
47
35
  });
@@ -56,14 +44,18 @@ const inputFactory = useInputFactory();
56
44
  const defaultCtrl = useOptionFactory(props.url, props);
57
45
  const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
58
46
  optionCtrl.inputFactory = shallowRef(inputFactory);
59
-
60
- const url = ref<IUrlInfo>({
61
- ...optionCtrl?.url,
62
- url: optionCtrl?.url?.url || '',
63
- fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
64
- params: optionCtrl?.params || optionCtrl?.url?.params,
65
- loadingText: false,
66
- });
47
+ /***
48
+ * 默认字段映射
49
+ * - label: 显示字段 支持模板 ${}
50
+ * - value: 值字段
51
+ */
52
+ optionCtrl.fieldMap = {
53
+ ...{
54
+ label: 'Name',
55
+ value: 'Id',
56
+ },
57
+ ...optionCtrl?.fieldMap,
58
+ };
67
59
 
68
60
  /// 避免类型错误
69
61
  const innerValue = ref<SelectValue | undefined>(optionCtrl?.selected.value || undefined);
@@ -103,7 +95,7 @@ if (optionCtrl) {
103
95
  (newOptions) => {
104
96
  selectOptions.value = newOptions || [];
105
97
  },
106
- { immediate: true, deep: true }
98
+ { immediate: true, deep: true },
107
99
  );
108
100
  }
109
101
 
@@ -112,29 +104,14 @@ const onSearch = (value: string) => {
112
104
  if (value === '') return;
113
105
  let search_value = value.trim();
114
106
  let query: ReqParams = {
115
- ...url.value.params,
116
107
  Query: {
117
- ...url.value.params?.Query,
108
+ SearchField: '%' + search_value + '%',
118
109
  },
119
110
  };
120
- if (props.searchField) {
121
- if (Array.isArray(props.searchField)) {
122
- props.searchField.forEach((field) => {
123
- query.Query![field] = {
124
- $like: '%' + search_value + '%',
125
- };
126
- });
127
- } else {
128
- query.Query![props.searchField] = {
129
- $like: '%' + search_value + '%',
130
- };
131
- }
132
- }
133
- if (props.onsearch) {
134
- props.onsearch(search_value, query);
135
- }
136
111
 
137
- if (optionCtrl) loadOption(optionCtrl, props);
112
+ optionCtrl.params = combineParams(optionCtrl.params, query);
113
+
114
+ if (optionCtrl) loadOption(true, optionCtrl, props);
138
115
  };
139
116
 
140
117
  const onSelected = (value: any) => {
@@ -153,17 +130,6 @@ const onSelected = (value: any) => {
153
130
  }
154
131
  };
155
132
 
156
- onMounted(() => {
157
- if (url.value && !url.value.fieldMap) {
158
- url.value.fieldMap = {
159
- title: 'Name',
160
- label: 'Name',
161
- value: 'Name',
162
- key: 'Id',
163
- };
164
- }
165
- });
166
-
167
133
  onUnmounted(() => {
168
134
  if (optionCtrl) unloadOption(optionCtrl, props);
169
135
  });
@@ -173,13 +139,16 @@ onUnmounted(() => {
173
139
  <div>
174
140
  <AutoComplete
175
141
  v-model:value="innerValue"
176
- :class="[errInfo?.errClass, 'error w-full']"
142
+ :class="['w-full', errInfo?.errClass]"
177
143
  :options="selectOptions"
178
144
  @search="onSearch"
179
145
  @select="onSelected"
180
- :placeholder="optionCtrl?.url?.loading ? '请输入并选择' + labelText : ''"
146
+ :placeholder="'请输入并选择' + labelText"
181
147
  v-bind="attrs"
182
148
  >
149
+ <template #option="{ label }">
150
+ {{ label }}
151
+ </template>
183
152
  </AutoComplete>
184
153
  </div>
185
154
  </template>
@@ -93,7 +93,7 @@ onMounted(() => {
93
93
  key: 'Id',
94
94
  };
95
95
  }
96
- if (optionCtrl) loadOption(optionCtrl, props);
96
+ if (optionCtrl) loadOption(optionCtrl.autoload, optionCtrl, props);
97
97
  });
98
98
 
99
99
  onUnmounted(() => {
@@ -84,7 +84,7 @@ onMounted(() => {
84
84
  key: 'Id',
85
85
  };
86
86
  }
87
- if (optionCtrl) loadOption(optionCtrl, props);
87
+ if (optionCtrl) loadOption(optionCtrl.autoload, optionCtrl, props);
88
88
  });
89
89
  onUnmounted(() => {
90
90
  if (optionCtrl) unloadOption(optionCtrl, props);
@@ -102,7 +102,7 @@ onMounted(() => {
102
102
  key: 'Id',
103
103
  };
104
104
  }
105
- if (optionCtrl) loadOption(optionCtrl, props);
105
+ if (optionCtrl) loadOption(optionCtrl.autoload, optionCtrl, props);
106
106
  });
107
107
  onUnmounted(() => {
108
108
  if (optionCtrl) unloadOption(optionCtrl, props);
@@ -135,14 +135,6 @@ watch(
135
135
  },
136
136
  );
137
137
 
138
- // watch(
139
- // () => props.params,
140
- // (newVal) => {
141
- // loadOption(true, props, selectOptions, inputFactory, url.value, newVal);
142
- // },
143
- // { deep: true },
144
- // );
145
-
146
138
  onMounted(() => {
147
139
  if (url.value && !url.value.fieldMap) {
148
140
  url.value.fieldMap = {
@@ -154,7 +146,7 @@ onMounted(() => {
154
146
  if (props.dataKey) {
155
147
  const options = JSON.parse(JSON.stringify(OPTIONS.getOptions(props.dataKey)));
156
148
  selectOptions.value = options;
157
- } else if (optionCtrl) loadOption(optionCtrl, props);
149
+ } else if (optionCtrl) loadOption(optionCtrl.autoload, optionCtrl, props);
158
150
  });
159
151
 
160
152
  onUnmounted(() => {
@@ -55,7 +55,7 @@ onMounted(() => {
55
55
  message.error('Switch组件必须有且只有两个选项');
56
56
  return;
57
57
  }
58
- if (optionCtrl) loadOption(optionCtrl, props);
58
+ if (optionCtrl) loadOption(optionCtrl.autoload, optionCtrl, props);
59
59
  });
60
60
 
61
61
  onUnmounted(() => {
@@ -4,7 +4,7 @@ import { computed, ref, watch } from 'vue';
4
4
  import message from 'vue-m-message';
5
5
  import type { UploadProps } from 'ant-design-vue';
6
6
  import { Upload, Progress, Tag, Popconfirm } from 'ant-design-vue';
7
- import { UploadFile, UploadStatus, donwloadFromMinio, path, Switch } from '@/index';
7
+ import { UploadFile, UploadStatus, donwloadFromMinio, path, Switch, previewFromMinio } from '@/index';
8
8
  import { useInputFactory } from '@/utils/form-validate';
9
9
  import { IUrlInfo } from '@skyfox2000/fapi';
10
10
 
@@ -22,6 +22,10 @@ export interface UploadListProps {
22
22
  * 下载Url
23
23
  */
24
24
  downloadUrl?: IUrlInfo;
25
+ /**
26
+ * 预览Url
27
+ */
28
+ previewUrl?: IUrlInfo;
25
29
  /**
26
30
  * 文件列表
27
31
  */
@@ -168,12 +172,11 @@ watch(
168
172
  );
169
173
 
170
174
  const downloadFile = (index: number) => {
171
- if (!props.downloadUrl) return;
172
175
  const minioFile = fileList.value[index].minioFile!;
173
176
  const url: IUrlInfo = {
174
- api: props.downloadUrl.api,
175
- authorize: props.downloadUrl.authorize,
176
- url: props.downloadUrl.url,
177
+ api: props.downloadUrl!.api,
178
+ authorize: props.downloadUrl!.authorize,
179
+ url: props.downloadUrl!.url,
177
180
  params: {
178
181
  Query: {
179
182
  FileKey: minioFile.Key,
@@ -190,10 +193,21 @@ const onlineOrOffline = (file: UploadFile) => {
190
193
  }
191
194
  };
192
195
 
193
- // const previewFile = (index: number) => {
194
- // const fileInfo = internalFileList.value[index].minioFile;
195
- // console.log(fileInfo);
196
- // };
196
+ const previewFile = (index: number) => {
197
+ const minioFile = fileList.value[index].minioFile!;
198
+ const url: IUrlInfo = {
199
+ api: props.previewUrl!.api,
200
+ authorize: props.previewUrl!.authorize,
201
+ url: props.previewUrl!.url,
202
+ params: {
203
+ Query: {
204
+ FileKey: minioFile.Key,
205
+ },
206
+ },
207
+ };
208
+
209
+ previewFromMinio(url, minioFile.FileName!);
210
+ };
197
211
 
198
212
  const removeFile = (index: number) => {
199
213
  fileList.value.splice(index, 1);
@@ -322,7 +336,26 @@ const getStatus = (status?: UploadStatus) => {
322
336
  >
323
337
  </Tooltip>
324
338
  </div>
325
- <!-- <span class="text-blue-500 hover:text-blue-700 mr-4" @click="previewFile(index)">预览</span> -->
339
+ <div
340
+ class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
341
+ v-if="previewUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)"
342
+ >
343
+ <Tooltip title="预览">
344
+ <ToolIcon
345
+ icon="icon-eye"
346
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:preview' }"
347
+ clickable
348
+ @click="previewFile(index)"
349
+ />
350
+ <span
351
+ v-if="showActionText"
352
+ class="mr-2 text-sm text-nowrap"
353
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:preview' }"
354
+ @click="previewFile(index)"
355
+ >预览</span
356
+ >
357
+ </Tooltip>
358
+ </div>
326
359
  <div class="flex items-center text-red-500 hover:text-red-700 cursor-pointer">
327
360
  <Popconfirm
328
361
  v-model:open="confirmOpen"
@@ -356,7 +389,13 @@ const getStatus = (status?: UploadStatus) => {
356
389
  </div>
357
390
 
358
391
  <!-- 上传进度条 -->
359
- <div v-if="file.status !== UploadStatus.Online && file.status !== UploadStatus.Offline && file.status !== UploadStatus.Success">
392
+ <div
393
+ v-if="
394
+ file.status !== UploadStatus.Online &&
395
+ file.status !== UploadStatus.Offline &&
396
+ file.status !== UploadStatus.Success
397
+ "
398
+ >
360
399
  <Progress :percent="file.percent" :stroke-width="2" :show-info="false" style="height: 2px"></Progress>
361
400
  </div>
362
401
  </div>
package/src/index.ts CHANGED
@@ -129,7 +129,7 @@ export {
129
129
  } from '@/utils/options';
130
130
 
131
131
  // download 工具
132
- export { downloadBlob, donwloadFromMinio } from '@/utils/download';
132
+ export { downloadBlob, donwloadFromMinio, previewFromMinio, CanPreviewFileExt } from '@/utils/download';
133
133
 
134
134
  // icon-loader 工具
135
135
  export {
@@ -179,11 +179,12 @@ export type OptionControl = OptionControlOption & {
179
179
  */
180
180
  optionQuery?: ReqParams;
181
181
  /**
182
- * 当前数据
182
+ * 当前传入数据
183
183
  */
184
184
  data: ShallowRef<OptionItemProps[] | undefined>;
185
185
  /**
186
- * 选项数据
186
+ * 实际选项数据
187
+ * - 已转换fieldMap
187
188
  */
188
189
  options: Ref<OptionItemProps[]>;
189
190
  /**
@@ -78,3 +78,34 @@ export const donwloadFromMinio = <T>(url: IUrlInfo, params?: ReqParams, pageCtrl
78
78
  message.error('文件下载失败,请稍后重试');
79
79
  }
80
80
  };
81
+
82
+ export const CanPreviewFileExt = ['xlsx', 'xls', 'csv', 'txt'];
83
+
84
+ export const previewFromMinio = (url: IUrlInfo, fileName: string, params?: ReqParams) => {
85
+ const fileExt = fileName.split('.').pop();
86
+ if (CanPreviewFileExt.includes(fileExt!)) {
87
+ console.log(url);
88
+ } else {
89
+ message.error('文件类型不支持预览');
90
+ return false;
91
+ }
92
+
93
+ const newParams = combineParams(url.params, params);
94
+ return httpPost(url, newParams).then((result: ApiResponse<any> | null) => {
95
+ if (result?.status === ResStatus.SUCCESS && result.data) {
96
+ const minioFile: MinioFile = result.data as unknown as MinioFile;
97
+ // 提取内容和文件名
98
+ const base64String = minioFile.Content!;
99
+
100
+ // 解码 Base64 字符串
101
+ const byteCharacters = atob(base64String);
102
+ const byteArrays = [];
103
+ for (let b = 0; b < byteCharacters.length; b++) {
104
+ byteArrays.push(byteCharacters.charCodeAt(b));
105
+ }
106
+ } else {
107
+ message.error('文件预览失败!');
108
+ }
109
+ return undefined;
110
+ });
111
+ };
@@ -8,7 +8,7 @@ import {
8
8
  ReqParams,
9
9
  ResStatus,
10
10
  } from '@skyfox2000/fapi';
11
- import { inject, ref, Ref, watch } from 'vue';
11
+ import { inject, ref, watch } from 'vue';
12
12
  import { OptionItemProps, SelectValue, OptionControl, OptionProps } from '@/typings/option.d';
13
13
  import { ProviderKeys } from '@/typings/page.d';
14
14
  import message from 'vue-m-message';
@@ -20,12 +20,12 @@ import { combineParams } from '@skyfox2000/microbase';
20
20
  * 自动初始化选择项
21
21
  * @param optionCtrl 选项控制器
22
22
  */
23
- export const loadOption = (optionCtrl: OptionControl, props?: OptionProps) => {
23
+ export const loadOption = (load: boolean, optionCtrl: OptionControl, props?: OptionProps) => {
24
24
  if (optionCtrl.inputFactory && props?.reloadEvent) {
25
25
  const inputFactory = optionCtrl.inputFactory.value;
26
26
  /// 接收事件,联动显示或者重新加载数据
27
27
  inputFactory.reloadHandler = (_event: string, params: Record<string, AnyData> | AnyData[]) => {
28
- optionEventHandler(optionCtrl.url!, optionCtrl, params, optionCtrl.options);
28
+ optionEventHandler(optionCtrl.url!, optionCtrl, params);
29
29
  };
30
30
  eventBus.on(props.reloadEvent, inputFactory.reloadHandler);
31
31
  }
@@ -35,13 +35,12 @@ export const loadOption = (optionCtrl: OptionControl, props?: OptionProps) => {
35
35
  watch(
36
36
  () => props.data,
37
37
  () => {
38
- updateOptions(optionCtrl, props.data!, optionCtrl.options, true);
38
+ updateOptions(optionCtrl, props.data!, true);
39
39
  },
40
40
  { deep: true, immediate: true },
41
41
  );
42
42
  } else if (optionCtrl.url && optionCtrl.url.url) {
43
- if (optionCtrl.autoload !== false)
44
- doQueryOptions(optionCtrl.url, optionCtrl, optionCtrl.params ?? {}, optionCtrl.options);
43
+ if (load) doQueryOptions(optionCtrl.url, optionCtrl, optionCtrl.params ?? {});
45
44
  } else {
46
45
  const labelText = ref<string>(inject(ProviderKeys.LabelText, ''));
47
46
  message.error('`' + labelText.value + '` 未配置选项数据!', {
@@ -54,15 +53,9 @@ export const loadOption = (optionCtrl: OptionControl, props?: OptionProps) => {
54
53
  * 组件选项数据更新
55
54
  * @param optionCtrl 选项控制器
56
55
  * @param data 提供的下拉数据
57
- * @param options 实际选择项
58
56
  * @param mapping 是否需要转换字段
59
57
  */
60
- const updateOptions = (
61
- optionCtrl: OptionControl,
62
- data: Record<string, AnyData>[],
63
- options: Ref<OptionItemProps[]>,
64
- mapping: boolean,
65
- ) => {
58
+ const updateOptions = (optionCtrl: OptionControl, data: Record<string, AnyData>[], mapping: boolean) => {
66
59
  if (mapping) {
67
60
  // 转换字段
68
61
  const fieldMap = {
@@ -79,7 +72,7 @@ const updateOptions = (
79
72
  });
80
73
  }
81
74
 
82
- options.value = data as OptionItemProps[];
75
+ optionCtrl.options.value = data as OptionItemProps[];
83
76
  };
84
77
 
85
78
  /**
@@ -93,14 +86,13 @@ const optionEventHandler = (
93
86
  url: IUrlInfo,
94
87
  optionCtrl: OptionControl,
95
88
  params_data: Record<string, AnyData> | AnyData[],
96
- options: Ref<OptionItemProps[]>,
97
89
  ) => {
98
90
  if (Array.isArray(params_data)) {
99
91
  // 数据组仅用于联动显示
100
- updateOptions(optionCtrl, params_data, options, true);
92
+ updateOptions(optionCtrl, params_data, true);
101
93
  } else {
102
94
  // 其它情况使用Query参数
103
- doQueryOptions(url, optionCtrl, params_data, options);
95
+ doQueryOptions(url, optionCtrl, params_data);
104
96
  }
105
97
  };
106
98
 
@@ -118,21 +110,15 @@ export const unloadOption = (optionCtrl: OptionControl, props: OptionProps) => {
118
110
  * @param url 选项接口
119
111
  * @param optionCtrl 选项控制器
120
112
  * @param params 查询条件
121
- * @param options 实际选择项
122
113
  */
123
- const doQueryOptions = (
124
- url: IUrlInfo,
125
- optionCtrl: OptionControl,
126
- params: ReqParams,
127
- options: Ref<OptionItemProps[]>,
128
- ) => {
114
+ const doQueryOptions = (url: IUrlInfo, optionCtrl: OptionControl, params: ReqParams) => {
129
115
  const urlParams = JSON.parse(JSON.stringify(url.params ?? {}));
130
116
  const ctrlParams = JSON.parse(JSON.stringify(optionCtrl.params ?? {}));
131
117
  const newParams: ReqParams = combineParams(urlParams, ctrlParams, params);
132
118
  queryOptions(url, optionCtrl, optionCtrl.fieldMap, newParams).then((results) => {
133
119
  // 使用url,由request负责转换,无需再次map转换
134
120
  const data = results as OptionItemProps[];
135
- updateOptions(optionCtrl, data, options, false);
121
+ updateOptions(optionCtrl, data, false);
136
122
  });
137
123
  };
138
124
 
@@ -164,8 +150,8 @@ const queryOptions = <T>(
164
150
  url: '',
165
151
  cacheTime: 60000,
166
152
  fieldMap: {
167
- ...fieldMap,
168
153
  ...url.fieldMap,
154
+ ...fieldMap,
169
155
  },
170
156
  };
171
157
  const optionUrl = {
@@ -175,6 +161,7 @@ const queryOptions = <T>(
175
161
  optionUrl.loadingText = false;
176
162
  if (!params) params = {};
177
163
  if (!params.Query) params.Query = {};
164
+ optionCtrl.optionQuery = params;
178
165
  optionCtrl.isOptionLoading.value = true;
179
166
  return httpPost<T>(optionUrl, params)
180
167
  .then((result: ApiResponse<T> | null) => {
@@ -284,9 +271,11 @@ export const onOptionChanged = (
284
271
  if (inputFactory?.editorCtrl && inputFactory.errInfo?.value.errClass) {
285
272
  formValidate(inputFactory.editorCtrl);
286
273
  }
274
+ optionCtrl.selected.value = values as undefined | string | number | string[] | number[];
287
275
 
288
276
  // 获取选中的选项对象或对象数组
289
277
  const selectedValues = getSelectedValues(values, optionCtrl.options.value);
278
+ optionCtrl.selectedOptions.value = selectedValues as OptionItemProps[];
290
279
 
291
280
  // 如果配置了 formData 和 outFields,将选中的其它属性值映射到 formData 上
292
281
  if (props.formData && props.outFields) {
package/src/utils/page.ts CHANGED
@@ -230,12 +230,12 @@ export const useOptionFactory = (url?: IUrlInfo, props?: OptionProps) => {
230
230
  const optionCtrl: OptionControl = {
231
231
  ...defaultOptions.OptionOption,
232
232
  url: url,
233
- options: ref([]),
234
233
  reload: ref(false),
234
+ optionQuery: {},
235
235
  data: shallowRef([]),
236
236
  selected: ref([]),
237
237
  selectedOptions: ref([]),
238
- optionQuery: {},
238
+ options: ref([]),
239
239
  isOptionLoading: ref(false),
240
240
  };
241
241
 
@@ -244,15 +244,50 @@ export const useOptionFactory = (url?: IUrlInfo, props?: OptionProps) => {
244
244
  () => optionCtrl.reload.value,
245
245
  (newVal) => {
246
246
  if (newVal) {
247
- // 使用 nextTick 或 setTimeout 延迟重置值
248
247
  setTimeout(() => {
249
248
  optionCtrl.reload.value = false;
250
249
  }, 1);
251
- loadOption(optionCtrl, props);
250
+ loadOption(true, optionCtrl, props);
252
251
  }
253
252
  },
254
253
  );
255
254
 
255
+ // // 为 optionCtrl 创建响应式的 params 监听
256
+ // // 使用 Proxy 来拦截 params 的设置,确保能够触发响应式更新
257
+ // const originalParams = optionCtrl.params;
258
+ // const paramsRef = ref(originalParams);
259
+
260
+ // // 使用 Object.defineProperty 来拦截 params 的赋值
261
+ // Object.defineProperty(optionCtrl, 'params', {
262
+ // get() {
263
+ // return paramsRef.value;
264
+ // },
265
+ // set(newParams) {
266
+ // paramsRef.value = newParams;
267
+ // },
268
+ // enumerable: true,
269
+ // configurable: true,
270
+ // });
271
+
272
+ // let isInitialized = false;
273
+
274
+ // // 监听params变化,自动重新加载数据
275
+ // watch(
276
+ // () => paramsRef.value,
277
+ // () => {
278
+ // if (!isInitialized) {
279
+ // isInitialized = true;
280
+ // return;
281
+ // }
282
+ // // 确保有URL且params存在时才自动重新加载
283
+ // // 避免重复加载,通过reload状态控制
284
+ // if (!optionCtrl.reload.value) {
285
+ // optionCtrl.reload.value = true;
286
+ // }
287
+ // },
288
+ // { deep: true },
289
+ // );
290
+
256
291
  return {
257
292
  optionCtrl,
258
293
  };