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

news2024/11/28 6:38:34

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

主要是使用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>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1562624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于单片机智能数字温度采集报警器系统设计

**单片机设计介绍&#xff0c;基于单片机智能数字温度采集报警器系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机智能数字温度采集报警器系统设计的核心目标是通过单片机实现温度的实时采集、显示以及超温报警…

Nexpose v6.6.244 for Linux Windows - 漏洞扫描

Nexpose v6.6.244 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, Release Mar 27, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.o…

Windows启动动画的小秘密

>网管小贾 / sysadm.cc 员工求领导办事&#xff0c;司空见惯&#xff0c;没啥稀奇。 领导求员工办事&#xff0c;想都别想&#xff0c;怎么可能。 然而这世上之事万里总有个一&#xff0c;这不&#xff0c;就在上个礼拜&#xff0c;开天辟地头一遭&#xff0c;让我给碰上…

Redis开源协议调整,我们怎么办?

2024年3月20日, Redis官方宣布&#xff0c;从 Redis 7.4版本开始&#xff0c;Redis将获得源可用许可证 ( RSALv2 ) 和服务器端公共许可证 ( SSPLv1 ) 的双重许可&#xff0c;时间点恰逢刚刚完成最新一轮融资&#xff0c;宣布的时机耐人寻味。 Redis协议调整&#xff0c;对云计算…

需要本地后端的真机调试-微信

打开和修改IP改为电脑与手机同一局域网的 不知道这个要不要

交通标志识别项目 | 基于Tensorflow+SSD实现道路交通标志识别

项目应用场景 面向智能驾驶或自动驾驶场景道路道路交通标志的识别&#xff0c;在交通标志识别的基础上为下一步的智能决策提供前提 项目效果&#xff1a; 项目细节 > 具体参见项目 README.md (1) 安装依赖 Python3.5、TensorFlow v0.12.0、Pickle、OpenCV-Python、Matplotl…

宁波ISO45001:2018职业健康与安全管理体系认证

&#x1f913;ISO45001&#xff1a;2018职业健康与安全管理体系认证 ISO45001&#xff08;OHSAS18001&#xff09;全称&#x1f349;是职业安全卫生&#x1f350;管理标准&#xff0c;是国际上&#x1f955;继ISO9000质量管理体系&#x1f334;标准和ISO14000环境管理&#x1f…

主站设备通过Modbus转Profinet网关与湿度传感器通讯配置

Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;可以实现不同协议设备通讯&#xff0c;有些现场需要实时监测环境参数&#xff0c;但大由于当时环境仪表设备不能达到直连效果&#xff0c;通过Modbus转Profinet网关&#xff0c;湿度传感器的数据可以被准确、可靠地传输…

【通信原理笔记】【三】模拟信号调制——3.3 包络调制(AM)

文章目录 前言一、AM的数学表示二、AM的相干解调三、AM的非相干解调四、AM调制的性能总结 前言 本文将介绍包络调制方法&#xff0c;该方法的思路是将 m ( t ) m(t) m(t)作为已调信号的复包络的模——即包络。 一、AM的数学表示 根据包络调制的思路&#xff0c;我们有如下数学…

注册接口和前置SQL及数据生成及封装

注册接口 演示注册接口的三步操作&#xff1a;【注册流程逻辑】 第一步&#xff1a;发送注册短信验证码接口请求 请求方法&#xff1a; put 请求地址&#xff1a;http://shop.lemonban.com:8107/user/sendRegisterSms 请求参数&#xff1a;{“mobile”:“13422337766”} 请求头…

NASA数据集——2016-2019 年北极地区天气研究和预报(WRF)随机时间倒拉格朗日传输(STILT)粒子轨迹文件

ABoVE: Level-4 WRF-STILT Particle Trajectories for Circumpolar Receptors, 2016-2019 简介 文件修订日期&#xff1a;2021-12-07 数据集版本: 1 摘要 本数据集提供了 2016-2019 年期间天气研究和预报&#xff08;WRF&#xff09;随机时间倒拉格朗日传输&#xff08;ST…

JavaEE初阶-线程3

文章目录 一、线程安全问题-内存可见性二、等待通知2.1 wait()方法2.2 notify()方法 一、线程安全问题-内存可见性 import java.util.Scanner;public class Demo27 {private static int count0;//下面这段代码会出现内存的可见性问题//将从内存中读取count值的操作称为load 判…

LINUX笔记温习

目录 DAY1 DAY2 day3&#xff1a; day4 day5 day6 day7 day8 day9 day10 day11 day12 day13 day14 day15 20day DAY1 1、多层级文件夹创建要带-p&#xff1b; 2、创建多文件&#xff0c;要先到该目录下才能创建(第一个目录必须存在才能有效建立)&#xff1b; D…

简单说清楚什么是SQL Injection?

最近看完了《The Pragmatic Programmer: 20th Anniversary Edition, 2nd Edition: Your Journey to Mastery》&#xff0c;在第7章&#xff1a;While You Are Coding的footnotes中&#xff0c;提到了一幅漫画&#xff1a; 这不仅用简单的方式说清楚了什么是SQL Injection&#…

Veritas NetBackup 10.4 (Unix, Linux, Windows) - 一流的企业备份解决方案

Veritas NetBackup 10.4 (Unix, Linux, Windows) - 一流的企业备份解决方案 The #1 enterprise backup and recovery solution. 请访问原文链接&#xff1a;https://sysin.org/blog/veritas-netbackup-10/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者…

【THM】Active Reconnaissance(主动侦察)-初级渗透测试

介绍 在网络安全模块的第一个房间里,我们主要进行被动侦察。在第二个房间中,我们重点关注主动侦察以及与之相关的基本工具。我们学习使用网络浏览器来收集有关我们目标的更多信息。此外,我们讨论使用简单的工具(例如ping、traceroute、telnet和 )nc来收集有关网络、系统和…

陀螺仪传感器,IMU和加速度计的产品和选型

爱普生陀螺仪传感器是一种角速度传感器&#xff0c;作为一种石英电子式陀螺仪芯片&#xff0c;具有温度特性好、功耗低、成本低、稳定性好等特点。目前EPSON主力单轴陀螺仪传感器型号为XV7001BB、XV7011BB、XV7021BB和XV7181BB。针对扫地机器人传感器模组等领域的需要&#xff…

【详细教程制作】用户列表

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

正则表达式引擎库汇合

1.总览表格 一些正则表达式库的对比 index库名编程语言说明代码示例编译指令1Posix正则C语言是C标准库中用于编译POSIX风格的正则表达式库 posix-re.cgcc posix-re.c 2PCRE库C语言提供类似Perl语言的一个正则表达式引擎库。 一般系统上对应/usr/lib64/libpcre.so这个库文件&am…

012——LED模块驱动开发(基于I.MX6uLL)

目录 一、 硬件原理图 二、 驱动程序 三、 应用程序 四、 Makefile 五、操作 一、 硬件原理图 又是非常经典的点灯环节 &#xff0c;每次学新语言第一步都是hello world&#xff0c;拿到新板子或者学习新的操作系统&#xff0c;第一步就是点灯。 LED 的驱动方式&#xff0…