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