@skyfox2000/webui 1.2.11 → 1.3.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.
Files changed (47) hide show
  1. package/.vscode/settings.json +1 -1
  2. package/lib/assets/modules/{file-upload-CGyzCx7I.js → file-upload-C4GVmWjB.js} +1 -1
  3. package/lib/assets/modules/{form-excel-DWirWVPA.js → form-excel-Cr2hcL1s.js} +3 -3
  4. package/lib/assets/modules/{index-Czk7DDWM.js → index-D5onbqkl.js} +2 -2
  5. package/lib/assets/modules/{index-C1zkNPmi.js → index-DjBruVH-.js} +1 -1
  6. package/lib/assets/modules/{menuTabs-BOax-dro.js → menuTabs-B9fCWfN1.js} +36 -36
  7. package/lib/assets/modules/{toolIcon-vJF7OgP6.js → toolIcon-DKTf30Tq.js} +1 -1
  8. package/lib/assets/modules/{uploadList-DaUjVXLU.js → uploadList-CY57np42.js} +980 -923
  9. package/lib/assets/modules/uploadList-D2lisNHt.js +327 -0
  10. package/lib/components/form/autoComplete/index.vue.d.ts +15 -52
  11. package/lib/components/form/cascader/index.vue.d.ts +16 -56
  12. package/lib/components/form/checkbox/index.vue.d.ts +15 -54
  13. package/lib/components/form/index.d.ts +1 -1
  14. package/lib/components/form/propEditor/index.vue.d.ts +1 -7
  15. package/lib/components/form/radio/index.vue.d.ts +15 -54
  16. package/lib/components/form/select/index.vue.d.ts +15 -60
  17. package/lib/components/form/switch/index.vue.d.ts +62 -29
  18. package/lib/es/AceEditor/index.js +3 -3
  19. package/lib/es/BasicLayout/index.js +6 -6
  20. package/lib/es/Error403/index.js +1 -1
  21. package/lib/es/Error404/index.js +1 -1
  22. package/lib/es/ExcelForm/index.js +37 -37
  23. package/lib/es/UploadForm/index.js +4 -4
  24. package/lib/index.d.ts +1 -1
  25. package/lib/typings/form.d.ts +19 -0
  26. package/lib/typings/option.d.ts +93 -74
  27. package/lib/utils/options.d.ts +4 -7
  28. package/lib/utils/page.d.ts +5 -0
  29. package/lib/webui.css +1 -1
  30. package/lib/webui.es.js +861 -851
  31. package/package.json +17 -17
  32. package/src/components/content/form/formItem.vue +2 -2
  33. package/src/components/form/autoComplete/index.vue +29 -16
  34. package/src/components/form/cascader/index.vue +25 -9
  35. package/src/components/form/checkbox/index.vue +26 -10
  36. package/src/components/form/index.ts +1 -1
  37. package/src/components/form/propEditor/index.vue +6 -21
  38. package/src/components/form/radio/index.vue +26 -10
  39. package/src/components/form/select/index.vue +38 -40
  40. package/src/components/form/switch/index.vue +23 -5
  41. package/src/index.ts +8 -1
  42. package/src/typings/form.d.ts +19 -0
  43. package/src/typings/option.d.ts +93 -73
  44. package/src/utils/form-excel.ts +2 -2
  45. package/src/utils/options.ts +58 -62
  46. package/src/utils/page.ts +41 -0
  47. package/lib/assets/modules/uploadList-BW23uSvi.js +0 -369
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyfox2000/webui",
3
- "version": "1.2.11",
3
+ "version": "1.3.0",
4
4
  "description": "后台前端通用组件定义",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -31,15 +31,15 @@
31
31
  "build:types": "vue-tsc --declaration --emitDeclarationOnly"
32
32
  },
