vue+element ui实现表单组件的封装

效果图:
在这里插入图片描述
在这里插入图片描述

主要是使用vue + elmentUi 的from的基础上进行封装
在这里插入图片描述

使用改组件,是需要自定义从父组件传入一下字段表单字段

export const topicTypeMainTaskEdit: any = new Map([
  // 主任务可编辑状态
  [
    'feasibleInstructions', // 督办件
    [
      {
        value: 'documentNum',
        formKey: ['documentNum'],
        rules: [
          { required: true, message: '请输入办文编号', trigger: 'blur' },
          { min: 0, max: 30, message: '办文编号字数长度超过限制' }
        ],
        label: '办文编号',
        class: 'half-item',
        type: 'text',
        maxlength: 30
      },
      {
        value: 'taskTitle',
        formKey: ['taskTitle'],
        rules: [
          { required: true, message: '请输入任务标题', trigger: 'blur' },
          { min: 0, max: 300, message: '任务标题字数长度超过限制' }
        ],
        label: '任务标题',
        class: 'half-item-all',
        isMate: true, // 填写时是否和关联任务的相应的字段匹配
        type: 'text',
        maxlength: 300
      },
      {
        value: 'taskSourceId',
        formKey: {
          value: 'taskSourceId',
          label: 'taskSource'
        },
        rules: [
          { required: true, message: '请选择事项类型', trigger: 'change' }
        ],
        hasSlot: {
          key: 'taskSource',
          label: '事项类型管理',
          type: 'managementMatters'
        },
        slotKey: 'taskSource',
        label: '事项类型',
        type: 'select',
        list: 'itemTypeList',
        options: () => JSON.parse(localStorage.getItem('store')).firstLevelTask.itemTypeData.filter(res => { return res.dicStatus * 1 === 1 })
      },
      {
        value: 'mainLeaderId',
        formKey: {
          value: 'mainLeaderId',
          label: 'mainLeader'
        },
        label: '批示领导',
        hasSlot: {
          key: 'mainLeader',
          label: '批示领导管理',
          type: 'managementMatters'
        },
        slotKey: 'mainLeader',
        type: 'select',
        multiple: true,
        list: 'leaderOptions',
        options: () => JSON.parse(localStorage.getItem('store')).firstLevelTask.mainLeaderData.filter(res => { return res.dicStatus * 1 === 1 })
      },
      {
        value: 'indicationTime',
        formKey: ['indicationTime'],
        label: '批示时间',
        class: 'half-item',
        type: 'date',
        noLimitCurrentDate: true // false为限制不能选当天以前的日期
      },
      {
        value: 'itemClaim',
        formKey: ['itemClaim'],
        rules: [
          { min: 0, max: 300, message: '省领导批示内容字数长度超过限制' }
        ],
        label: '省领导批示内容',
        class: '',
        type: 'textarea',
        showWordLimit: true,
        maxlength: 300,
        rows: 4
      },
      {
        value: 'workRequire',
        formKey: ['workRequire'],
        rules: [
          { min: 0, max: 300, message: '领导跟批情况字数长度超过限制' }
        ],
        label: '领导跟批情况',
        class: '',
        type: 'textarea',
        showWordLimit: true,
        maxlength: 300,
        rows: 4
      },
      {
        value: 'documentUrl',
        formKey: ['documentUrl'],
        // rules: [
        //   { required: true, message: '请输入相关公文', trigger: 'blur' }
        // ],
        label: '相关公文',
        class: 'half-item',
        type: 'text',
        maxlength: 300
      },
      // {
      //   value: 'documentUrl',
      //   label: '相关公文',
      //   formKey: ['documentUrl', 'mainDeptId', 'mainUnitId'],
      //   type: 'authPanel',
      //   authPanelType: 'department',
      //   deptArray: [],
      //   multiple: true
      // },
      {
        value: 'taskContent',
        formKey: ['taskContent'],
        rules: [
          { required: true, message: '请输入任务描述', trigger: 'blur' },
          { min: 0, max: 800, message: '任务描述字数长度超过限制' }
        ],
        label: '任务描述',
        class: '',
        type: 'textarea',
        showWordLimit: true,
        isMate: true, // 填写时是否和关联任务的相应的字段匹配
        maxlength: 800,
        rows: 4
      },
      {
        value: 'mainUnitName',
        rules: [
          { required: true, message: '请选择主办处室', trigger: 'blur' }
        ],
        label: '主办处室',
        formKey: ['mainUnitName', 'mainDeptId', 'mainUnitId'],
        type: 'authPanel',
        authPanelType: 'department',
        deptArray: [],
        multiple: true,
        linkage: 'mainUnitName',
        fn: (data: any, formData: any) => {
          let interrupt = false
          const departId = Array.isArray(data) && data.map(item => {
            return item.departId
          })
          formData && formData.forEach(i => {
            if (i.key === 'assistUnitNames') {
              i.deptArray.forEach(j => {
                if (departId.indexOf(j.departId) > -1) {
                  interrupt = true
                  Message({
                    message: `${j.name}不能同时作为主办、会办处室`,
                    type: 'error'
                  })
                }
              })
            }
          })
          return {
            interrupt
          }
        }
      },
      {
        value: 'assistUnitNames',
        label: '会办处室',
        formKey: ['assistUnitNames', 'assistDeptIds', 'assistUnitIds'],
        type: 'authPanel',
        authPanelType: 'department',
        deptArray: [],
        multiple: true,
        linkage: 'assistUnitNames',
        fn: (data: any, formData: any) => {
          let interrupt = false
          const departId = Array.isArray(data) && data.map(item => {
            return item.departId
          })
          formData && formData.forEach(i => {
            if (i.key === 'mainUnitName') {
              i.deptArray.forEach(j => {
                if (departId.indexOf(j.departId) > -1) {
                  interrupt = true
                  Message({
                    message: `${j.name}不能同时作为主办、会办处室`,
                    type: 'error'
                  })
                }
              })
            }
          })
          return {
            interrupt
          }
        }
      },
      {
        value: 'leaderId',
        formKey: {
          value: 'leaderId',
          label: 'leader'
        },
        rules: [
          { required: true, message: '请选择分管领导', trigger: 'change' }
        ],
        label: '分管领导',
        hasSlot: {
          key: 'leader',
          label: '分管领导管理',
          type: 'managementMatters'
        },
        slotKey: 'leader',
        type: 'select',
        multiple: true,
        list: 'leaderOptions',
        options: () => JSON.parse(localStorage.getItem('store')).firstLevelTask.leaderData.filter(res => { return res.dicStatus * 1 === 1 })
      },
      {
        value: 'supervisionCycle',
        formKey: ['cycleType', 'supervisionCycle', 'supervisionCycleIds', 'firstSubmitTime'],
        rules: [
          { required: true, message: '请选择报送时间' }
        ],
        label: '报送时间',
        class: 'half-item',
        type: 'deliveryTime'
      },
      {
        value: 'limitDate',
        formKey: ['limitDate'],
        label: '办结期限',
        class: 'half-item',
        type: 'date'
      },
      {
        value: 'peopleArray',
        formKey: ['sendCopys', 'sendCopysId', 'sendCopysDeptId'],
        label: '抄送人员',
        type: 'authPanel',
        authPanelType: 'people',
        deptArray: [],
        multiple: true,
        hasSameDataDefaultProps: { isSame: 'complexId', parentId: 'departId', childrenId: 'userId' }
      }
    ]
  ],
  [
    'keyWork', // 重点工作
    [
      {
        value: 'taskTitle',
        formKey: ['taskTitle'],
        rules: [
          { required: true, message: '请输入任务标题', trigger: 'blur' },
          { min: 0, max: 300, message: '任务标题字数长度超过限制' }
        ],
        label: '任务标题',
        type: 'text',
        maxlength: 300
      },
      {
        value: 'workRequire',
        formKey: ['workRequire'],
        rules: [
          { min: 0, max: 500, message: '描述字数长度超过限制' }
        ],
        label: '描述',
        type: 'textarea',
        showWordLimit: true,
        maxlength: 500,
        rows: 4
      },
      {
        value: 'taskSourceId',
        formKey: {
          value: 'taskSourceId',
          label: 'taskSource'
        },
        rules: [
          { required: true, message: '请选择事项类型', trigger: 'change' }
        ],
        hasSlot: {
          key: 'taskSource',
          label: '事项类型管理',
          type: 'managementMatters'
        },
        slotKey: 'taskSource',
        label: '事项类型',
        type: 'select',
        list: 'itemTypeList',
        options: () => JSON.parse(localStorage.getItem('store')).firstLevelTask.itemTypeData.filter(res => { return res.dicStatus * 1 === 1 })
      },
      // {
      //   value: 'documentUrl',
      //   label: '相关公文',
      //   formKey: ['documentUrl'],
      //   type: 'authPanel',
      //   authPanelType: 'department',
      //   deptArray: [],
      //   multiple: true
      // },
      {
        value: 'documentUrl',
        formKey: ['documentUrl'],
        label: '相关公文',
        class: 'half-item',
        type: 'text',
        maxlength: 300
      },
      {
        value: 'peopleArray',
        formKey: ['sendCopys', 'sendCopysId', 'sendCopysDeptId'],
        label: '抄送人员',
        type: 'authPanel',
        authPanelType: 'people',
        deptArray: [],
        multiple: true,
        hasSameDataDefaultProps: { isSame: 'complexId', parentId: 'departId', childrenId: 'userId' }
      }
    ]
  ]
])

