vue项目根据配置加载组件生成表单

1、需求分析

当前需求是完成导出平台,页面结构比较简单,上半部分是搜索的筛选项,下半部分是查询的内容列表和分页。如图所示。

页面基本类似,主要包括 buttonGroup,select,date,input 和 button 等,

2、接口文档分析

接口地址按模块划分,相同筛选条件的入参相同(如图),返回字段后台已经罗列的出参字段对应的含义说明。

3、考虑实现方案

(1)每个页面单独实现工作量较大 —— 导出页面共计20多个。

(2)各个页面组件基本 —— 表单组件和表格

(3)相同功能相似 —— 导出 查询等

综上 考虑把各个小模块拆解成小的组件,每个页面根据一个JSON对组件进行配置,复用各个组件,实现各个页面的显示和功能。

4、开始实现

(1)JOSN配置项设计(如下JSON)

export const TASK_INTEGRAL = {
  url: '/export/task', // 导出地址
  exportType: 'TASK_INTEGRAL', // 导出类型
  title: '任务积分明细', // 页面标题
  explain: '<p>这是这个导出页面的说明</p>', // 语流页面说明 富文本
  views: [
    {
      displayText: '平台:', // 当前表单名称
      viewType: 'buttonGroup', // 表单类型
      groupType: 'single', // 按钮组类型 单选 single / 多选 multiple
      fieldName: 'platform', // 关联的字段
      value: ['4'], // 默认值
      values: [ //备选项
        {
          key: '4.0数据',
          val: '4'
        },
        {
          key: '3.0数据',
          val: '3'
        }
      ],
      valuesType: 'platform' // 组件业务类型
    },
    {
      displayText: '任务名称:', // 当前表单名称
      viewType: 'select', // 表单类型
      fieldName: 'taskData', // 关联的字段
      placeholder: '请输入任务名称', // placeholder
      value: '', // 默认值
      values: [], // 备选项的值 eg:{key:'这个选项1',val:1}
      multiple: false, // 下拉框是否可以多选
      required: 1, // 是否为必填项 0:不必选,可以不选择,为空代表查询所有数据 1:必须选一个 2:必须同时选两个 5:必选、多选,但最多选择不超过5个
      warning: '请选择任务!', // 必选未选择时的提示
      valuesType: 'task' // 备选项类型
    },
    {
      displayText: '批次名称:', // 当前表单名称
      viewType: 'select', // 表单类型
      fieldName: 'batchData', // 关联的字段
      placeholder: '请输入批次名称', // placeholder
      value: '', // 默认值
      values: [], // 备选项的值 eg:{key:'这个选项1',val:1}
      multiple: true, // 下拉框是否可以多选
      required: 0, // 是否为必填项 0:不必选,可以不选择,为空代表查询所有数据 1:必须选一个 2:必须同时选两个 5:必选、多选,但最多选择不超过5个
      valuesType: 'batch' // 备选项类型
    },
    {
      displayText: '任务提交时间:', // 当前表单名称
      viewType: 'date', // 表单类型
      dateType: 'datetimerange', // 日期类型 
      fieldName: 'dateRang', // 关联的字段
      placeholder: '请选择任务提交时间', // placeholder
      format: 'yyyy-MM-dd HH:mm:ss',
      required: 0, // 是否为必填项 0:不必选,可以不选择,为空代表查询所有数据 1:必须选一个 2:必须同时选两个 5:必选、多选,但最多选择不超过5个
      width: '280px' // 默认值
    },
    {
      displayText: '查询', // 当前表单名称
      viewType: 'button', // 表单类型
      btnType: 'primary', // 按钮类型
      handleType: 'queryData' // 操作事件 query 查询  export 导出  clear 清空
    },
    {
      displayText: '导出', // 当前表单名称
      viewType: 'button', // 表单类型
      btnType: 'primary', // 按钮类型
      handleType: 'exportData' // 操作事件
    },
    {
      displayText: '清空搜索条件', // 当前表单名称
      viewType: 'button', // 表单类型
      btnType: 'text', // 按钮类型
      handleType: 'clearData' // 操作事件
    }
  ],
  // 表格配置项
  tableConfig: [
    {
      title: 'realName',
      minWidth: 100,
      slot: ''
    }, {
      title: 'account',
      minWidth: 200,
      slot: ''
    }, {
      title: 'taskName',
      minWidth: 200,
      slot: ''
    }, {
      title: 'batchName',
      minWidth: 200,
      slot: ''
    }, {
      title: 'guildName',
      minWidth: 100,
      slot: ''
    }, {
      title: 'integral',
      minWidth: 100,
      slot: ''
    }, {
      title: 'manager',
      minWidth: 100,
      slot: ''
    }
  ]
}

