<template> <div class="dict-selector"> <el-select v-if="formType == 'select'" v-model="valueSync" :placeholder="placeholder || $t('请选择')" :clearable="clearable" :multiple="multiple" :disabled="disabled" @change="(val) => $emit('change', val)" > <el-option v-for="dict in formattedList" :key="dict.value" :label="$l(dict, 'label')" :value="dict.value" /> </el-select> <el-radio-group v-if="formType == 'radio'" v-model="valueSync" :disabled="disabled" > <el-radio v-for="dict in formattedList" :label="dict.value" :checked="valueSync === dict.value" :key="dict.value" >{{ $l(dict, "label") }}</el-radio > </el-radio-group> <el-checkbox-group v-if="formType == 'checkbox'" v-model="valueSync" :disabled="disabled" > <el-checkbox v-for="dict in formattedList" :label="dict.value" :key="dict.value" >{{ $l(dict, "label") }}</el-checkbox > </el-checkbox-group> </div> </template> <script> const FORMATTERS = { string: String, bool: function (val) { return [false, "false", 0, "0"].indexOf(val) < 0; }, number: Number, array: function (val) { return typeof val == "string" ? val.split(",").filter((item) => item && item !== "") : val; }, }; export default { props: { placeholder: { type: String, default: null, }, type: String, value: [String, Number, Array, Boolean], multiple: Boolean, formType: { type: String, default: "select", }, formatter: { type: [Function, String], default: String, }, defaultable: Boolean, // 是否默认选择第一个 disabled: Boolean, /** * 过滤字典项,用于只使用部分字典项的场景 */ filter: { type: Function, default: () => true, }, clearable: Boolean, }, data() { return { valueSync: this.multiple ? [] : null, }; }, computed: { dicts() { return this.getList(this.type); }, dictList() { return this.dicts.filter(this.filter); }, formattedList() { let arr = []; this.dictList.forEach((item) => { arr.push({ label: item.label, labelEn: item.labelEn, value: this.format(item.value), cssClass: item.cssClass, colorType: item.colorType, }); }); return arr; }, }, watch: { valueSync(val) { this.$emit("input", val); }, value(val) { if (val != this.valueSync) this.setValueSync(); }, dictList() { this.setDefault(); }, }, created() { this.setValueSync(); this.setDefault(); }, methods: { format(val) { if (val === null || val == undefined || val == "") return val; let formatter = typeof this.formatter == "function" ? this.formatter : FORMATTERS[this.formatter]; if (!formatter) { console.warn("格式器无效", this.formatter); return val; } return formatter(val); }, changeValue(val) { this.valueSync = val; }, setValueSync() { if ( this.value === null || this.value === undefined || this.value === "" ) { return (this.valueSync = this.multiple ? [] : this.value); } if (this.multiple) { let value = this.value || []; if (typeof this.value == "string") { value = this.value.split(",").filter((item) => item && item != ""); } this.valueSync = value.map((item) => this.format(item)); } else { this.valueSync = this.format(this.value); } }, getList() { return this.getDictDatas(this.type); }, setDefault() { if (!this.defaultable) return; if ( this.dictList.length && (this.valueSync === null || this.valueSync == undefined || this.valueSync == "") ) { this.valueSync = this.multiple ? [] : this.formattedList[0].value; } }, }, }; </script> <style scoped> .dict-selector { display: inline-block; } </style>