然后先初始化表单字段的数据

const getTopicTypeData = this.topicTypeData.length > 0 ? this.topicTypeData : topicTypeData[this.topicTypeDataKey].get(this.otherTask || this.topicType)
    // const getTopicTypeData = this.topicTypeData.length > 0 ? this.topicTypeData : topicTypeData[this.topicTypeDataKey].get(this.topicType || this.otherTask)
    this.topicTypeMainTask = [...getTopicTypeData.map(item => {
      return { ...item, type: item.type === 'text' ? 'input' : item.type, isEdit: !item.disabled, key: item.value, value: '', options: typeof item.options === 'function' ? item.options() : item.options || '' }
    }), { key: 'fileJson', type: 'upload', value: '' }]
    this.topicTypeMainTask.forEach(item => {
      // if (item.type === 'authPanel' && item.authPanelType === 'people') {
      if (item.type === 'authPanel' && item.authPanelType === 'people' && !item.mixedData) {
        item.deptArray = this.taskData.sendCopysId ? this.resestPeopleArray(this.taskData.sendCopysId, this.taskData.sendCopys, this.taskData.sendCopysDeptId) : []
        item.value = this.taskData[item.key]
      } else if (item.type === 'authPanel' && (item.authPanelType === 'department' || (item.mixedData === true && item.authPanelType === 'people'))) {
        // else if (item.type === 'authPanel' && item.authPanelType === 'department') {
        if (item.disabled && typeof item.disabled === 'function') {
          item.disabled = item.disabled(!!(this.taskData.status && this.taskData.status === '4'))
        }
        item.deptArray = this.resestDeptArr(item.formKey)
        item.value = this.taskData[item.key]
      } else if (item.type === 'deliveryTime') {
        item.deliveryTime = {
          supervisionCycleIds: this.taskData.supervisionCycleIds,
          cycleType: this.taskData.cycleType,
          supervisionCycle: this.taskData.supervisionCycle,
          firstSubmitTime: this.taskData.firstSubmitTime
        }
        item.value = this.taskData[item.key]
      } else if (item.type === 'select') {
        if (this.topicType === 'coordinatingCommittee' && item.key === 'meetingTypeId') {
          item.value = '1'
        } else {
          if (item.multiple) {
            item.value = (this.taskData[item.key] && this.taskData[item.key].split(',')) || []
          } else {
            item.value = this.taskData[item.key]
          }
        }
      } else if (item.type === 'upload') {
        item.value = this.taskData[item.key] ? this.taskData[item.key] : '[]'
      } else {
        item.value = this.taskData[item.key]
      }
    })