(2)表单组件设计(例如select)

// 模板部分 select主要配置,默认值val,是否可以多选multiple。option通过循环加载被选项
<template>
  <div class="exportItem">
    <FormItem :label="config.displayText">
      <i-select
        v-model="val"
        filterable
        :multiple="config.multiple"
        :remote-method="remoteMethod"
        :loading="isLoading"
        loading-text="搜索中请等待..."
      >
        <i-option
          :key="index"
          v-for="(item, index) in config.values"
          :value="item.val"
        >{{ item.key }}</i-option
        >
      </i-select>
    </FormItem>
  </div>
</template>

遇到的问题:

 ① values字段不是固定的。——设计配置select的option是在values字段里传到组件内的。做的时候发现option的值是通过接口获取的,所以增加了一个字段valuesType。根据valuesType的值来调不同的接口。

 ② 组件之间的联动。—— 崽组件监听子组件的值,发生修改时及时向父组件同步,父组件根据指定组件发生改变再去调用另一个子组件做出响应。

// 子组件的监听方法  
// 子组件的值只要发生变化 就调用父组件的setData 方法同步数据
watch: {
    val() {
      this.$emit('setData', '', this.val, this.config.fieldName)
    }
  },

// 父组件的setData方法
// 设置值 把值都放在 params下的fieldName 里 
// setCallBack 里根据子组件的key处理和调用其他组件
    setData(obj, value, ...keys) {
      if (!obj) {
        obj = this.params;
      }
      keys.reduce((acc, cur, i) => {
        // acc 上一次return的结果 cur这一次当前遍历的值 i当前遍历的索引
        // eslint-disable-next-line no-return-assign
        return (acc[cur] = i === keys.length - 1 ? value : acc[cur] || {})
        // 根据递归创建空对象,直到是最后一个属性并赋值
      }, obj)
      // 最后这个obj是需要递归的初始值,即第一次递归的acc和cur等于obj

      // 设置值的回调  
      this.setCallBack(value && value[0], keys)
    },
    setCallBack(value, keys) {
      let val = parseInt(value)
      // 修改平台 重新加载任务列表
      if (keys.indexOf('platform') > -1) {
        if (val === 3) {
          this.$refs['selecttask'] && this.$refs['selecttask'][0] && this.$refs['selecttask'][0].getTaskList3()
          this.$refs['selectmedal'] && this.$refs['selectmedal'][0] && this.$refs['selectmedal'][0].getMedalList3()
          this.$refs['selectguild'] && this.$refs['selectguild'][0] && this.$refs['selectguild'][0].getGuildList3()
        } else if (val === 4) {
          this.$refs['selecttask'] && this.$refs['selecttask'][0] && this.$refs['selecttask'][0].getTaskList4()
          this.$refs['selectmedal'] && this.$refs['selectmedal'][0] && this.$refs['selectmedal'][0].getMedalList4()
          this.$refs['selectguild'] && this.$refs['selectguild'][0] && this.$refs['selectguild'][0].getGuildList4()
        }
        this.$refs['buttonGrouplanguageType'] && this.$refs['buttonGrouplanguageType'][0].computedIsShowButtonGroup(val)
        this.clearData({exclude: ['buttonGroupplatform']})
      }
      this.$refs['selectteam'] && this.$refs['selectteam'][0] && this.$refs['selectteam'][0].getGuildList3()
      let platform = this.params.platform
      // 修改任务 重新加载批次
      if (keys.indexOf('taskData') > -1 && platform && this.$refs['selectbatch'] && this.$refs['selectbatch'][0]) {
        this.clearData({include: ['selectbatch']})
        if (platform.indexOf('3') > -1) {
          this.$refs['selectbatch'][0].getBatchList3(this.params)
        } else if (platform.indexOf('4') > -1) {
          this.$refs['selectbatch'][0].getBatchList4(this.params)
        }
      }

      if (keys.indexOf('batchData') > -1) {
        this.$refs['stepsstep'] && this.$refs['stepsstep'][0] && this.$refs['stepsstep'][0].getStep(this.params)
      }
    },

 ③ option的值太多。 本来打算把所有option的值都加载出来然后本地进行模糊搜索,发现任务选择有3000 左右的值,全部加载接口查询要10s+,修改为搜索时远程查询。(远程查询有延时体检不如本地查询 )

