Commit 0c57c6d7f244b5b4e4ee8fef3aad9a7fa327fb0f
1 parent
2161ab68
feat:新增Form 里的远程下拉radio,精简版没有,完整版有
Showing
4 changed files
with
135 additions
and
0 deletions
... | ... | @@ -9,5 +9,7 @@ export { useForm } from './src/hooks/useForm'; |
9 | 9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; |
10 | 10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; |
11 | 11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; |
12 | +export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; | |
13 | + | |
12 | 14 | |
13 | 15 | export { BasicForm }; | ... | ... |
... | ... | @@ -27,6 +27,7 @@ import { BasicUpload } from '/@/components/Upload'; |
27 | 27 | import { StrengthMeter } from '/@/components/StrengthMeter'; |
28 | 28 | import { IconPicker } from '/@/components/Icon'; |
29 | 29 | import { CountdownInput } from '/@/components/CountDown'; |
30 | +import ApiRadioGroup from './components/ApiRadioGroup.vue'; | |
30 | 31 | //自定义组件 |
31 | 32 | import JAddInput from './jeecg/components/JAddInput.vue'; |
32 | 33 | |
... | ... | @@ -39,6 +40,7 @@ componentMap.set('InputSearch', Input.Search); |
39 | 40 | componentMap.set('InputTextArea', Input.TextArea); |
40 | 41 | componentMap.set('InputNumber', InputNumber); |
41 | 42 | componentMap.set('AutoComplete', AutoComplete); |
43 | +componentMap.set('ApiRadioGroup', ApiRadioGroup); | |
42 | 44 | |
43 | 45 | componentMap.set('Select', Select); |
44 | 46 | componentMap.set('ApiSelect', ApiSelect); | ... | ... |
1 | +<!-- | |
2 | + * @Description:It is troublesome to implement radio button group in the form. So it is extracted independently as a separate component | |
3 | +--> | |
4 | +<template> | |
5 | + <RadioGroup v-bind="attrs" v-model:value="state" button-style="solid" @change="handleChange"> | |
6 | + <template v-for="item in getOptions" :key="`${item.value}`"> | |
7 | + <RadioButton v-if="props.isBtn" :value="item.value" :disabled="item.disabled"> | |
8 | + {{ item.label }} | |
9 | + </RadioButton> | |
10 | + <Radio v-else :value="item.value" :disabled="item.disabled"> | |
11 | + {{ item.label }} | |
12 | + </Radio> | |
13 | + </template> | |
14 | + </RadioGroup> | |
15 | +</template> | |
16 | +<script lang="ts"> | |
17 | + import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue'; | |
18 | + import { Radio } from 'ant-design-vue'; | |
19 | + import { isFunction } from '/@/utils/is'; | |
20 | + import { useRuleFormItem } from '/@/hooks/component/useFormItem'; | |
21 | + import { useAttrs } from '/@/hooks/core/useAttrs'; | |
22 | + import { propTypes } from '/@/utils/propTypes'; | |
23 | + import { get, omit } from 'lodash-es'; | |
24 | + import { useI18n } from '/@/hooks/web/useI18n'; | |
25 | + type OptionsItem = { label: string; value: string | number | boolean; disabled?: boolean }; | |
26 | + | |
27 | + export default defineComponent({ | |
28 | + name: 'ApiRadioGroup', | |
29 | + components: { | |
30 | + RadioGroup: Radio.Group, | |
31 | + RadioButton: Radio.Button, | |
32 | + Radio, | |
33 | + }, | |
34 | + props: { | |
35 | + api: { | |
36 | + type: Function as PropType<(arg?: Recordable | string) => Promise<OptionsItem[]>>, | |
37 | + default: null, | |
38 | + }, | |
39 | + params: { | |
40 | + type: [Object, String] as PropType<Recordable | string>, | |
41 | + default: () => ({}), | |
42 | + }, | |
43 | + value: { | |
44 | + type: [String, Number, Boolean] as PropType<string | number | boolean>, | |
45 | + }, | |
46 | + isBtn: { | |
47 | + type: [Boolean] as PropType<boolean>, | |
48 | + default: false, | |
49 | + }, | |
50 | + numberToString: propTypes.bool, | |
51 | + resultField: propTypes.string.def(''), | |
52 | + labelField: propTypes.string.def('label'), | |
53 | + valueField: propTypes.string.def('value'), | |
54 | + immediate: propTypes.bool.def(true), | |
55 | + }, | |
56 | + emits: ['options-change', 'change'], | |
57 | + setup(props, { emit }) { | |
58 | + const options = ref<OptionsItem[]>([]); | |
59 | + const loading = ref(false); | |
60 | + const isFirstLoad = ref(true); | |
61 | + const emitData = ref<any[]>([]); | |
62 | + const attrs = useAttrs(); | |
63 | + const { t } = useI18n(); | |
64 | + // Embedded in the form, just use the hook binding to perform form verification | |
65 | + const [state] = useRuleFormItem(props); | |
66 | + | |
67 | + // Processing options value | |
68 | + const getOptions = computed(() => { | |
69 | + const { labelField, valueField, numberToString } = props; | |
70 | + | |
71 | + return unref(options).reduce((prev, next: Recordable) => { | |
72 | + if (next) { | |
73 | + const value = next[valueField]; | |
74 | + prev.push({ | |
75 | + label: next[labelField], | |
76 | + value: numberToString ? `${value}` : value, | |
77 | + ...omit(next, [labelField, valueField]), | |
78 | + }); | |
79 | + } | |
80 | + return prev; | |
81 | + }, [] as OptionsItem[]); | |
82 | + }); | |
83 | + | |
84 | + watchEffect(() => { | |
85 | + props.immediate && fetch(); | |
86 | + }); | |
87 | + | |
88 | + watch( | |
89 | + () => props.params, | |
90 | + () => { | |
91 | + !unref(isFirstLoad) && fetch(); | |
92 | + }, | |
93 | + { deep: true }, | |
94 | + ); | |
95 | + | |
96 | + async function fetch() { | |
97 | + const api = props.api; | |
98 | + if (!api || !isFunction(api)) return; | |
99 | + options.value = []; | |
100 | + try { | |
101 | + loading.value = true; | |
102 | + const res = await api(props.params); | |
103 | + if (Array.isArray(res)) { | |
104 | + options.value = res; | |
105 | + emitChange(); | |
106 | + return; | |
107 | + } | |
108 | + if (props.resultField) { | |
109 | + options.value = get(res, props.resultField) || []; | |
110 | + } | |
111 | + emitChange(); | |
112 | + } catch (error) { | |
113 | + console.warn(error); | |
114 | + } finally { | |
115 | + loading.value = false; | |
116 | + } | |
117 | + } | |
118 | + | |
119 | + function emitChange() { | |
120 | + emit('options-change', unref(getOptions)); | |
121 | + } | |
122 | + | |
123 | + function handleChange(_, ...args) { | |
124 | + emitData.value = args; | |
125 | + } | |
126 | + | |
127 | + return { state, getOptions, attrs, loading, t, handleChange, props }; | |
128 | + }, | |
129 | + }); | |
130 | +</script> | ... | ... |