33
33
  "peerDependencies": {
34
+ "@json2csv/plainjs": "^7.0.6",
34
35
  "@skyfox2000/fapi": "^1.1.19",
35
- "@skyfox2000/microbase": "^1.2.1",
36
+ "@skyfox2000/microbase": "^1.2.2",
36
37
  "@vue-office/excel": "^1.7.14",
37
- "@json2csv/plainjs": "^7.0.6",
38
- "async-validator": "^4.2.5",
39
- "exceljs": "^4.4.0",
40
38
  "ace-builds": "^1.42.0",
41
39
  "ant-design-vue": "^4.2.6",
40
+ "async-validator": "^4.2.5",
42
41
  "dayjs": "^1.11.13",
42
+ "exceljs": "^4.4.0",
43
43
  "pinia": "^2.3.0",
44
44
  "pinia-plugin-persistedstate": "^4.2.0",
45
45
  "vue": "^3.5.16",
@@ -49,21 +49,21 @@
49
49
  "vue3-ace-editor": "^2.2.4"
50
50
  },
51
51
  "devDependencies": {
52
- "@types/node": "^22.15.30",
53
- "@vitejs/plugin-vue": "^5.2.4",
54
- "autoprefixer": "^10.4.21",
52
+ "@types/node": "^22.10.2",
53
+ "@vitejs/plugin-vue": "^5.2.1",
54
+ "autoprefixer": "^10.4.20",
55
55
  "esbuild": "^0.19.12",
56
- "eslint": "^9.28.0",
56
+ "eslint": "^9.17.0",
57
57
  "eslint-config-prettier": "^9.1.0",
58
- "eslint-plugin-prettier": "^5.4.1",
59
- "eslint-plugin-vue": "^9.33.0",
60
- "postcss": "^8.5.4",
61
- "prettier": "^3.5.3",
62
- "rollup": "^4.42.0",
58
+ "eslint-plugin-prettier": "^5.2.1",
59
+ "eslint-plugin-vue": "^9.32.0",
60
+ "postcss": "^8.4.49",
61
+ "prettier": "^3.4.2",
62
+ "rollup": "^4.29.1",
63
63
  "tailwindcss": "^3.4.17",
64
- "typescript": "^5.8.3",
65
- "vite": "^6.3.5",
64
+ "typescript": "^5.7.2",
65
+ "vite": "^6.2.3",
66
66
  "vite-plugin-dts": "^4.5.4",
67
- "vue-tsc": "^2.2.10"
67
+ "vue-tsc": "^2.2.0"
68
68
  }
69
69
  }