④表格内有特殊操作。如图

解决方法

        // 有特殊操作的这一项 单独增加判断 添加slot  操作在slot里完成 
        if (this.dic[index] === '已获得勋章数') {
            this.columns.push({
              title: this.dic[index],
              key: index,
              width: 200,
              slot: 'detail'
            })
          } 

(3)表格显示设计(未实现)

// 表格配置项
  tableConfig: [
    {
      title: 'realName',
      minWidth: 100,
      slot: ''
    }, {
      title: 'account',
      minWidth: 200,
      slot: ''
    }, {
      title: 'taskName',
      minWidth: 200,
      slot: ''
    }, {
      title: 'batchName',
      minWidth: 200,
      slot: ''
    }, {
      title: 'guildName',
      minWidth: 100,
      slot: ''
    }, {
      title: 'integral',
      minWidth: 100,
      slot: ''
    }, {
      title: 'manager',
      minWidth: 100,
      slot: ''
    }
  ]

-- 当时计划是表格头部配置在JOSN内,配置项包括,title,宽度和slot(考虑有格式化和查询按钮等特殊需求等)这个配置对以后扩展更灵活。

-- 未实现原因 

1.相同字段对应的出参不相同,如 用户名 有的接口返回userName 有的接口返回的是 releaName。根据原型和文档无法准确地配置JSON。

2.部分表格返回结果根据搜索条件有所差异不能统一。

 (4)当前表格的实现方式

接口出参数据接口(如下)

{
	"count": 156,
	"total": 156,
	"pageSize": 10,
	"list": [{
		"cellStyleMap": {},
		"realName": "胡伟",
		"account": "weihu6@iflytek.com",
		"taskName": "字幕SDK",
		"batchName": "PWpz20060116364A17D4FF00000-1",
		"guildName": null,
		"integral": 12.800000190734863,
		"manager": null,
		"userId": "BC20CA416611412DB769F116FC20A634",
		"taskId": "140D559FBDD1458A886B5D4B8DDC443C",
		"batchId": "DDC04AE6FF534B6486AC0915FB4B02A1"
	}]
}

得到数据后遍历一遍list[0]的值放到columns里去(问题:返回的字段不需要全部展示),过滤规则是 不在响应词典里的都过滤掉(问题:接口返回对象里的字段是按照字母排序的,导致显示的表格和原型不一致),后台增加sortIndex字段 (如下)

"sortIndex": ["realName", "account", "taskName", "batchName", "guildName", "integral", "manager", "userId", "taskId", "batchId", "markTeamIdList"], 

前端取columns值的时候按照这个字段顺序去取。

(5)分页实现

通用逻辑

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值