<template>
  <view>
    <view
      :key="item.id"
      v-for="(item, index) of scheme"
      :style="{ marginTop: index !== 0 && item.type === 'label' ? '15px' : '0' }"
    >
      <!-- 标题文字 label -->
      <l-title v-if="item.type === 'label'" border>{{ item.title }}</l-title>

      <!-- 文字输入框 text -->
      <l-input
        v-else-if="item.type === 'text'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :disabled="!isEdit(item)"
        :required="Boolean(item.verify)"
        :title="item.title"
      />

      <!-- 单选和选择 radio和select -->
      <l-select
        v-else-if="item.type === 'radio' || item.type === 'select'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :disabled="!isEdit(item)"
        :required="Boolean(item.verify)"
        :range="item.__sourceData__"
        :title="item.title"
      />

      <!-- 多选 checkbox -->
      <l-checkbox-picker
        v-else-if="item.type === 'checkbox'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :readonly="!isEdit(item)"
        :required="Boolean(item.verify)"
        :range="item.__sourceData__"
        :title="item.title"
      />

      <!-- 多行文本 textarea -->
      <l-textarea
        v-else-if="item.type === 'textarea' || item.type === 'texteditor'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :readonly="!isEdit(item)"
        :required="Boolean(item.verify)"
        :title="item.title"
      />

      <!-- 时间日期 datetime -->
      <l-datetime-picker
        v-else-if="item.type === 'datetime' && Number(item.dateformat) === 1"
        @input="setValue(item.__valuePath__, $event)"
        @change="relChange(item.id, $event)"
        :value="getValue(item.__valuePath__)"
        :disabled="!isEdit(item)"
        :required="Boolean(item.verify)"
        :title="item.title"
      />

      <!-- 日期 date -->
      <l-date-picker
        v-else-if="item.type === 'datetime' && Number(item.dateformat) !== 1"
        @input="setValue(item.__valuePath__, $event)"
        @change="relChange(item.id, $event)"
        :value="getValue(item.__valuePath__)"
        :required="Boolean(item.verify)"
        :disabled="!isEdit(item)"
        :title="item.title"
      />

      <!-- 日期区间 datetimerange -->
      <l-input
        v-else-if="item.type === 'datetimerange'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :disabled="!isEdit(item)"
        :required="Boolean(item.verify)"
        :title="item.title"
        placeholder=""
      />

      <!-- 当前状态 currentInfo：组织结构 organize  -->
      <l-organize-picker
        v-else-if="item.type === 'currentInfo' && item.dataType !== 'time'"
        :value="getValue(item.__valuePath__)"
        :type="item.dataType"
        :required="Boolean(item.verify)"
        :title="item.title"
        readonly
      />

      <!-- 当前状态 currentInfo：时间 time -->
      <l-input
        v-else-if="item.type === 'currentInfo' && item.dataType === 'time'"
        :value="getValue(item.__valuePath__)"
        :disabled="!isEdit(item)"
        :required="Boolean(item.verify)"
        :title="item.title"
        disabled
      />

      <!--  编码 encode -->
      <l-input
        v-else-if="item.type === 'encode'"
        :value="getValue(item.__valuePath__)"
        :required="Boolean(item.verify)"
        :title="item.title"
        disabled
      />

      <!-- 公司人员结构选单 organize -->
      <l-organize-picker
        v-else-if="item.type === 'organize'"
        @input="setValue(item.__valuePath__, $event)"
        @change="relChange(item.id, $event)"
        :value="getValue(item.__valuePath__)"
        :rootId="getValue(item.__relationPath__)"
        :type="item.dataType"
        :required="Boolean(item.verify)"
        :readonly="item.__relationPath__ ? !isEdit(item) || !getValue(item.__relationPath__) : !isEdit(item)"
        :title="item.title"
        :placeholder="displayPlaceHolder(item)"
      />

      <!-- 文件上传 upload -->
      <l-upload-file
        v-else-if="item.type === 'upload'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :required="Boolean(item.verify)"
        :readonly="!isEdit(item)"
        :title="item.title"
        :number="9"
      />

      <!-- HTML内容 html -->
      <view v-else-if="item.type === 'html'" class="cu-form-group">
        <view class="bg-white">
          <u-parse :imageProp="{ domain: apiRoot }" :content="CONVERT_HTML(item.title)"></u-parse>
        </view>
      </view>

      <!-- 表格 girdtable -->
      <l-customform-table
        v-else-if="item.type === 'girdtable'"
        @input="setValue(item.__valuePath__, $event)"
        :value="getValue(item.__valuePath__)"
        :item="item"
        :edit="isEdit(item)"
      />
    </view>
  </view>
</template>

<script>
import get from 'lodash/get'
import set from 'lodash/set'
import moment from 'moment'

