@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.
- package/.vscode/settings.json +1 -1
- package/lib/assets/modules/{file-upload-CGyzCx7I.js → file-upload-C4GVmWjB.js} +1 -1
- package/lib/assets/modules/{form-excel-DWirWVPA.js → form-excel-Cr2hcL1s.js} +3 -3
- package/lib/assets/modules/{index-Czk7DDWM.js → index-D5onbqkl.js} +2 -2
- package/lib/assets/modules/{index-C1zkNPmi.js → index-DjBruVH-.js} +1 -1
- package/lib/assets/modules/{menuTabs-BOax-dro.js → menuTabs-B9fCWfN1.js} +36 -36
- package/lib/assets/modules/{toolIcon-vJF7OgP6.js → toolIcon-DKTf30Tq.js} +1 -1
- package/lib/assets/modules/{uploadList-DaUjVXLU.js → uploadList-CY57np42.js} +980 -923
- package/lib/assets/modules/uploadList-D2lisNHt.js +327 -0
- package/lib/components/form/autoComplete/index.vue.d.ts +15 -52
- package/lib/components/form/cascader/index.vue.d.ts +16 -56
- package/lib/components/form/checkbox/index.vue.d.ts +15 -54
- package/lib/components/form/index.d.ts +1 -1
- package/lib/components/form/propEditor/index.vue.d.ts +1 -7
- package/lib/components/form/radio/index.vue.d.ts +15 -54
- package/lib/components/form/select/index.vue.d.ts +15 -60
- package/lib/components/form/switch/index.vue.d.ts +62 -29
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +6 -6
- package/lib/es/Error403/index.js +1 -1
- package/lib/es/Error404/index.js +1 -1
- package/lib/es/ExcelForm/index.js +37 -37
- package/lib/es/UploadForm/index.js +4 -4
- package/lib/index.d.ts +1 -1
- package/lib/typings/form.d.ts +19 -0
- package/lib/typings/option.d.ts +93 -74
- package/lib/utils/options.d.ts +4 -7
- package/lib/utils/page.d.ts +5 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +861 -851
- package/package.json +17 -17
- package/src/components/content/form/formItem.vue +2 -2
- package/src/components/form/autoComplete/index.vue +29 -16
- package/src/components/form/cascader/index.vue +25 -9
- package/src/components/form/checkbox/index.vue +26 -10
- package/src/components/form/index.ts +1 -1
- package/src/components/form/propEditor/index.vue +6 -21
- package/src/components/form/radio/index.vue +26 -10
- package/src/components/form/select/index.vue +38 -40
- package/src/components/form/switch/index.vue +23 -5
- package/src/index.ts +8 -1
- package/src/typings/form.d.ts +19 -0
- package/src/typings/option.d.ts +93 -73
- package/src/utils/form-excel.ts +2 -2
- package/src/utils/options.ts +58 -62
- package/src/utils/page.ts +41 -0
- 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.
|
|
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.
|
|
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.
|
|
53
|
-
"@vitejs/plugin-vue": "^5.2.
|
|
54
|
-
"autoprefixer": "^10.4.
|
|
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.
|
|
56
|
+
"eslint": "^9.17.0",
|
|
57
57
|
"eslint-config-prettier": "^9.1.0",
|
|
58
|
-
"eslint-plugin-prettier": "^5.
|
|
59
|
-
"eslint-plugin-vue": "^9.
|
|
60
|
-
"postcss": "^8.
|
|
61
|
-
"prettier": "^3.
|
|
62
|
-
"rollup": "^4.
|
|
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.
|
|
65
|
-
"vite": "^6.3
|
|
64
|
+
"typescript": "^5.7.2",
|
|
65
|
+
"vite": "^6.2.3",
|
|
66
66
|
"vite-plugin-dts": "^4.5.4",
|
|
67
|
-
"vue-tsc": "^2.2.
|
|
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
|
-
...
|
|
59
|
-
url:
|
|
60
|
-
fieldMap:
|
|
61
|
-
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(
|
|
137
|
+
if (optionCtrl) loadOption(optionCtrl, props);
|
|
125
138
|
};
|
|
126
139
|
|
|
127
140
|
const onSelected = (value: any) => {
|
|
128
|
-
const selectedOptions = onOptionChanged(props, value as SelectValue
|
|
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(
|
|
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="
|
|
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
|
-
...
|
|
26
|
-
url:
|
|
27
|
-
fieldMap:
|
|
28
|
-
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(
|
|
96
|
+
if (optionCtrl) loadOption(optionCtrl, props);
|
|
81
97
|
});
|
|
82
98
|
|
|
83
99
|
onUnmounted(() => {
|
|
84
|
-
unloadOption(
|
|
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
|
-
...
|
|
42
|
-
url:
|
|
43
|
-
fieldMap:
|
|
44
|
-
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
|
|
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(
|
|
87
|
+
if (optionCtrl) loadOption(optionCtrl, props);
|
|
72
88
|
});
|
|
73
89
|
onUnmounted(() => {
|
|
74
|
-
unloadOption(
|
|
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 :
|
|
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
|
-
...
|
|
42
|
-
url:
|
|
43
|
-
fieldMap:
|
|
44
|
-
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
|
|
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(
|
|
105
|
+
if (optionCtrl) loadOption(optionCtrl, props);
|
|
90
106
|
});
|
|
91
107
|
onUnmounted(() => {
|
|
92
|
-
unloadOption(
|
|
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
|
-
...
|
|
67
|
-
url:
|
|
68
|
-
fieldMap:
|
|
69
|
-
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
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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(
|
|
157
|
+
} else if (optionCtrl) loadOption(optionCtrl, props);
|
|
157
158
|
});
|
|
158
159
|
|
|
159
160
|
onUnmounted(() => {
|
|
160
|
-
unloadOption(
|
|
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<
|
|
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(
|
|
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>
|