这些字段都是存在在一个新ts文件中,如果对象有值,根据不用的表单类型进行赋值回显,没有的话就是空

表单组件中传入的值代表的意思
 props: {
    isShowSearchBtn: { // 是否显示查询按钮
      type: Boolean,
      default: true
    },
    labelPosition: { // 表单文本标题的位置
      type: String,
      default: 'right'
    },
    labelWidth: { // 表单文本标题的宽度
      type: String,
      default: ''
    },
    formItemWidth: {
      type: String,
      default: '100%'
    },
    setStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    updateModel: {
      type: Object,
      default: () => {
        return {}
      }
    },
    isRules: { // 是否要校验
      type: Boolean,
      default: true
    },
    rules: { // 校验规则
      type: Object,
      default: () => {
        return {}
      }
    },
    formData: { // 表单数据
      type: Array,
      default: () => {
        return []
      }
    },
    inline: { // 是否是行内
      type: Boolean,
      default: true
    },
    flexWrap: {
      type: Boolean,
      default: false
    }, // 控制表单是否换行
    justifyContent: { // 布局
      type: String,
      default: 'space-between'
    }, // 表单布局风格
    noCheck: {
      type: Boolean,
      default: true
    },
    pickerOptions: { // 时间日期表单的时间限制
      type: Object,
      default: () => {
        return {
          disabledDate(time) {
            return time.getTime() < Date.now() - 8.64e7
          }
        }
      }
    }
  },

