<template>
  <div v-show="!hidden">
    <!-- 子表-->
    <ibps-dynamic-form-table
      v-if="field.field_type==='table'"
      ref="formItem"
      :value.sync="dataModel"
      :label="field.label"
      :field="field"
      :rights="fieldRights"
      :form-data="models"
      :desc-position="descPosition"
      :readonly-rights="readonlyRights"
      :readonly="readonly"
      :params="params"
      :main-code="code"
      :required="required"
      :rules="rules"
      v-on="listeners"
    />
    <ibps-dynamic-form-field
      v-else
      ref="formItem"
      :field="field"
      :desc-position="descPosition"
      :value.sync="dataModel"
      :readonly="readonly"
      :required="required"
      :rules="rules"
      :form-data="$utils.isNotEmpty(row)?formData:models"
      :params="params"
      :form-opinion="formOpinion"
      v-on="listeners"
    />

    <template v-if="field && field.desc && !noDesc">
      <ibps-field-desc :desc="field.desc" :desc-position="descPosition" />
    </template>
  </div>
</template>
<script>
import FormUtil from '../utils/formUtil'
import FormOptions from '../constants/formOptions'

export default {
  props: {
    models: [Object, Array], // 字段数据
    formData: [Array, Object], // 表单数据（包含子表）
    rights: { // 字段权限
      type: [String, Object],
      default: 'e'
    },
    field: {
      type: Object,
      required: true
    },
    mainCode: String, // 主表名
    row: [String, Number], // 子表行数
    code: {
      type: String
    },
    readonlyRights: { // 只读
      type: Boolean,
      default: false
    },
    // 扩展参数
    params: Object,
    formOpinion: Array, // 表单意见
    descPosition: String
  },
  data() {
    let defaultVal = ''
    if (this.fieldType === 'table') {
      const isOne2More = (this.fieldOptions['relation'] || 'one2More') === 'one2More'
      defaultVal = isOne2More ? [] : {}
    } else {
      defaultVal = ''
    }
    return {
      dataModel: this.models[this.field.name] || defaultVal,
      fieldRights: this.rights[this.field.name] || 'e'
    }
  },
  computed: {
    fieldName() {
      return this.field.name
    },
    fieldType() {
      return this.field.field_type
    },
    subTableRights() { // 子表权限
      if (this.fieldType === 'table' && this.$utils.isNotEmpty(this.fieldRights) &&
      this.$utils.isPlainObject(this.fieldRights)) {
        return this.fieldRights['rights']
      }
      return false
    },
    hidden() { // 是否隐藏
      // pc 设置移动端隐藏
      if (!this.$utils.toBoolean(this.fieldOptions.mobile, true)) {
        return true
      }
      if (this.subTableRights) {
        return this.subTableRights === FormOptions.t.PERMISSIONS.HIDE
      }
      return this.fieldRights === FormOptions.t.PERMISSIONS.HIDE || this.fieldType === 'hidden' ||
      (this.fieldType === 'approval_opinion' && (this.$utils.isNotEmpty(this.defId) || this.hiddenApprovalOpinion))
    },
    readonly() { // 是否只读
      if (this.subTableRights) {
        return this.subTableRights === FormOptions.t.PERMISSIONS.READ
      }
      return this.readonlyRights ? true : this.fieldRights === FormOptions.t.PERMISSIONS.READ
    },
    required() { // 必填  【只读隐藏，都设置非必填】
      if (this.readonly || this.hidden) {
        return false
      }
      if (this.subTableRights) {
        return this.subTableRights === FormOptions.t.PERMISSIONS.REQUIRED
      }
      return this.fieldRights === FormOptions.t.PERMISSIONS.REQUIRED ? true : this.field.field_options.required || false
    },
    fieldOptions() {
      return this.field.field_options || {}
    },
    formula() {
      return this.params.responseFormula ? this.params.responseFormula : null
    },
    linkages() {
      return this.params.responseLinkages ? this.params.responseLinkages : null
    },
    noDesc() {
      const noDesc = ['editor', 'attachment', 'signature', 'desc', 'bpmInstHis', 'bpmLink', 'alert']
      return noDesc.includes(this.fieldType)
    },
    // 表单验证
    rules() {
      if (this.readonly || this.hidden) { return [] }
      return FormUtil.buildFormRules(this.field, this.required, this.formData)
    },
    listeners() {
      return {
        ...this.$listeners,
        change: (data) => { this.emitEvent('change', data) }, // 在 Input 值改变时触发
        focus: (event) => { this.emitEvent('focus', event) }, // 在 Input 获得焦点时触发
        blur: (event) => { this.emitEvent('blur', event) }, // 在 Input 失去焦点时触发
        // click: (event) => { this.emitEvent('click', event) } // 在 Input 点击时触发
        'change-data': this.handleModels // 数据改变
      }
    }
  },
  watch: {
    dataModel: {
      handler(val) {
        if (FormOptions.t.NON_MODEL_FIELD_TYPES.includes(this.fieldType)) {
          return
        }
        this.handleModels(this.field.name, val)
        this.$nextTick(() => {
          // 值改变进行公式计算
          this.runCalFormula()
          // 值改变进行数据联动
          this.runLinkage()
        })
      },
      deep: true,
      immediate: true
    },
    models: {
      handler(val, oldVal) {
        this.dataModel = val[this.field.name]
      },
      deep: true
    },
    fieldRights: {
      handler(val) {
        this.handleFieldRights(this.fieldName, val)
      },
      deep: true,
      immediate: true
    },
    rights: {
      handler(val, oldVal) {
        this.fieldRights = val[this.fieldName]
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    handleModels(name, val) {
      this.models[name] = val
      this.$emit('update:models', {
        ...this.models,
        [name]: val
      })
    },
    handleFieldRights(name, val) {
      if (this.$utils.isEmpty(name)) {
        return
      }
      this.rights[name] = val
      this.$emit('update:rights', {
        ...this.rights,
        [name]: val
      })
    },
    // 更新主表的数据
    setFieldData(name, val) {
      setTimeout(() => {
        this.$emit('update-form-data', name, val)
      }, 10)
    },
    // 表单意见
    changeFormOpinion(data) {
      this.$emit('change-form-opinion', data)
    },
    /**
     * 进行公式计算
     */
    runCalFormula() {
      if (!this.formula) return
      const { field, code, mainCode, row } = this
      if (field.field_type === 'table') {
        const columns = field.field_options.columns || []
        for (let i = 0; i < columns.length; i++) {
          const column = columns[i]
          this.calFormula(field.name, column.name, mainCode, row)
        }
      } else {
        this.calFormula(code, field.name, mainCode, row)
      }
    },
    calFormula(code, name, mainCode, row) {
      const key = code + '.' + name
      const formulas = this.formula[key]
      if (formulas) {
        if (mainCode) {
          FormUtil.runSubCalFormula(this, formulas, code, mainCode, row)
        } else {
          FormUtil.runMainCalFormula(this, formulas, code)
        }
      }
    },
    /**
     * 进行联动数据
     */
    runLinkage() {
      if (!this.linkages) return
      const { field, code } = this
      if (field.isSub) { // 子表
        const key = code + '.' + field.name
        const linkages = this.linkages ? this.linkages[key] : null
        if (linkages) {
          FormUtil.runLinkage(this, linkages, field, field.row)
        }
      } else {
        field.code = code
        const key = field.code + '.' + field.name
        const linkages = this.linkages ? this.linkages[key] : null
        if (linkages) {
          FormUtil.runLinkage(this, linkages, field)
        }
      }
    },
    emitEvent(event) {
      this.$emit(event, ...Array.from(arguments).slice(1))
    },
    /**
     * 获得表单验证
     */
    getFormValidator() {
      return this.$refs.formItem.$validator
    },
    /**
     *  获得表单验证的第一个错误
     */
    getFirstError() {
      return this.$refs.formField.errors.has(this.field.name) ? this.$refs.formField.errors.first(this.field.name) : ''
    },
    /**
     * 获得表单错误信息
     */
    getFormErrors() {
      return this.$refs.formItem.errors
    },
    /**
     *  当前字段
     */
    getEl() {
      return this.$refs.formItem.getEl()
    }
  }
}
</script>

