You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
5.8 KiB
206 lines
5.8 KiB
7 months ago
|
<!-- @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>
|