如果表单数据对象遍历中出现slotKey,代表这个字段是使用插槽
在这里插入图片描述

在父组件中使用插槽,然后将根据不用字段显示不同的内容
在这里插入图片描述

表单组件里面的表单类型
<el-form
      ref="formRef"
      :inline="inline"
      :model="model"
      :rules="isRules ? rules : {}"
      :label-position="labelPosition"
      :label-width="labelWidth"
      :style="{'flex-wrap': flexWrap ? 'nowrap' : 'wrap', 'justify-content' : justifyContent}"
    >
      <el-form-item
        v-for="(item,i) in formData"
        :key="'form'+i"
        :class="item.type + '-form'"
        :label="item.label"
        :prop="item.key"
        :rules="isRules ? item.rules : []"
        :error="item.success ? '' : item.message"
        :style="{width: item.width ? item.width : formItemWidth, ...item.style }"
      >
        <!-- 插槽 -->
        <template v-if="item.slotKey">
          <slot :name="item.slotKey" :row="item" />
        </template>
        <template v-else>
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'input'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            :placeholder="item.placeholder || '请输入'"
            @blur="handleBlur(item)"
          />
          <!-- 文本框 -->
          <el-input
            v-else-if="item.type === 'textarea'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            type="textarea"
            :rows="3"
            :placeholder="item.placeholder || '请输入'"
            @blur="handleBlur(item)"
          />
          <!-- 下拉框 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :multiple="item.multiple"
            :placeholder="item.placeholder || '请选择'"
            @change="(val) => updateDeptArray(val, item)"
          >
            <el-option v-for="(option, j) in item.options" :key="'option'+j" :label="option.label" :value="option.value" />
          </el-select>
          <!-- 输入框(可以过滤) -->
          <el-autocomplete
            v-else-if="item.type === 'autocomplete'"
            v-model="model[item.key]"
            :fetch-suggestions="(a,b) => querySearch(a,b,item.options)"
            :placeholder="item.placeholder || '请输入'"
            @select="(val) => handleSelect(val, item)"
          />
          <!-- 单选框 -->
          <el-radio-group v-else-if="item.type === 'radio'" v-model="model[item.key]">
            <el-radio v-for="(option, z) in item.options" :key="'option'+z" :label="option.value">
              {{ option.label }}
            </el-radio>
          </el-radio-group>
          <!-- 日期 -->
          <el-date-picker
            v-else-if="item.type === 'date'"
            :key="'datePicker' + i"
            v-model="model[item.key]"
            :picker-options="!item.noLimitCurrentDate && pickerOptions"
            type="date"
            :placeholder="item.placeholder || '请选择'"
            value-format="yyyy-MM-dd"
            format="yyyy-MM-dd"
          />
          <!-- 日期时间 -->
          <el-date-picker
            v-else-if="item.type === 'daterange'"
            :key="'daterangePicker' + i"
            v-model="model[item.key]"
            :picker-options="!item.noLimitCurrentDate && pickerOptions"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            format="yyyy-MM-dd"
          />
          <!-- 数字 -->
          <el-input-number
            v-else-if="item.type === 'inputNumber'"
            v-model="model[item.key]"
            :min="1"
          />
          <!-- 报送时间 -->
          <div v-else-if="item.type === 'deliveryTime'" class="module-timeInput" @click="showSubMission">
            <el-input v-model="model[item.key]" :disabled="!item.isEdit" :placeholder=" item.placeholder || '请选择报送时间'" readonly />
          </div>
          <!-- 单位或者人员组织构架 -->
          <auth-panel
            v-else-if="item.type === 'authPanel'"
            :auth-panel-params="item.params"
            :mixed-data="item.mixedData"
            :disabled="item.disabled"
            :type="item.authPanelType"
            :dept-array="item.deptArray"
            :has-same-data-default-props="item.hasSameDataDefaultProps"
            :multiple="item.multiple"
            :stage-single="item.stageSingle"
            :select-all="true"
            @update:deptArray="(val) => updateDeptArray(val, item)"
          />
          <!-- <auth-panel v-else-if="item.type === 'authPanel'" :disabled="!item.isEdit" :type="item.authPanelType" :dept-array="item.deptArray" :has-same-data-default-props="item.hasSameDataDefaultProps" :multiple="item.multiple" :select-all="true" @update:deptArray="(val) => updateDeptArray(val, item)" /> -->
          <!-- 文件上传 -->
          <template v-else-if="item.type === 'upload'">
            <el-form-item label="">
              <div class="group-item">
                <div class="exportFiles">
                  <upload :file-data="fileList" @changeFile="getFileList" /> <!--:file-type="fileFormat"-->
                </div>
              </div>
              <file-list v-for="file in fileList" :key="file.fileId" :file="file" :file-operate-btn="['eyes', 'closeBg']" @remove-file="removeFile" />
            </el-form-item>
          </template>
        </template>
      </el-form-item>
      <el-form-item>
        <template v-if="isShowSearchBtn">
          <el-button type="primary" size="middle" @click="submitForm('formRef')">查询</el-button>
          <el-button plain @click="resetForm('formRef')">重置</el-button>
        </template>
        <slot name="btnList" />
      </el-form-item>
    </el-form>

