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

4 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>