<!-- @format --> <template> {{resultField}} <a-radio-group v-bind="getBindValue"> <template v-if="radioType === 'radio'"> <a-radio v-for="item in getOptions" :key="item.value" @click="triggerChange(item.value)" :value="item.value" :disabled="item.disabled"> {{ item.label }} </a-radio> </template> <template v-else> <a-radio-button @click="triggerChange(item.value)" v-for="item in getOptions" :key="item.value" :value="item.value" :disabled="item.disabled"> {{ item.label }} </a-radio-button> </template> </a-radio-group> </template> <script lang="ts"> import { computed, PropType, defineComponent,ref,watch,nextTick,unref } from 'vue'; import { PropTypes, tuple } from '/nerv-lib/util/type'; import { cloneDeep, get, isArray, isEqual, isFunction, isString, isUndefined } from 'lodash-es'; import { HttpRequestConfig, useApi } from '/nerv-lib/use/use-api'; export default defineComponent({ name: 'NsRadioApi', props: { api: { type: [String, Object, Function] as PropType<string | Function | HttpRequestConfig>, required: true, }, method:{ type: String, default: 'get', }, //是否选择第一个 autoSelectFirst: { type: Boolean, default: false, }, immediate: { type: Boolean, default: false, }, //接口参数 params: { type: Object, default: () => ({}), }, labelField: { type: [String, Function], default: 'label', }, valueField: { type: String, default: 'value', }, firstOption: { type: Object, }, numberToString: { type: Boolean, default: false, }, //响应返回数据 resultField: { type: String, default: 'data.data', }, //数据筛选函数 filterData: { type: Function, }, radioType: PropTypes.oneOf(tuple('radio', 'radioButton')).def('radioButton'), defaultValue: PropTypes.any, value: PropTypes.any, options: PropTypes.array, buttonStyle: PropTypes.oneOf(tuple('outline', 'solid')).def('solid'), onChange: PropTypes.func, }, emits: ['update:value', 'change'], setup(props, { attrs,emit }) { const getBindValue = computed(() => { return { ...props, ...attrs, options: [], }; }); const option=ref<object[]>([]) const getOptions=computed(()=>{ const { firstOption, labelField, valueField, numberToString, options:initOptions, } = props; let sourceOptions = []; firstOption && sourceOptions.push(firstOption); if(props.autoSelectFirst&&option.value.length){ emit('change',option.value[0].value) } if(initOptions&&initOptions.length){ initOptions.forEach(item=>{ sourceOptions.push(item) }) } return unref(option.value).reduce((acc, next: Recordable) => { if (isString(next)) { //值是字符串类型 const option = { label: next, value: next, }; acc.push(option); return acc; } else { const value = get(next, valueField); const option = { ...next, label: isFunction(labelField) ? labelField(next) : get(next, labelField as string), value: numberToString ? `${value}` : value, }; acc.push(option); return acc; } }, sourceOptions); }) /** * 获取数据 */ const fetch = () => { const { api, method, params: _params, resultField, filterData, } = props; const requestConfig: HttpRequestConfig = { method: method }; const params: Recordable = cloneDeep(_params); const { httpRequest } = useApi(); httpRequest({ api, params, requestConfig }) .then((res: Recordable) => { emit('validateChange', { help: undefined }); if (resultField) { let data = get(res, resultField) || []; if (isFunction(filterData)) { data = filterData(data) } option.value=data.filter(x=>!x.hidden) } }) .catch((error: any) => { if (error?.response?.status === 403) { emit('validateChange', { help: '暂无权限', validateStatus: 'error' }); } }); }; //处理点击事件 const triggerChange=(value)=> { if (isUndefined(value)) { emit('change', value, undefined); } else if (isArray(value)) { const options: Record<string, any>[] = []; value.forEach((v) => { getOptions.value.forEach((option) => { if (option.value === v) { options.push(option); } }); }); emit('change', value, options); } else { let op = {}; getOptions.value.forEach((option) => { if (option.value === value) { op = option; } }); emit('change', value, op); } } /** ** 联动 immediate 为是否主动获取数据 */ watch( [() => props.params, () => props.api], async () => { await fetch(); }, { deep: true, immediate: props.immediate }, ); return { getBindValue,getOptions,triggerChange }; }, }); </script> <style lang="less" scoped></style>