完整代码

<template>
  <div class="form" :style="setStyle">
    <el-form
      ref="formRef"
      :inline="inline"
      :model="model"
      :rules="isRules ? rules : {}"
      :label-position="labelPosition"
      :label-width="labelWidth"
      :style="{'flex-wrap': flexWrap ? 'nowrap' : 'wrap', 'justify-content' : justifyContent}"
    >
      <el-form-item
        v-for="(item,i) in formData"
        :key="'form'+i"
        :class="item.type + '-form'"
        :label="item.label"
        :prop="item.key"
        :rules="isRules ? item.rules : []"
        :error="item.success ? '' : item.message"
        :style="{width: item.width ? item.width : formItemWidth, ...item.style }"
      >
        <!-- 插槽 -->
        <template v-if="item.slotKey">
          <slot :name="item.slotKey" :row="item" />
        </template>
        <template v-else>
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'input'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            :placeholder="item.placeholder || '请输入'"
            @blur="handleBlur(item)"
          />
          <!-- 文本框 -->
          <el-input
            v-else-if="item.type === 'textarea'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            type="textarea"
            :rows="3"
            :placeholder="item.placeholder || '请输入'"
            @blur="handleBlur(item)"
          />
          <!-- 下拉框 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="model[item.key]"
            :disabled="!item.isEdit"
            :multiple="item.multiple"
            :placeholder="item.placeholder || '请选择'"
            @change="(val) => updateDeptArray(val, item)"
          >
            <el-option v-for="(option, j) in item.options" :key="'option'+j" :label="option.label" :value="option.value" />
          </el-select>
          <!-- 输入框(可以过滤) -->
          <el-autocomplete
            v-else-if="item.type === 'autocomplete'"
            v-model="model[item.key]"
            :fetch-suggestions="(a,b) => querySearch(a,b,item.options)"
            :placeholder="item.placeholder || '请输入'"
            @select="(val) => handleSelect(val, item)"
          />
          <!-- 单选框 -->
          <el-radio-group v-else-if="item.type === 'radio'" v-model="model[item.key]">
            <el-radio v-for="(option, z) in item.options" :key="'option'+z" :label="option.value">
              {{ option.label }}
            </el-radio>
          </el-radio-group>
          <!-- 日期 -->
          <el-date-picker
            v-else-if="item.type === 'date'"
            :key="'datePicker' + i"
            v-model="model[item.key]"
            :picker-options="!item.noLimitCurrentDate && pickerOptions"
            type="date"
            :placeholder="item.placeholder || '请选择'"
            value-format="yyyy-MM-dd"
            format="yyyy-MM-dd"
          />
          <!-- 日期时间 -->
          <el-date-picker
            v-else-if="item.type === 'daterange'"
            :key="'daterangePicker' + i"
            v-model="model[item.key]"
            :picker-options="!item.noLimitCurrentDate && pickerOptions"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            format="yyyy-MM-dd"
          />
          <!-- 数字 -->
          <el-input-number
            v-else-if="item.type === 'inputNumber'"
            v-model="model[item.key]"
            :min="1"
          />
          <!-- 报送时间 -->
          <div v-else-if="item.type === 'deliveryTime'" class="module-timeInput" @click="showSubMission">
            <el-input v-model="model[item.key]" :disabled="!item.isEdit" :placeholder=" item.placeholder || '请选择报送时间'" readonly />
          </div>
          <!-- 单位或者人员组织构架 -->
          <auth-panel
            v-else-if="item.type === 'authPanel'"
            :auth-panel-params="item.params"
            :mixed-data="item.mixedData"
            :disabled="item.disabled"
            :type="item.authPanelType"
            :dept-array="item.deptArray"
            :has-same-data-default-props="item.hasSameDataDefaultProps"
            :multiple="item.multiple"
            :stage-single="item.stageSingle"
            :select-all="true"
            @update:deptArray="(val) => updateDeptArray(val, item)"
          />
          <!-- <auth-panel v-else-if="item.type === 'authPanel'" :disabled="!item.isEdit" :type="item.authPanelType" :dept-array="item.deptArray" :has-same-data-default-props="item.hasSameDataDefaultProps" :multiple="item.multiple" :select-all="true" @update:deptArray="(val) => updateDeptArray(val, item)" /> -->
          <!-- 文件上传 -->
          <template v-else-if="item.type === 'upload'">
            <el-form-item label="">
              <div class="group-item">
                <div class="exportFiles">
                  <upload :file-data="fileList" @changeFile="getFileList" /> <!--:file-type="fileFormat"-->
                </div>
              </div>
              <file-list v-for="file in fileList" :key="file.fileId" :file="file" :file-operate-btn="['eyes', 'closeBg']" @remove-file="removeFile" />
            </el-form-item>
          </template>
        </template>
      </el-form-item>
      <el-form-item>
        <template v-if="isShowSearchBtn">
          <el-button type="primary" size="middle" @click="submitForm('formRef')">查询</el-button>
          <el-button plain @click="resetForm('formRef')">重置</el-button>
        </template>
        <slot name="btnList" />
      </el-form-item>
    </el-form>
    <!--报送周期组件-->
    <submission-dialog ref="submissionDialog" :sub-mission-data="subMissionData" @confirm="confirmMission" />
  </div>
