<template>
  <el-row
    class="custom-form-item"
    :ref="item.prop"
    :style="item.styles"
    :class="{ isDefects: defectsSet.includes(item.prop) }"
  >
    <el-col :lg="item.width">
      <el-form-item
        :label="
          !hiddenLabel && item.label
            ? `${item.label}${item.labelSuffix || '：'}`
            : ''
        "
        :label-width="item.labelWidth ? `${item.labelWidth}px` : ''"
        :prop="item.prop"
        :rules="item.rules"
        :class="isEmpty"
      >
        <div class="flex">
          <div>
            <!-- 表单改文本 -->
            <template v-if="vwForm.detail">
              <form-item-text :item="item" :form="form"></form-item-text>
            </template>
            <template v-else>
              <!-- 输入框 -->
              <el-input
                :class="item.toothBit ? 'toothBit' : ''"
                v-if="item.type === 'input'"
                v-model="form[item.prop]"
                :readonly="item.readonly"
                :disabled="item.disabled"
                :placeholder="
                  item.placeholder ||
                  ` ${item.label ? '请输入' + item.label : ''}`
                "
                @blur="handleBlur"
                :clearable="item.notClearable ? false : true"
                :maxlength="
                  item.maxlength
                    ? item.maxlength
                    : item.fieldType === 'text'
                    ? ''
                    : item.fieldLength
                "
              >
                <!-- 牙位按钮 -->
                <el-button
                  slot="append"
                  v-if="item.toothBit"
                  @click="openToothBit"
                  class="toothBit"
                  >{{ item.append || "牙位" }}</el-button
                >
                <template slot="append" v-else-if="item.append">{{
                  item.append
                }}</template>
                <template slot="prepend" v-if="item.prepend">{{
                  item.prepend
                }}</template>
              </el-input>

              <!-- 密码框 -->

              <el-input
                v-if="item.type === 'password'"
                v-model="form[item.prop]"
                type="password"
                :placeholder="item.placeholder || `请输入 ${item.label || ''}`"
                :readonly="item.readonly"
                :disabled="item.disabled"
                @blur="handleBlur"
                :show-password="item.showPassword"
                clearable
                :maxlength="
                  item.maxlength
                    ? item.maxlength
                    : item.fieldType === 'text'
                    ? ''
                    : item.fieldLength
                "
              >
                <template slot="append" v-if="item.append">{{
                  item.append
                }}</template>
                <template slot="prepend" v-if="item.prepend">{{
                  item.prepend
                }}</template>
              </el-input>

              <!-- 文本域 -->
              <template v-if="item.type === 'textarea'">
                <el-input
                  type="textarea"
                  :placeholder="
                    item.placeholder || `请输入 ${item.label || ''}`
                  "
                  @blur="handleBlur"
                  :autosize="{ minRows: item.minRows, maxRows: item.maxRows }"
                  v-model="form[item.prop]"
                  :minlength="item.minlength"
                  :disabled="item.disabled"
                  :maxlength="
                    item.maxlength
                      ? item.maxlength
                      : item.fieldType === 'text'
                      ? ''
                      : item.fieldLength
                  "
                  :show-word-limit="item.showWordLimit"
                ></el-input>
              </template>

              <!-- 计数器 -->
              <div v-if="item.type === 'number'" style="display: inline-table">
                <el-input-number
                  v-model="form[item.prop]"
                  :readonly="item.readonly"
                  :disabled="item.disabled"
                  :controls="item.controls ? true : false"
                  :controls-position="item.controlsPosition"
                  :placeholder="item.placeholder"
                  :step="item.step"
                  :precision="item.precision"
                  :min="item.minRows"
                  :max="item.maxRows"
                  @blur="handleBlur"
                  style="display: table-cell"
                >
                </el-input-number>
                <span
                  v-if="item.append"
                  class="el-input-group__append"
                  style="line-height: 28px"
                  >{{ item.append }}</span
                >
              </div>

              <!-- 单选框 -->
              <el-radio-group
                v-if="item.type === 'radio'"
                @change="handleChange"
                v-model="form[item.prop]"
                :disabled="item.disabled"
              >
                <el-radio
                  v-for="(opt, optIndex) in item.dicData"
                  :key="optIndex"
                  :label="opt.value"
                  >{{ opt.label }}
                </el-radio>
              </el-radio-group>

              <!-- 多选框 -->
              <template v-if="item.type === 'checkbox'">
                <el-checkbox-group
                  v-model="form[item.prop]"
                  :disabled="item.disabled"
                  @change="handleChange"
                >
                  <el-checkbox
                    v-for="(opt, optIndex) in item.dicData"
                    :key="optIndex"
                    :label="opt.value"
                    >{{ opt.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </template>

              <!-- 下拉框 -->
              <template v-if="item.type === 'select'">
                <el-select
                  :clearable="item.clearable"
                  :filterable="item.filterable"
                  :disabled="item.disabled"
                  v-model="form[item.prop]"
                  :placeholder="
                    item.placeholder
                      ? item.placeholder
                      : `请选择 ${item.label || ''}`
                  "
                  default-first-option
                  :multiple="item.multiple"
                  :multiple-limit="item.limit"
                  @change="handleChange"
                >
                  <el-option
                    v-for="(opt, optIndex) in item.dicData"
                    :key="optIndex"
                    :label="opt.label"
                    :value="opt.value"
                  >
                  </el-option>
                </el-select>
              </template>
              <!-- 级联 -->
              <el-cascader
                v-else-if="item.type === 'cascader'"
                v-model="form[item.prop]"
                :disabled="item.disabled"
                clearable
                :filterable="item.filterable"
                :props="{ multiple: item.multiple }"
                :options="item.dicData"
                :show-all-levels="item.showAllLevels"
                :separator="item.separator"
                @change="handleChange"
                style="width: 100%"
              ></el-cascader>

              <!-- 时间 -->
              <el-time-picker
                v-else-if="item.type === 'time'"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                style="width: 100%"
                @change="handleChange"
                clearable
              >
              </el-time-picker>
              <!-- 时间范围 -->
              <el-time-picker
                v-else-if="item.type === 'timerange'"
                is-range
                v-model="form[item.prop]"
                range-separator="至"
                :start-placeholder="item.startPlaceholder"
                :end-placeholder="item.endPlaceholder"
                :unlink-panels="item.unlinkPanels"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-time-picker>
              <!-- 日期 -->
              <el-date-picker
                v-else-if="item.type === 'date'"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-date-picker>
              <!-- 年 -->
              <el-date-picker
                v-else-if="item.type === 'year'"
                type="year"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-date-picker>
              <!-- 月 -->

              <el-date-picker
                type="month"
                v-else-if="item.type === 'month'"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-date-picker>
              <!-- 周 -->

              <el-date-picker
                type="week"
                v-else-if="item.type === 'week'"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :value-format="item.valueFormat || 'yyyy-ww'"
                :format="item.format || 'yyyy 第 WW 周'"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-date-picker>
              <!-- 日期范围 -->

              <el-date-picker
                v-else-if="item.type === 'daterange'"
                type="daterange"
                range-separator="至"
                :start-placeholder="item.startPlaceholder"
                :end-placeholder="item.endPlaceholder"
                :unlink-panels="item.unlinkPanels"
                v-model="form[item.prop]"
                :value-format="item.valueFormat"
                :format="item.format"
                :disabled="item.disabled"
                @change="handleChange"
                clearable
              >
              </el-date-picker>

              <!-- 日期时间 -->
              <el-date-picker
                v-model="form[item.prop]"
                v-else-if="item.type === 'datetime'"
                type="datetime"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                clearable
                :disabled="item.disabled"
                :picker-options="pickerOptions"
                :value-format="item.valueFormat"
                :format="item.format"
                @change="handleChange"
              >
              </el-date-picker>

              <!-- 日期时间范围 -->
              <el-date-picker
                v-else-if="item.type === 'datetimerange'"
                v-model="form[item.prop]"
                type="datetimerange"
                :picker-options="rangeOptions"
                range-separator="至"
                clearable
                :disabled="item.disabled"
                :start-placeholder="item.startPlaceholder"
                :end-placeholder="item.endPlaceholder"
                :value-format="item.valueFormat"
                :format="item.format"
                align="right"
                @change="handleChange"
              >
              </el-date-picker>
            </template>
            <el-upload-self
              v-if="item.type === 'upload'"
              v-bind="item"
              v-model="form[item.prop]"
              :disabled="item.disabled"
            ></el-upload-self>
          </div>
          <span
            class="important_field"
            v-if="item.importantField && !vwForm.detail"
            >{{ item.importantFieldDesc || "*" }}</span
          >
        </div>
      </el-form-item>
    </el-col>
    <dialog-tooth-bit
      v-if="item.toothBit"
      ref="dialog"
      append-to-body
      title="牙位选择"
      v-model="form[item.prop]"
    ></dialog-tooth-bit>
  </el-row>
</template>

<script>
/**
 * @description 自定义单组件
 */

import ElUploadSelf from "@/components/Upload"
import FormItemText from "./FormItemText"
import DialogToothBit from "./DialogToothBit"
import { getTimePoor, getInfoByIdCard } from "@/utils/index"
import { getChineseHeadLetter } from "@/utils/chinesePingyin.js"
import { pickerOptions, rangeOptions } from "@/data/dateOption"
export default {
  name: "FormItemSelf",
  components: { ElUploadSelf, FormItemText, DialogToothBit },
  inject: {
    vwForm: {
      default: {},
    },
    getDefectsSet: {
      type: Function,
      default: () => {},
    },
  },
  props: {
    item: {
      type: Object,
    },
    form: {
      type: Object | Array,
    },
    hiddenLabel: {
      type: Boolean,
      default: false,
    },
    columns: Array,
    group: Array,
    type: String,
  },
  data() {
    return {
      pickerOptions,
      rangeOptions,
    }
  },
  computed: {
    //重要字段空数据且填写表单时添加重点
    isEmpty() {
      const { importantField, prop } = this.item
      if (!importantField || this.vwForm.detail) return ""

      const value = this.form[prop] // []
      let empty = !value
      if (value === 0) empty = false
      else if (value && typeof value !== "number") {
        empty = !(Object.keys(value) || value).length
      }
      return empty ? "empty-tip" : ""
    },
    defectsSet() {
      return this.getDefectsSet ? this.getDefectsSet() : []
    },
  },
  methods: {
    scrollToView() {
      if (this.$refs["JY_LCYY"]) {
        this.$refs["JY_LCYY"].$el.scrollIntoView({ behavior: "smooth" })
      }
    },
    openToothBit() {
      this.$refs.dialog.open()
    },

    // 处理timerange 重置后不能选择的问题
    timerangeReset() {
      if (this.item.type === "timerange") {
        this.$watch(`form.${this.item.prop}`, (val) => {
          if (val && val.length === 1) {
            this.form[this.item.prop] = null
          }
        })
      }
    },
    // 处理number 默认为0的问题
    numberReset() {
      if (this.item.type === "number") {
        this.$watch(
          `form.${this.item.prop}`,
          (val) => {
            if (!val && val !== 0 && val !== undefined) {
              this.form[this.item.prop] = undefined
            }
          },
          { immediate: true }
        )
      }
    },

    // 处理数组 默认值的问题
    checkboxReset() {
      const { type, multiple, value } = this.item
      if (
        type === "checkbox" ||
        (type === "select" && multiple) ||
        type === "cascader"
      ) {
        if (value && typeof value === "string") {
          this.form[this.item.prop] = value.split(",")
        }
        this.$watch(
          `form.${this.item.prop}`,
          (val) => {
            if (!Array.isArray(val)) {
              this.$set(this.form, this.item.prop, [])
            }
          },
          { immediate: true }
        )
      }
    },

    // 处理复选框排斥
    checkboxRepel(val) {
      const { repelValue, repel } = this.item
      if (repel && repelValue) {
        const len = val.length
        const lastValue = val[len - 1]
        if (!lastValue) return
        if (lastValue === repelValue) {
          this.form[this.item.prop].splice(0, len - 1)
        } else {
          let idx = val.findIndex((_) => _ === repelValue)
          if (idx > -1) {
            this.form[this.item.prop].splice(idx, 1)
          }
        }
      }
    },
    // 处理运算规则
    handleAlgorithm() {
      const { algorithm } = this.item
      if (algorithm) {
        const algorithmArr = algorithm.split(";") //多个规则数组集合
        algorithmArr.forEach((item) => {
          if (item.includes("|")) {
            // 自定义方法规则： type|target|args
            const algorithmValue = item.split("|")
            this.handleSelfProcess(algorithmValue)
          } else {
            // 直接运算 target=process
            let target = this.getProp(algorithm.split("=")[0])
            if (!this.form.hasOwnProperty(target)) return
            let process = this.getProcess(algorithm.split("=")[1])
            if (process.includes("stop")) return
            try {
              this.$set(this.form, target, eval(process))
            } catch {}
          }
        })
      }
    },
    // 自定义方法规则
    handleSelfProcess(algorithmValue) {
      const type = algorithmValue[0]
      const ruleTarget = algorithmValue[1]
      const ruleArgs = algorithmValue[2]
      if (!ruleTarget || !ruleArgs || !this.form.hasOwnProperty(ruleTarget))
        return
      const args = ruleArgs.split(",").map((v) => {
        if (v) {
          return this.form[v]
        }
        return null
      })

      let val
      switch (type) {
        // 时间差
        case "timepoor":
          val = getTimePoor(...args)
          break
        case "initials":
          //计算中文姓名缩写
          val = getChineseHeadLetter(...args)
          break
        case "idcard_birthdate":
          val = getInfoByIdCard(...args)
          break
        case "idcard_age":
          val = getInfoByIdCard(...args, "age")
          break
        case "idcard_gender":
          val = getInfoByIdCard(...args, "gender")
          break
        default:
          break
      }
      val && this.$set(this.form, ruleTarget, val)
    },
    // 获取prop  prop 以{}包裹
    getProp(value) {
      if (!value) return ""
      return value.replace(/[{][\w]*[}]/g, (word) => {
        return word.replace(/{|}/g, "")
      })
    },
    // 获取运算过程
    getProcess(value) {
      return value.replace(/[{][\w]*[}]/g, (word) => {
        const actualValue = this.form[word.replace(/{|}/g, "")]
        return actualValue ? actualValue : "stop"
      })
    },
    // 表单子项控制显隐
    showFormItem() {
      const { dynamicshSet, prop, noImmediate } = this.item
      if (dynamicshSet && dynamicshSet.length > 0) {
        this.$watch(
          `form.${prop}`,
          function (val) {
            const columns = this.columns || []
            const group = this.group || []
            const dyMap = {} // 显示数据集合
            dynamicshSet.forEach((dy) => {
              if (dyMap[dy.target]) {
                dyMap[dy.target].push(dy.value)
              } else {
                dyMap[dy.target] = [dy.value]
              }
            })

            Object.keys(dyMap).forEach((key) => {
              let targetItem = columns.find((_) => _.prop === key)
              if (!targetItem) {
                targetItem = group.find((_) => _.prop === key)
              }
              if (!targetItem) return
              const values = dyMap[key]
              let display = false
              if (Array.isArray(val)) {
                display = values.filter((v) => val.includes(v)).length > 0
              } else {
                display = values.includes(val)
              }

              if (!display && targetItem) {
                // 清空数据
                const newVal = Array.isArray(this.form[targetItem.prop])
                  ? []
                  : targetItem.type === "number"
                  ? undefined
                  : ""
                this.$set(this.form, targetItem.prop, newVal)
              }

              if (this.type === "form") {
                // 动态表格、表单处理
                setTimeout(() => {
                  this.$set(this.form, "$_hidden" + targetItem.prop, !display)
                }, 200)
              } else {
                this.$set(targetItem, "display", Boolean(display))
              }
            })
          },
          {
            immediate: !noImmediate,
          }
        )
      }
    },
    //
    handleBlur() {
      this.handleAlgorithm()
    },
    handleChange(val) {
      this.checkboxRepel(val)
      this.handleAlgorithm()
    },
  },
  created() {
    this.timerangeReset()
    this.numberReset()
    this.checkboxReset()
  },
  mounted() {
    this.showFormItem()
  },
}
</script>

<style lang="scss" scoped>
.custom-form-item {
  background: white;
  margin: 3px;
  &.isDefects {
    border: 1px solid red;
  }
  ::v-deep .el-form-item {
    padding: 10px 2px;
    margin-bottom: 0px;
  }
  .toothBit {
    ::v-deep .el-input-group__append {
      background-color: #1890ff;
      border-color: #1890ff;
      color: #fff;
    }
  }
  .el-input,
  .el-select,
  .el-cascader,
  .el-date-editor {
    width: 100%;
  }
  .el-input-number {
    width: 100%;
  }
  .flex {
    align-items: center;
    > div {
      flex: 1;
    }
  }
  .inline-block {
    > div {
      display: inline-block;
    }
  }
  .important_field {
    color: #ff4d4f;
    padding-left: 10px;
    display: inline-block;
    max-width: 150px;
    line-height: 1.2;
  }

  ::v-deep .el-input-number .el-input__inner {
    padding: 0 2px !important;
  }

  .el-radio {
    padding: 2px 0;
  }

  // 去除禁用样式
  ::v-deep .is-disabled {
    input {
      background-color: #fff;
      color: #606266;
    }

    .el-textarea__inner,
    .el-input__inner {
      background-color: #fff;
      color: #606266;
    }
    .el-checkbox__inner,
    .el-radio__inner {
      background-color: #fff;
    }
    + span.el-checkbox__label,
    + span.el-radio__label {
      color: #606266;
    }
    &.is-checked {
      .el-radio__inner {
        border-color: #1890ff;
        background: #1890ff;
        &::after {
          background: #fff;
        }
      }
      + .el-radio__label {
        color: #1890ff;
      }

      .el-checkbox__inner {
        background-color: #1890ff;
        border-color: #1890ff;
        &::after {
          border-color: #fff;
        }
      }
    }
  }

  .empty-tip {
    ::v-deep .el-form-item__label {
      color: red;
    }
  }

  ::v-deep .el-form-item__label {
    font-weight: bolder;
  }
  // ::v-deep .el-form-item__label::after {
  //   content: "☑";
  //   color: #ff4d4f;
  //   margin-left: 4px;
  // }

  ::v-deep .el-checkbox-group {
    &::after,
    &::before {
      content: " ";
      display: table;
    }
    &::after {
      clear: both;
      visibility: hidden;
      font-size: 0;
      height: 0;
    }
    .el-checkbox {
      float: left;
    }
  }
}
</style>
