121 lines
3.8 KiB
Vue
121 lines
3.8 KiB
Vue
<!-- 组件使用文档: https://gitee.com/zuohuaijun/Admin.NET/pulls/1559 -->
|
||
<script setup lang="ts">
|
||
import { reactive, watch, PropType } from 'vue';
|
||
import { useUserInfo } from '/@/stores/userInfo';
|
||
|
||
const emit = defineEmits(['update:modelValue']);
|
||
const dictList = useUserInfo().dictList;
|
||
const props = defineProps({
|
||
modelValue: {
|
||
type: [String, Number, Boolean, Array, null],
|
||
default: null,
|
||
required: true,
|
||
},
|
||
code: {
|
||
type: String,
|
||
required: true,
|
||
},
|
||
propLabel: {
|
||
type: String,
|
||
default: 'label',
|
||
},
|
||
propValue: {
|
||
type: String,
|
||
default: 'value',
|
||
},
|
||
onItemFilter: {
|
||
type: Function,
|
||
default: (dict: any): boolean => dict,
|
||
},
|
||
onItemFormatter: {
|
||
type: Function as PropType<(dict: any) => string | undefined | null>,
|
||
default: () => undefined,
|
||
},
|
||
renderAs: {
|
||
type: String,
|
||
default: 'tag',
|
||
validator(value: string) {
|
||
return ['tag', 'select', 'radio', 'checkbox'].includes(value);
|
||
},
|
||
},
|
||
multiple: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
});
|
||
|
||
const state = reactive({
|
||
dict: {} as any | any[] | undefined,
|
||
dictData: [] as any[],
|
||
value: null as any,
|
||
});
|
||
|
||
const setDictValue = (value: any) => {
|
||
state.value = value;
|
||
state.dictData = dictList[props.code]?.filter(props.onItemFilter) ?? [];
|
||
|
||
if (Array.isArray(value)) {
|
||
state.dict = state.dictData.filter((x: any) => value.includes(x[props.propValue]));
|
||
if (state.dict) {
|
||
state.dict.forEach((item: any) => {
|
||
if (!['success', 'warning', 'info', 'primary', 'danger'].includes(item.tagType ?? '')) {
|
||
item.tagType = 'primary';
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
state.dict = state.dictData.find((x: any) => x[props.propValue] == state.value);
|
||
if (state.dict && !['success', 'warning', 'info', 'primary', 'danger'].includes(state.dict.tagType ?? '')) {
|
||
state.dict.tagType = 'primary';
|
||
}
|
||
}
|
||
};
|
||
|
||
watch(
|
||
() => props.modelValue,
|
||
(newValue) => setDictValue(newValue),
|
||
{ immediate: true }
|
||
);
|
||
</script>
|
||
|
||
<template>
|
||
<!-- 渲染标签 -->
|
||
<template v-if="props.renderAs === 'tag'">
|
||
<template v-if="Array.isArray(state.dict)">
|
||
<el-tag v-for="(item, index) in state.dict" :key="index" v-bind="$attrs" :type="item.tagType" :style="item.styleSetting" :class="item.classSetting" class="mr-1">
|
||
{{ onItemFormatter(item) ?? item[props.propLabel] }}
|
||
</el-tag>
|
||
</template>
|
||
<template v-else>
|
||
<el-tag v-if="state.dict" v-bind="$attrs" :type="state.dict.tagType" :style="state.dict.styleSetting" :class="state.dict.classSetting">
|
||
{{ onItemFormatter(state.dict) ?? state.dict[props.propLabel] }}
|
||
</el-tag>
|
||
<span v-else>{{ state.value }}</span>
|
||
</template>
|
||
</template>
|
||
<!-- 渲染选择器 -->
|
||
<template v-if="props.renderAs === 'select'">
|
||
<el-select v-model="state.value" v-bind="$attrs" :multiple="props.multiple" @change="(newValue: any) => emit('update:modelValue', newValue)">
|
||
<el-option v-for="(item, index) in state.dictData" :key="index" :label="onItemFormatter(item) ?? item[props.propLabel]" :value="item[props.propValue]" />
|
||
</el-select>
|
||
</template>
|
||
<!-- 渲染复选框(多选) -->
|
||
<template v-if="props.renderAs === 'checkbox'">
|
||
<el-checkbox-group v-model="state.value" v-bind="$attrs" @change="(newValue: any) => emit('update:modelValue', newValue)">
|
||
<el-checkbox v-for="(item, index) in state.dictData" :key="index" :label="item[props.propValue]">
|
||
{{ onItemFormatter(item) ?? item[props.propLabel] }}
|
||
</el-checkbox>
|
||
</el-checkbox-group>
|
||
</template>
|
||
<!-- 渲染单选框 -->
|
||
<template v-if="props.renderAs === 'radio'">
|
||
<el-radio-group v-model="state.value" v-bind="$attrs" @change="(newValue: any) => emit('update:modelValue', newValue)">
|
||
<el-radio v-for="(item, index) in state.dictData" :key="index" :value="item[props.propValue]">
|
||
{{ onItemFormatter(item) ?? item[props.propLabel] }}
|
||
</el-radio>
|
||
</el-radio-group>
|
||
</template>
|
||
</template>
|
||
|
||
<style scoped lang="scss"></style>
|