export default {
  name: 'l-customform',

  props: {
    scheme: { default: () => [] },
    editMode: { default: true },
    initFormValue: { default: () => ({}) },
    rel: { default: () => ({}) }
  },

  data() {
    return {
      formValue: this.initFormValue
    }
  },

  methods: {
    // 本方法由调用方使用 $refs 的方式调用
    // 给表单设置值
    setFormValue(formValue) {
      this.formValue = formValue
    },

    // 本方法由调用方使用 $refs 的方式调用
    // 获取表单值
    getFormValue() {
      return this.formValue
    },

    // 本方法由调用方使用 $refs 的方式调用
    // 依次验证表单项，返回一个所有错误提示的数组，如果为空数组则表示无错误
    verifyValue() {
      const errorList = []
		console.log(this.scheme)
      this.scheme
        .filter(t => t.verify)
        .forEach(schemeItem => {
          if (schemeItem.table && schemeItem.field) {
			  console.log(schemeItem.verify,'hemeItem.verify')
            const verifyFunc = this.verify[schemeItem.verify]
			console.log(schemeItem.verify)
            const verifyResult = verifyFunc(this.getValue(schemeItem.__valuePath__))
            if (verifyResult !== true) {
              errorList.push(`[${schemeItem.title}]: ${verifyResult}`)
            }
          } else if (schemeItem.fieldsData) {
            this.getValue(schemeItem.__valuePath__).forEach((valueItem, valueIndex) => {
              schemeItem.fieldsData.forEach(fieldItem => {
                const verifyFunc = this.verify[fieldItem.verify]
                const verifyResult = verifyFunc(
                  this.getValue(`${schemeItem.__valuePath__}.${valueIndex}.${fieldItem.field}`)
                )
                if (verifyResult !== true) {
                  errorList.push(`[表格${schemeItem.title}第${tableIndex}行${fieldItem.name}列]: ${verifyResult}`)
                }
              })
            })
          }
        })

      return errorList
    },

    // 设置表单数据的方法
    setValue(path, value) {
      set(this.formValue, path, value)
    },

    // 获取表单数据的方法
    getValue(path) {
      return get(this.formValue, path)
    },

    // 处理互相关联的表单项（organize 级联，datetimerange 日期区间）
    relChange(id, val) {
      const relList = this.rel[id] || []
      relList.forEach(relItem => {
        if (relItem.type === 'organize') {
          // 组织结构，重设级联过来的组件
          this.setValue(relItem.path, '')

          // 向下递归
          if (this.rel[relItem.id]) {
            this.relChange(relItem.id)
          }
        } else if (relItem.type === 'datetimerange') {
          // 时间日期区间，重新计算
          const startTime = this.getValue(relItem.startPath)
          const endTime = this.getValue(relItem.endPath)

          if (!startTime || !endTime || moment(endTime).isBefore(startTime)) {
            return
          }

          const newVal = moment
            .duration(moment(endTime).diff(moment(startTime)))
            .asDays()
            .toFixed(0)

          this.setValue(relItem.path, newVal)
        }
      })
    },

    // 获取表单项的 placeholder ，在无法编辑时隐藏
    displayPlaceHolder(item) {
      if (!this.editMode || item.type !== 'organize') {
        return ' '
      }

      if (!item.relation) {
        return `请选择${item.title || item.name}`
      }

      const parentType = { user: '部门', department: '公司' }[item.dataType]
      const parentValue = this.getValue(item.__relationPath__)
      return parentValue ? `请选择${item.title || item.name}` : `请先选择上级${parentType}`
    },

    // 获取表单项可否编辑
    isEdit(item) {
      return this.editMode && item.edit !== 0
    }
  },

  computed: {
    verify() {
      return {
        NotNull: t => (t !== null && t !== undefined && t !== '' && (!Array.isArray(t) || t.length > 0)) || '不能为空',
        Num: t => !isNaN(t) || '须输入数值',
        NumOrNull: t => t.length <= 0 || !isNaN(t) || '须留空或输入数值',
        Email: t => /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须符合Email格式',
        EmailOrNull: t =>
          t.length <= 0 || /^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_]+.[a-zA-Z0-9]+$/.test(t) || '须留空或符合Email格式',
        EnglishStr: t => /^[a-zA-Z]*$/.test(t) || '须由英文字母组成',
        EnglishStrOrNull: t => t.length <= 0 || /^[a-zA-Z]*$/.test(t) || '须留空或由英文字母组成',
        Phone: t => /^[+0-9- ]*$/.test(t) || '须符合电话号码格式',
        PhoneOrNull: t => t.length <= 0 || /^[+0-9- ]*$/.test(t) || '须留空或符合电话号码格式',
        Fax: t => /^[+0-9- ]*$/.test(t) || '须符合传真号码格式',
        Mobile: t => /^1[0-9]{10}$/.test(t) || '须符合手机号码格式',
        MobileOrPhone: t => /^[+0-9- ]*$/.test(t) || /^1[0-9]{10}$/.test(t) || '须符合电话或手机号码格式',
        MobileOrNull: t => t.length <= 0 || /^1[0-9]{10}$/.test(t) || '须留空或符合手机号码格式',
        MobileOrPhoneOrNull: t =>
          t.length <= 0 || /^1[0-9]{10}$/.test(t) || /^[+0-9- ]*$/.test(t) || '须留空或符合手机/电话号码格式',
        Uri: t => /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须符合网址Url格式',
        UriOrNull: t => t.length <= 0 || /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须留空或符合网址Url格式',
		PositiveFloatint:t=> /^([1-9]\d*|(0|[1-9]\d*)\.\d*[1-9])$/.test(t) || '请输入正确的整数或小数(不能为零和负数)'
      }
    }
  }
}
</script>
