<script>
import Input from '../components/Input.vue'
import InputNumber from '../components/InputNumber.vue'
import Select from '../components/Select.vue'
import Date from '../components/Date.vue'
import Cascader from '../components/Cascader.vue'
import Autocomplete from '../components/Autocomplete.vue'
import FileUpload from '../components/FileUpload/FileUpload.vue'
import Radio from '../components/Radio.vue'
import Checkbox from '../components/Checkbox.vue'
import CheckboxOther from '../components/CheckboxOther.vue'
import FormHead1 from '../components/FormHead1.vue'
import FormHead2 from '../components/FormHead2.vue'
import ChildForm from '../components/ChildForm.vue'
import Map from '../components/Map.vue'
import District from '../components/District.vue'

import { ElMessage } from 'element-plus'
import { cloneDeep } from 'lodash-es'
import { useValidator } from '@common/src/hooks/web/useValidator'
import { useUserStore } from '@common/src/store/modules/user'
import Anchor from './Anchor.vue'

export default {
  name: 'FormMixins',
  components: {
    Input,
    InputNumber,
    Select,
    Date,
    Cascader,
    FileUpload,
    Autocomplete,
    Radio,
    Checkbox,
    CheckboxOther,
    FormHead1,
    FormHead2,
    ChildForm,
    Map,
    District,
    ElMessage,
    Anchor
  },
  props: {
    templateForm: {
      type: Array,
      default: () => []
    },
    templateFormData: {
      type: Object,
      default: () => null
    },
    // 表单类型 edit add look
    formMode: {
      type: String,
      default: 'add'
    },
    // 表单列数
    col: {
      type: Number,
      default: 3
    },
    labelPosition: {
      type: String,
      default: 'left',
      validator: (value) => {
        return ['left', 'top'].includes(value)
      }
    },
    labelWidth: {
      type: String,
      default: '120px'
    },
    // 集成锚点功能
    useAnchor: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      tempForm: [],
      // (0:不展示，1:单行文本，2:多行文本，3:下拉列表单选，4:下拉列表多选，
      // 5:下拉树形列表单选，6:下拉树形列表多选,7:附件，8：日期选择，9：轨迹，10：日期时间选择，
      // 11.带选项的输入框，12.数字输入框 13.单选，14.多选，15.多选带其他，
      // 16.一级表单头，17.二级表单头, 18.子表单, 19.地图，20.富文本，21.下拉树形父子不关联)
      formType: {
        1: 'Input',
        2: 'Input',
        3: 'Select',
        4: 'Select',
        5: 'Cascader',
        6: 'Cascader',
        7: 'FileUpload',
        8: 'Date',
        10: 'Date',
        11: 'Autocomplete',
        12: 'InputNumber',
        13: 'Radio',
        14: 'Checkbox',
        15: 'CheckboxOther',
        16: 'FormHead1',
        17: 'FormHead2',
        18: 'ChildForm',
        19: 'Map',
        20: 'Editor',
        21: 'Cascader',
        // 以下是自定义 非动态部分
        101: 'District'
      },
      form: {},
      formItems: []
    }
  },
  computed: {
    // 动态生成规则
    rules() {
      const obj = {}
      this.tempForm.forEach((item) => {
        // 判断是否是输入型表单
        const isText = item.type === 'Input'
        obj[item.prop] = []
        if (item.required) {
          obj[item.prop].push({
            required: true,
            message: isText ? '请输入' : '请选择',
            trigger: isText ? 'blur' : 'change'
          })
        }
        // 自定义验证规则
        if (item.valid) {
          obj[item.prop].push({
            validator: item.valid,
            trigger: isText ? 'blur' : 'change'
          })
        }
        // 有字数限制时验证规则
        if (item.maxLength) {
          obj[item.prop].push({
            message: `最多 ${item.maxLength} 个字符`,
            trigger: 'blur',
            max: item.maxLength
          })
        }
      })
      return obj
    },
    // 用户的部门信息 用于进行 权限处理
    deptList() {
      return useUserStore().getUserDeptList
    },
    colLen() {
      return 24 / this.col
    }
  },
  watch: {
    templateForm: {
      handler(n) {
        if (!n?.length) {
          // console.log('无表单')
          return
        }
        this.setForm(n)
      },
      immediate: true
    }
  },
  methods: {
    // 额外属性 只有部分组件才会使用
    getAdditionalProps(item) {
      if (item.inputType === '18') {
        // 子表单使用
        return {
          labelWidth: this.labelWidth,
          labelPosition: this.labelPosition,
          col: this.col
        }
      } else {
        return {}
      }
    },
    setForm(arr) {
      // 根据表单配置生成 对应验证规则
      const { idCard, phone, email } = useValidator()
      const valids = [idCard(), phone(), email()]

      this.form = {}
      // 动态生成表单
      this.tempForm = arr
        .map((item) => {
          // 拼装
          return {
            label: item.fieldDesc,
            prop: item.fieldName,
            index: item.orderNo, // 排序
            type: this.formType[item.inputType],
            inputState: item.inputType === '2' ? 'textarea' : '', // 输入框的类型
            inputType: item.inputType,
            required: item.isNull === '1', // 是否必填(0:否，1:是)
            maxLength: item.limitLength,
            isListShow: item.isListShow === '1', // 是否列表中展示(0:否，1:是)
            fieldType: item.fieldType, // 字段类型(int,varchar等)
            isPrimaryKey: item.isPrimaryKey, // 是否主键(0:否，1:是)
            isMultiple: ['4', '6', '14', '15'].includes(item.inputType), // 下拉和树 有多选
            isSearch: item.isSearch === '1', // 可搜索字段
            // 字典与业务表查询时所用字段
            contactType: item.contactType,
            contactNo: item.contactNo,
            formHead: item.formHead || '',
            fieldTemplateList: item.fieldTemplateList, // 子表单数据
            deptAuth: item.deptAuth, // 部门权限
            isAddReadonly: item.isAddReadonly === '1', // 只读
            defaultValue: item.defaultValue,
            valueType: item.valueType, // 验证规则
            isFormShow: item.isFormShow === '1' // 是否在表单中显示
          }
        })
        .map((item) => {
          /**
           * 增加验证功能 valueType 1 身份证 2 手机号 3 邮箱
           */
          if (item.valueType) {
            item.valid = valids[Number(item.valueType) - 1].validator
          }
          return item
        })

      // 默认值处理
      this.tempForm
        .filter((item) => item.prop)
        .forEach((item) => {
          // item.isMultiple || item.formType === 7 时，默认值为数组 || inputType=8 =10 为null（）日期
          // this.form[item.prop] = item.defaultValue || (item.isMultiple ? [] : '')
          if (item.defaultValue) {
            this.form[item.prop] = item.defaultValue
          } else if (item.isMultiple) {
            this.form[item.prop] = []
          } else if (item.inputType === '8' || item.inputType === '10') {
            this.form[item.prop] = null
          } else this.form[item.prop] = ''
        })
      // 排序 过滤 显示的
      this.formItems = this.tempForm
        .sort((a, b) => a.index - b.index)
        .filter((item) => item.isFormShow)
      this.setParams()
    },
    resetForm() {
      this.form = {}
      this.formItems = []
      this.$nextTick(() => {
        this.$refs.form && this.$refs.form.clearValidate()
        // 文件上传 清空列表
        this.$refs.FileUpload?.length && this.$refs.FileUpload[0].reset()
      })
    },
    // 设置表单值
    async setParams() {
      const data = this.templateFormData
      if (!data) return
      for (const i of this.tempForm) {
        if (i.isMultiple && data[i.prop]) {
          data[i.prop] =
            (Array.isArray(data[i.prop]) ? data[i.prop] : data[i.prop]?.split(',')).filter(
              (i) => i !== ''
            ) || []
        }
      }
      this.form = { ...data }
    },
    // 获取表单值
    getParams() {
      return new Promise((resolve, reject) => {
        this.$refs.form.validate(async (valid) => {
          if (valid) {
            let form = cloneDeep(this.form)

            for (const i in form) {
              const item = this.tempForm.find((item) => item.prop === i)
              // 有子表单时 获取并验证子表单的数据
              if (item?.fieldTemplateList?.length) {
                const res = await this.$refs[item.prop][0].getParams().catch((err) => {
                  console.log(err)
                  reject(new Error(false))
                  // return false
                })
                // 拼装子表单数据
                form = { ...form, [item.prop]: JSON.stringify(res) }
              }

              // 使用地图组件时 如果选取点位 则单独存一下 district_no 字段
              if (item?.inputType === '19') {
                if (form[item.prop]) {
                  const val = JSON.parse(form[item.prop])
                  form.district_no = val.district_no
                } else form.district_no = ''
              }

              // 该数据为输入类型且为整型时  为空时转为null
              if (form[i] === '' && item?.fieldType === '1') {
                form[i] = null
              }
              // 数组转字符串
              if (Array.isArray(form[i])) {
                form[i] = form[i].join(',')
              }
            }
            // 移除为空的key
            delete form['']

            resolve(form)
          } else {
            ElMessage.warning('有必填项未完成')
            reject(new Error(false))
          }
        })
      })
    },
    // 提交表单
    async submit() {
      const params = await this.getParams()
      console.log(params)
      if (!params) return

      return params
    },
    // 查看当前表单是否有权限操作
    noAuth(deptStringList) {
      if (!deptStringList) return true
      let index = 0
      const data = String(deptStringList)

      for (const i of data.split(',')) {
        const item = this.deptList.find((j) => j.deptId == i)
        if (item) index++
      }
      return !index
    }
  }
}
</script>

<style lang="less" scoped>
@import '../style/index.less';
</style>
