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)分页实现
通用逻辑