</template>
<script>
import authPanel from '@/components/authPanel/index.vue'
import submissionDialog from '@/components/Dialog/submissionDialog.vue'
import upload from '@/components/UploadCom/index.vue'
import fileList from '@/components/fileList/index.vue'
export default {
  name: 'InitForm',
  components: { authPanel, upload, fileList, submissionDialog },
  props: {
    isShowSearchBtn: { // 是否显示查询按钮
      type: Boolean,
      default: true
    },
    labelPosition: { // 表单文本标题的位置
      type: String,
      default: 'right'
    },
    labelWidth: { // 表单文本标题的宽度
      type: String,
      default: ''
    },
    formItemWidth: {
      type: String,
      default: '100%'
    },
    setStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    updateModel: {
      type: Object,
      default: () => {
        return {}
      }
    },
    isRules: { // 是否要校验
      type: Boolean,
      default: true
    },
    rules: { // 校验规则
      type: Object,
      default: () => {
        return {}
      }
    },
    formData: { // 表单数据
      type: Array,
      default: () => {
        return []
      }
    },
    inline: { // 是否是行内
      type: Boolean,
      default: true
    },
    flexWrap: {
      type: Boolean,
      default: false
    }, // 控制表单是否换行
    justifyContent: { // 布局
      type: String,
      default: 'space-between'
    }, // 表单布局风格
    noCheck: {
      type: Boolean,
      default: true
    },
    pickerOptions: { // 时间日期表单的时间限制
      type: Object,
      default: () => {
        return {
          disabledDate(time) {
            return time.getTime() < Date.now() - 8.64e7
          }
        }
      }
    }
  },
  data() {
    return {
      model: {},
      fileList: [],
      linkageDataKey: {},
      subMissionData: { // 报送时间回显的参数格式
        supervisionCycleIds: '',
        cycleType: '',
        firstSubmitTime: '',
        supervisionCycle: ''
      },
      defaultProps: { // 初始化表单key值
        value: 'value', // 表单显示的值
        authPanel: 'list' // 获取选择单位/选择人员所选择的对象值
      }
    }
  },
  watch: {
    updateModel: {
      handler(newV) {
        if (newV) {
          this.model[Object.keys(newV)[0]] = newV[Object.keys(newV)[0]]
        }
      },
      deep: true
    }
  },
  created() {
    this.init()
  },
  methods: {
    init() {
      this.formData.forEach(item => {
        !item.defaultProps && (item.defaultProps = this.defaultProps)
        if (item.type === 'deliveryTime') {
          this.subMissionData = item.deliveryTime ? item.deliveryTime : this.subMissionData
        }
        if (item.linkage) {
          this.linkageDataKey[item.linkage] = this.formData.find(data => {
            return data.key === item.linkage
          })
          const linkageType = Array.isArray(this.linkageDataKey[item.linkage].value)
          if ((linkageType && this.linkageDataKey[item.linkage].value.length > 0) || (!linkageType && this.linkageDataKey[item.linkage].value)) {
            if (item.fn(this.linkageDataKey[item.linkage].value).then) {
              item.fn(this.linkageDataKey[item.linkage].value).then(() => {
                this.$set(this.model, item.key, Array.isArray(item.value) ? item.value.map(String) : item.value)
              })
            } else {
              this.$set(this.model, item.key, Array.isArray(item.value) ? item.value.map(String) : item.value)
            }
          }
        } else {
          this.$set(this.model, item.key, item.value)
          // if (item.type === 'select' && item.multiple) {
          //   if (item.value && item.value.length > 0) {
          //     this.$set(this.model, item.key, item.value)
          //   } else {
          //     this.$set(this.model, item.key, [])
          //     if (!item.message) {
          //       this.$nextTick(() => {
          //         this.$refs['formRef'].clearValidate([item.key])
          //       })
          //     }
          //   }
          // } else {
          //   this.$set(this.model, item.key, item.value)
          // }
          // this.model[item.key] = item.value
        }
        if (item.type === 'upload') {
          this.fileList = item.value ? JSON.parse(item.value) : []
        }
      })
    },
    // 清除校验
    // clearRules(value) {
    //   this.$nextTick(() => {
    //     if (value) {
    //       this.$refs['formRef'].clearValidate([value])
    //     } else {
    //       this.$refs['formRef'].resetFields()
    //     }
    //   })
    // },
    querySearch(queryString, cb, options) {
      const option = options || []
      cb(option.filter(item => {
        return item.value.indexOf(queryString) > -1
      }))
    },
    handleSelect(val, data) {
      data.formKey.forEach(item => {
        if (item.indexOf('Id') > -1) {
          this.$set(this.model, item, val.id)
        } else {
          this.$set(this.model, item, val.value)
        }
      })
    },
    submitForm(formEl) {
      if (!formEl) return
      this.$emit('submit', this.model)
    },
    resetForm(formEl) {
      if (!formEl) return
      this.$refs[formEl].resetFields()
      this.$emit('reset', this.model)
    },
    getTreeSelectData(data) {
      this.$set(this.model, 'treeSelectData', data)
    },
    updateDeptArray(data, formItem) {
      let interrupt = false // 是否中断赋值
      formItem.type === 'authPanel' && this.$set(this.model, formItem.key, data.map(item => { return item.name }).join(','))
      this.$refs.formRef.clearValidate(formItem.key)
      this.formData.forEach(item => {
        if (item.linkage === formItem.key) {
          interrupt = item.fn(data, this.formData).interrupt
        }
        if (item.type === 'authPanel' && item.key === formItem.key && !interrupt) {
          item.deptArray = data
        }
      })
      if (!interrupt) {
        this.$emit('update:formData', this.formData)
      }
    },
    async getFormData(callback) {
      if (!this.$refs.formRef) return
      const initFormData = this.initSaveFormData(JSON.parse(JSON.stringify(this.formData)))
      let data = {}
      await this.$refs.formRef.validate((valid) => {
        const errmsg = '验证不通过'
        if (valid) {
          data = callback ? callback({ data: initFormData, valid: true }) : { data: initFormData, valid: true }
        } else {
          data = { valid: false }
        }
      })
      return data
      // if (noCheck) {
      //   return this.checkFormData(callback, initFormData)
      // }
    },
    getFormDataNoCheck(callback) { // 获取数据不需要校验
      if (!this.$refs.formRef) return
      const initFormData = this.initSaveFormData(JSON.parse(JSON.stringify(this.formData)))
      this.$refs.formRef.clearValidate()
      return (callback ? callback({ data: initFormData, valid: true }) : { data: initFormData, valid: true })
    },
    initSaveFormData(initFormData) {
      Object.keys(this.model).forEach(modelKey => {
        initFormData.forEach(formData => {
          if (formData.key === modelKey) {
            if (formData.key === 'supervisionCycle') {
              formData.deliveryTime = this.subMissionData
            }
            formData[formData.defaultProps.value] = this.model[modelKey]
          }
        })
      })
      return initFormData
    },
    // 显示报送周期
    showSubMission() {
      this.$refs.submissionDialog.showVisilie()
    },
    // 回显周期数据
    confirmMission(callData) {
      this.$set(this.model, 'supervisionCycle', callData['supervisionCycle'])
      Object.keys(this.subMissionData).forEach(item => {
        this.$set(this.subMissionData, item, callData[item])
      })
    },
    getFileList(fileList) {
      this.fileList = fileList.map((item, index) => {
        return {
          source: item.source || '',
          fileId: item.fileId,
          fileName: item.name,
          name: item.name,
          fileSize: item.fileSize,
          sort: index + 1,
          suffixName: item.iconType
        }
      })
      this.$set(this.model, 'fileJson', JSON.stringify(this.fileList))
    },
    removeFile(data) {
      this.fileList = this.fileList.filter(item => {
        return item.fileId !== data.fileId
      })
      this.$set(this.model, 'fileJson', JSON.stringify(this.fileList))
    },
    // 输入框失去焦点
    handleBlur(data) {
      if (data.isMate) {
        console.log('1440', data, this.model[data.key], this.formData)
        this.$emit('getMatched', data, this.model, this.formData)
      }
    }
  }
}
</script>
  <style lang="scss" scoped>
  // .el-form{
  //   padding: 27px 16px 9px;
  // }
  .form{
    ::v-deep .el-autocomplete{
      width: 100%;
    }
    ::v-deep .el-form-item{
      &:last-of-type{
        margin-right: 0;
      }
    }
    ::v-deep .el-form--inline{
      display: flex;
      justify-content: space-between;
    }
    ::v-deep .el-form--inline{
      .el-form-item{
        display: flex;
        margin-right: 0;
      }
    }
    ::v-deep .el-tag{
      line-height: initial;
    }
    ::v-deep .el-form-item__content{
      width: 100%;
      flex: 1
    }
    ::v-deep .el-date-editor.el-input, ::v-deep .el-date-editor.el-input__inner{
      width: inherit;
    }
  }
  .el-select{
    width: 100%;
  }

  .hint{
    margin-left: 6px;
  }
  // .dialogObj-text-box {
  //   margin-left: 12px;
  //   min-width: 60px;
  //   &:hover {
  //     color: #1a8af9;
  //     cursor: pointer;
  //   }
  // }
  </style>


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值