@@ -35,7 +35,7 @@ defineOptions({
35
35
  const attrs = useAttrs(); // 手动获取 $attrs
36
36
 
37
37
  const editorCtrl = inject(ProviderKeys.EditorControl, undefined) as EditorControl<AnyData> | undefined;
38
- const labelWidth = inject(ProviderKeys.LabelWidth, '85px');
38
+ const labelWidth = inject(ProviderKeys.LabelWidth, '85px') ?? '85px';
39
39
  const errInfo = useFormItemFactory(props, editorCtrl);
40
40
 
41
41
  const visible = ref(false);
@@ -117,7 +117,7 @@ const required = computed(() => {
117
117
  <slot></slot>
118
118
  </div>
119
119
  <span
120
- :style="{ left: labelWidth }"
120
+ :style="{ left: nextLine ? '2px' : labelWidth }"
121
121
  class="absolute bottom-[3px] text-[12px] text-[#ff4d4fcc]"
122
122
  v-if="errInfo.errClass"
123
123
  >
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, useAttrs, watch } from 'vue';
2
+ import { ref, onMounted, onUnmounted, useAttrs, watch, shallowRef } from 'vue';
3
3
  import { AutoComplete } from 'ant-design-vue';
4
4
  import {
5
5
  useInputFactory,
@@ -14,13 +14,10 @@ import {
14
14
  outFormDataFields,
15
15
  } from '@/index';
16
16
  import { ReqParams, IUrlInfo } from '@skyfox2000/fapi';
17
+ import { useOptionFactory } from '@/utils/page';
17
18
 
18
19
  const props = defineProps({
19
20
  ...OptionCommProps,
20
- autoload: {
21
- type: Boolean,
22
- default: false,
23
- },
24
21
  value: {
25
22
  type: [String, Number, null, Array],
26
23
  default: undefined,
@@ -54,16 +51,22 @@ defineOptions({
54
51
  });
55
52
  const attrs = useAttrs(); // 手动获取 $attrs
56
53
 
54
+ const inputFactory = useInputFactory();
55
+
56
+ const defaultCtrl = useOptionFactory(props.url, props);
57
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
58
+ optionCtrl.inputFactory = shallowRef(inputFactory);
59
+
57
60
  const url = ref<IUrlInfo>({
58
- ...props.url,
59
- url: props.url?.url || '',
60
- fieldMap: props.fieldMap || props.url?.fieldMap,
61
- params: props.params || props.url?.params,
61
+ ...optionCtrl?.url,
62
+ url: optionCtrl?.url?.url || '',
63
+ fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
64
+ params: optionCtrl?.params || optionCtrl?.url?.params,
62
65
  loadingText: false,
63
66
  });
64
67
 
65
68
  /// 避免类型错误
66
- const innerValue = ref<SelectValue | undefined>(undefined);
69
+ const innerValue = ref<SelectValue | undefined>(optionCtrl?.selected.value || undefined);
67
70
 
68
71
  watch(
69
72
  () => props.value,
@@ -83,7 +86,6 @@ watch(
83
86
  },
84
87
  );
85
88
 
86
- const inputFactory = useInputFactory();
87
89
  const { editorCtrl, errInfo, labelText } = inputFactory;
88
90
 
89
91
  const emit = defineEmits(['update:value', 'select', 'change', 'update:labels']);
@@ -92,7 +94,18 @@ inputFactory.inputEmit = emit;
92
94
  /**
93
95
  * 实际的选择项
94
96
  */
95
- const selectOptions = ref<OptionItemProps[]>([]);
97
+ const selectOptions = ref<OptionItemProps[]>(optionCtrl?.options.value || []);
98
+
99
+ // 监听 optionCtrl.options 的变化,确保 selectOptions 能响应式更新
100
+ if (optionCtrl) {
101
+ watch(
102
+ () => optionCtrl.options.value,
103
+ (newOptions) => {
104
+ selectOptions.value = newOptions || [];
105
+ },
106
+ { immediate: true, deep: true }
107
+ );
108
+ }
96
109
 
97
110
  const onSearch = (value: string) => {
98
111
  selectOptions.value = [];
@@ -121,11 +134,11 @@ const onSearch = (value: string) => {
121
134
  props.onsearch(search_value, query);
122
135
  }
123
136
 
124
- loadOption(true, props, selectOptions, inputFactory, url.value, query);
137
+ if (optionCtrl) loadOption(optionCtrl, props);
125
138
  };
126
139
 
127
140
  const onSelected = (value: any) => {
128
- const selectedOptions = onOptionChanged(props, value as SelectValue, selectOptions, inputFactory);
141
+ const selectedOptions = onOptionChanged(optionCtrl, props, value as SelectValue);
129
142
 
130
143
  /// 选择后才更新数据
131
144
  emit('update:value', value);
@@ -152,7 +165,7 @@ onMounted(() => {
152
165
  });
153
166
 
154
167
  onUnmounted(() => {
155
- unloadOption(props, inputFactory);
168
+ if (optionCtrl) unloadOption(optionCtrl, props);
156
169
  });
157
170
  </script>
158
171
 
@@ -164,7 +177,7 @@ onUnmounted(() => {
164
177
  :options="selectOptions"
165
178
  @search="onSearch"
166
179
  @select="onSelected"
167
- :placeholder="props.url && !props.url.loading ? '请输入并选择' + labelText : ''"
180
+ :placeholder="optionCtrl?.url?.loading ? '请输入并选择' + labelText : ''"
168
181
  v-bind="attrs"
169
182
  >
170
183
  </AutoComplete>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, useAttrs, watch } from 'vue';
2
+ import { ref, onMounted, onUnmounted, useAttrs, watch, shallowRef } from 'vue';
3
3
  import {
4
4
  circleLoading,
5
5
  useInputFactory,
@@ -12,6 +12,7 @@ import {
12
12
  import { Cascader } from 'ant-design-vue';
13
13
  import { DefaultOptionType, ValueType } from 'ant-design-vue/es/vc-cascader/Cascader';
14
14
  import { IUrlInfo } from '@skyfox2000/fapi';
15
+ import { useOptionFactory } from '@/utils/page';
15
16
 
16
17
  const props = defineProps(OptionCommProps);
17
18
 
@@ -21,15 +22,19 @@ defineOptions({
21
22
  });
22
23
  const attrs = useAttrs(); // 手动获取 $attrs
23
24
 
25
+ const inputFactory = useInputFactory();
26
+ const defaultCtrl = useOptionFactory(props.url, props);
27
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
28
+ optionCtrl.inputFactory = shallowRef(inputFactory);
29
+
24
30
  const url = ref<IUrlInfo>({
25
- ...props.url,
26
- url: props.url?.url || '',
27
- fieldMap: props.fieldMap || props.url?.fieldMap,
28
- params: props.params || props.url?.params,
31
+ ...optionCtrl?.url,
32
+ url: optionCtrl?.url?.url || '',
33
+ fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
34
+ params: optionCtrl?.params || optionCtrl?.url?.params,
29
35
  loadingText: false,
30
36
  });
31
37
 
32
- const inputFactory = useInputFactory();
33
38
  const { editorCtrl, errInfo, labelText } = inputFactory;
34
39
 
35
40
  const placeholder = ref(attrs.placeholder);
@@ -47,7 +52,18 @@ inputFactory.inputEmit = emit;
47
52
  /**
48
53
  * 实际的选择项
49
54
  */
50
- const selectOptions = ref<OptionItemProps[]>([]);
55
+ const selectOptions = ref<OptionItemProps[]>(optionCtrl?.options.value || []);
56
+
57
+ // 监听 optionCtrl.options 的变化,确保 selectOptions 能响应式更新
58
+ if (optionCtrl) {
59
+ watch(
60
+ () => optionCtrl.options.value,
61
+ (newOptions) => {
62
+ selectOptions.value = newOptions || [];
63
+ },
64
+ { immediate: true, deep: true }
65
+ );
66
+ }
51
67
 
52
68
  const onChanged = (_: ValueType, selected: DefaultOptionType[]) => {
53
69
  if (!selected || selected.length === 0) {
@@ -77,11 +93,11 @@ onMounted(() => {
77
93
  key: 'Id',
78
94
  };
79
95
  }
80
- loadOption(props.autoload, props, selectOptions, inputFactory, url.value, url.value.params);
96
+ if (optionCtrl) loadOption(optionCtrl, props);
81
97
  });
82
98
 
83
99
  onUnmounted(() => {
84
- unloadOption(props, inputFactory);
100
+ if (optionCtrl) unloadOption(optionCtrl, props);
85
101
  });
86
102
  </script>
87
103
  <template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, useAttrs } from 'vue';
2
+ import { ref, onMounted, onUnmounted, useAttrs, watch, shallowRef } from 'vue';
3
3
  import { Checkbox, CheckboxGroup } from 'ant-design-vue';
4
4
  import {
5
5
  // circleLoading,
@@ -14,6 +14,7 @@ import {
14
14
  } from '@/index';
15
15
  import { CheckboxValueType } from 'ant-design-vue/es/checkbox/interface';
16
16
  import { IUrlInfo } from '@skyfox2000/fapi';
17
+ import { useOptionFactory } from '@/utils/page';
17
18
 
18
19
  const props = defineProps({
19
20
  ...OptionCommProps,
@@ -37,24 +38,39 @@ defineOptions({
37
38
  });
38
39
  const attrs = useAttrs(); // 手动获取 $attrs
39
40
 
41
+ const inputFactory = useInputFactory();
42
+ const defaultCtrl = useOptionFactory(props.url, props);
43
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
44
+ optionCtrl.inputFactory = shallowRef(inputFactory);
45
+
40
46
  const url = ref<IUrlInfo>({
41
- ...props.url,
42
- url: props.url?.url || '',
43
- fieldMap: props.fieldMap || props.url?.fieldMap,
44
- params: props.params || props.url?.params,
47
+ ...optionCtrl?.url,
48
+ url: optionCtrl?.url?.url || '',
49
+ fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
50
+ params: optionCtrl?.params || optionCtrl?.url?.params,
45
51
  loadingText: false,
46
52
  });
47
53
 
48
- const inputFactory = useInputFactory();
49
54
  const { errInfo } = inputFactory;
50
55
  const emit = defineEmits(['change', 'update:labels']);
51
56
  inputFactory.inputEmit = emit;
52
57
 
53
- const checkboxOptions = ref<OptionItemProps[]>([]);
58
+ const checkboxOptions = ref<OptionItemProps[]>(optionCtrl?.options.value || []);
59
+
60
+ // 监听 optionCtrl.options 的变化,确保 checkboxOptions 能响应式更新
61
+ if (optionCtrl) {
62
+ watch(
63
+ () => optionCtrl.options.value,
64
+ (newOptions) => {
65
+ checkboxOptions.value = newOptions || [];
66
+ },
67
+ { immediate: true, deep: true }
68
+ );
69
+ }
54
70
 
55
71
  const onChanged = (e: CheckboxValueType[]) => {
56
72
  const checkedValue = e;
57
- const selectedOptions = onOptionChanged(props, checkedValue as SelectValue, checkboxOptions, inputFactory);
73
+ const selectedOptions = onOptionChanged(optionCtrl, props, checkedValue as SelectValue);
58
74
  const labels: string[] = getSelectedLabels(selectedOptions);
59
75
  emit('update:labels', labels);
60
76
  };
@@ -68,10 +84,10 @@ onMounted(() => {
68
84
  key: 'Id',
69
85
  };
70
86
  }
71
- loadOption(props.autoload, props, checkboxOptions, inputFactory, url.value, url.value.params);
87
+ if (optionCtrl) loadOption(optionCtrl, props);
72
88
  });
73
89
  onUnmounted(() => {
74
- unloadOption(props, inputFactory);
90
+ if (optionCtrl) unloadOption(optionCtrl, props);
75
91
  });
76
92
  </script>
77
93
  <template>
@@ -23,8 +23,8 @@ import InputNumber from './input/inputNumber.vue';
23
23
  export { InputNumber };
24
24
 
25
25
  import PropEditor from './propEditor/index.vue';
26
- export type { PropConfigItem } from './propEditor/index.vue';
27
26
  export { PropEditor };
27
+ export type { PropConfigItem } from '@/typings/form.d';
28
28
 
29
29
  import Radio from './radio/index.vue';
30
30
  export { Radio };
@@ -1,22 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, watch } from 'vue';
3
3
  import { Input, Button } from 'ant-design-vue';
4
-
5
- export interface PropConfigItem {
6
- id: number;
7
- /**
8
- * 文本
9
- */
10
- text?: string;
11
- /**
12
- * 配置名
13
- */
14
- field: string;
15
- /**
16
- * 配置值
17
- */
18
- value: string;
19
- }
4
+ import type { PropConfigItem } from '@/typings/form.d';
20
5
 
21
6
  const props = defineProps<{
22
7
  /**
@@ -39,15 +24,15 @@ const props = defineProps<{
39
24
  * 值占位符
40
25
  */
41
26
  valueHolder?: string;
42
- /**
43
- * 新增配置行
44
- */
45
- addMore?: boolean;
27
+ // /**
28
+ // * 新增配置行
29
+ // */
30
+ // addMore?: boolean;
46
31
  }>();
47
32
  const emit = defineEmits(['update:value']);
48
33
 
49
34
  // 当有selectList时,不允许添加更多配置项
50
- const addMore = ref(props.selectList && props.selectList.length > 0 ? false : (props.addMore ?? true));
35
+ const addMore = ref(props.selectList && props.selectList.length > 0 ? false : true);
51
36
 
52
37
  const configList = ref<PropConfigItem[]>([]);
53
38
  // 标记是否为内部输入变更
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, watch, useAttrs } from 'vue';
2
+ import { ref, onMounted, onUnmounted, watch, useAttrs, shallowRef } from 'vue';
3
3
  import { Radio, RadioChangeEvent, RadioGroup } from 'ant-design-vue';
4
4
  import {
5
5
  OptionCommProps,
@@ -12,6 +12,7 @@ import {
12
12
  SelectValue,
13
13
  } from '@/index';
14
14
  import { IUrlInfo } from '@skyfox2000/fapi';
15
+ import { useOptionFactory } from '@/utils/page';
15
16
 
16
17
  const props = defineProps({
17
18
  ...OptionCommProps,
@@ -37,23 +38,38 @@ defineOptions({
37
38
  });
38
39
  const attrs = useAttrs(); // 手动获取 $attrs
39
40
 
41
+ const inputFactory = useInputFactory();
42
+ const defaultCtrl = useOptionFactory(props.url, props);
43
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
44
+ optionCtrl.inputFactory = shallowRef(inputFactory);
45
+
40
46
  const url = ref<IUrlInfo>({
41
- ...props.url,
42
- url: props.url?.url || '',
43
- fieldMap: props.fieldMap || props.url?.fieldMap,
44
- params: props.params || props.url?.params,
47
+ ...optionCtrl?.url,
48
+ url: optionCtrl?.url?.url || '',
49
+ fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
50
+ params: optionCtrl?.params || optionCtrl?.url?.params,
45
51
  loadingText: false,
46
52
  });
47
53
 
48
54
  const innerValue = ref(props.value);
49
55
 
50
- const inputFactory = useInputFactory();
51
56
  const { errInfo } = inputFactory;
52
- const radioOptions = ref<OptionItemProps[]>([]);
57
+ const radioOptions = ref<OptionItemProps[]>(optionCtrl?.options.value || []);
53
58
 
54
59
  const emit = defineEmits(['change', 'update:value', 'update:labels']);
55
60
  inputFactory.inputEmit = emit;
56
61
 
62
+ // 监听 optionCtrl.options 的变化,确保 radioOptions 能响应式更新
63
+ if (optionCtrl) {
64
+ watch(
65
+ () => optionCtrl.options.value,
66
+ (newOptions) => {
67
+ radioOptions.value = newOptions || [];
68
+ },
69
+ { immediate: true, deep: true }
70
+ );
71
+ }
72
+
57
73
  watch(
58
74
  () => innerValue.value,
59
75
  (val) => {
@@ -73,7 +89,7 @@ const isValueEqual = (val1: any, val2: any) => {
73
89
 
74
90
  const onChanged = (e: RadioChangeEvent) => {
75
91
  const checkedValue = e.target.value;
76
- const selectedOptions = onOptionChanged(props, checkedValue as SelectValue, radioOptions, inputFactory);
92
+ const selectedOptions = onOptionChanged(optionCtrl, props, checkedValue as SelectValue);
77
93
  const labels: string[] = getSelectedLabels(selectedOptions);
78
94
  emit('update:labels', labels);
79
95
  };
@@ -86,10 +102,10 @@ onMounted(() => {
86
102
  key: 'Id',
87
103
  };
88
104
  }
89
- loadOption(props.autoload, props, radioOptions, inputFactory, url.value, url.value?.params);
105
+ if (optionCtrl) loadOption(optionCtrl, props);
90
106
  });
91
107
  onUnmounted(() => {
92
- unloadOption(props, inputFactory);
108
+ if (optionCtrl) unloadOption(optionCtrl, props);
93
109
  });
94
110
  </script>
95
111
  <template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted, watch, PropType, useAttrs } from 'vue';
2
+ import { ref, onMounted, onUnmounted, watch, PropType, useAttrs, shallowRef } from 'vue';
3
3
  import { Select, SelectOption } from 'ant-design-vue';
4
4
  import {
5
5
  circleLoading,
@@ -16,6 +16,7 @@ import {
16
16
  isEmpty,
17
17
  } from '@/index';
18
18
  import { IUrlInfo } from '@skyfox2000/fapi';
19
+ import { useOptionFactory } from '@/utils/page';
19
20
 
20
21
  type SelectValueType = string | number | string[] | number[] | null;
21
22
  const props = defineProps({
@@ -38,24 +39,15 @@ const props = defineProps({
38
39
  type: String as PropType<string>,
39
40
  required: false,
40
41
  },
41
- /**
42
- * 是否显示全部选项
43
- */
44
- all: {
45
- type: Boolean as PropType<boolean>,
46
- default: false,
47
- },
48
- /**
49
- * 自定义全部选项的值
50
- * 如果all为true,则显示全部选项
51
- * 未设置allValue,则默认[0, 1]
52
- */
53
- allValue: {
54
- type: [String, Number, Array] as PropType<string | number | string[] | number[]>,
55
- required: false,
56
- },
57
42
  });
58
43
 
44
+ const inputFactory = useInputFactory();
45
+ const { editorCtrl, errInfo, labelText } = inputFactory;
46
+
47
+ const defaultCtrl = useOptionFactory(props.url, props);
48
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
49
+ optionCtrl.inputFactory = shallowRef(inputFactory);
50
+
59
51
  // 关闭自动继承属性到根元素
60
52
  defineOptions({
61
53
  inheritAttrs: false,
@@ -63,30 +55,39 @@ defineOptions({
63
55
  const attrs = useAttrs(); // 手动获取 $attrs
64
56
 
65
57
  const url = ref<IUrlInfo>({
66
- ...props.url,
67
- url: props.url?.url || '',
68
- fieldMap: props.fieldMap || props.url?.fieldMap,
69
- params: props.params || props.url?.params,
58
+ ...optionCtrl?.url,
59
+ url: optionCtrl?.url?.url || '',
60
+ fieldMap: optionCtrl?.fieldMap || optionCtrl?.url?.fieldMap,
61
+ params: optionCtrl?.params || optionCtrl?.url?.params,
70
62
  loadingText: false,
71
63
  });
72
64
 
73
- const inputFactory = useInputFactory();
74
- const { editorCtrl, errInfo, labelText } = inputFactory;
75
-
76
65
  const defaultVal = ref(props.value);
77
66
  const placeholder = ref(attrs.placeholder);
78
67
 
79
68
  /// 避免类型错误
80
- const innerValue = ref<string | number | string[] | number[] | undefined>(undefined);
69
+ const innerValue = ref<string | number | string[] | number[] | undefined>(optionCtrl?.selected.value || undefined);
81
70
  const emit = defineEmits(['change', 'update:value', 'update:labels']);
82
71
  inputFactory.inputEmit = emit;
83
72
 
84
73
  /**
85
74
  * 实际的选择项
86
75
  */
87
- const selectOptions = ref<OptionItemProps[]>([]);
76
+ const selectOptions = ref<OptionItemProps[]>(optionCtrl?.options.value || []);
77
+
78
+ // 监听 optionCtrl.options 的变化,确保 selectOptions 能响应式更新
79
+ if (optionCtrl) {
80
+ watch(
81
+ () => optionCtrl.options.value,
82
+ (newOptions) => {
83
+ selectOptions.value = newOptions || [];
84
+ },
85
+ { immediate: true, deep: true },
86
+ );
87
+ }
88
+
88
89
  const onChanged = (value: any) => {
89
- const selectedOptions = onOptionChanged(props, value as SelectValue, selectOptions, inputFactory);
90
+ const selectedOptions = onOptionChanged(optionCtrl, props, value as SelectValue);
90
91
  const labels: string[] = getSelectedLabels(selectedOptions);
91
92
 
92
93
  innerValue.value = value;
@@ -134,13 +135,13 @@ watch(
134
135
  },
135
136
  );
136
137
 
137
- watch(
138
- () => props.params,
139
- (newVal) => {
140
- loadOption(true, props, selectOptions, inputFactory, url.value, newVal);
141
- },
142
- { deep: true },
143
- );
138
+ // watch(
139
+ // () => props.params,
140
+ // (newVal) => {
141
+ // loadOption(true, props, selectOptions, inputFactory, url.value, newVal);
142
+ // },
143
+ // { deep: true },
144
+ // );
144
145
 
145
146
  onMounted(() => {
146
147
  if (url.value && !url.value.fieldMap) {
@@ -153,20 +154,17 @@ onMounted(() => {
153
154
  if (props.dataKey) {
154
155
  const options = JSON.parse(JSON.stringify(OPTIONS.getOptions(props.dataKey)));
155
156
  selectOptions.value = options;
156
- } else loadOption(props.autoload, props, selectOptions, inputFactory, url.value, url.value?.params);
157
+ } else if (optionCtrl) loadOption(optionCtrl, props);
157
158
  });
158
159
 
159
160
  onUnmounted(() => {
160
- unloadOption(props, inputFactory);
161
+ if (optionCtrl) unloadOption(optionCtrl, props);
161
162
  });
162
163
  </script>
163
164
 
164
165
  <template>
165
166
  <div>
166
- <div
167
- v-if="props.url && props.url.loading === true"
168
- class="absolute z-10 mt-[5px] mr-[10px] text-[#999] flex items-center"
169
- >
167
+ <div v-if="optionCtrl?.url?.loading" class="absolute z-10 mt-[5px] mr-[10px] text-[#999] flex items-center">
170
168
  <circleLoading class="text-[#555] mx-[5px] !ml-[10px] !w-4 !h-4" />
171
169
  <span>数据加载中...</span>
172
170
  </div>
@@ -1,24 +1,42 @@
1
1
  <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted } from 'vue';
3
- import { formValidate, useInputFactory, OptionItemProps, loadOption, unloadOption } from '@/index';
2
+ import { ref, onMounted, onUnmounted, PropType, watch, shallowRef } from 'vue';
3
+ import { formValidate, useInputFactory, OptionItemProps, loadOption, unloadOption, OptionCommProps } from '@/index';
4
4
  import { Switch } from 'ant-design-vue';
5
5
  import message from 'vue-m-message';
6
+ import { useOptionFactory } from '@/utils/page';
6
7
 
7
8
  const props = defineProps({
9
+ ...OptionCommProps,
8
10
  /**
9
11
  * 选择项数据
10
12
  */
11
13
  data: {
12
- type: Array<Record<string, any>>,
14
+ type: Array as PropType<OptionItemProps[]>,
13
15
  required: true,
14
16
  },
15
17
  });
16
18
 
19
+ const inputFactory = useInputFactory();
20
+ const defaultCtrl = useOptionFactory(props.url, props);
21
+ const optionCtrl = props.optionCtrl ?? defaultCtrl.optionCtrl;
22
+ optionCtrl.inputFactory = shallowRef(inputFactory);
23
+
17
24
  /**
18
25
  * 实际的选择项
19
26
  */
20
27
  const switchOptions = ref<OptionItemProps[]>([]);
21
28
 
29
+ // 监听 optionCtrl.options 的变化,确保 switchOptions 能响应式更新
30
+ if (optionCtrl) {
31
+ watch(
32
+ () => optionCtrl.options.value,
33
+ (newOptions) => {
34
+ switchOptions.value = newOptions || [];
35
+ },
36
+ { immediate: true, deep: true }
37
+ );
38
+ }
39
+
22
40
  const emit = defineEmits<{
23
41
  (e: 'change', checked: boolean | string | number): void;
24
42
  }>();
@@ -37,11 +55,11 @@ onMounted(() => {
37
55
  message.error('Switch组件必须有且只有两个选项');
38
56
  return;
39
57
  }
40
- loadOption(false, props, switchOptions);
58
+ if (optionCtrl) loadOption(optionCtrl, props);
41
59
  });
42
60
 
43
61
  onUnmounted(() => {
44
- unloadOption(props);
62
+ if (optionCtrl) unloadOption(optionCtrl, props);
45
63
  });
46
64
  </script>
47
65
  <template>