|
- import get from 'lodash/get'
- import moment from 'moment'
-
- /**
- * 表单数据处理相关方法
- * (配合 <l-customform> 使用,注意本工具类不包含拉取表单数据的代码)
- *
- * 提供以下工具方法:
- *
- * 【新建表单时使用】:
- * async getDefaultData(schemeItem, { processId })
- * 获取单个表单项的默认数据
- *
- * 【打开一个表单时使用】:
- * async getSourceData(schemeItem)
- * 获取表单中的选单数据 / 获取单条表单项的选单数据
- *
- * async convertToFormValue(schemeItem, val)
- * 将从 API 拉取的表单数据格式化规范化
- *
- * 【提交表单时使用】:
- * async convertToPostData(schemeItem, val, formValue, scheme)
- * 将本地表单数据格式化为提交时的格式
- */
-
- export default {
- methods: {
- /**
- * 获取一个 scheme 表单项的源数据 (加载表单时使用)
- * 参数: 单个 schemeItem
- *
- * radio、select、checkbox、layer 这四种表单项,需要加载额外的选单数据
- * 选单数据有两种获取方式:
- * 1、来自数据字典:
- * 数据字典在 this.GET_GLOBAL('dataDictionary')
- * 表单使用的字段在 schemeItem.itemCode
- * 选单数据中的 text 字段作为显示, value 字段作为值
- *
- * 2、来自数据源:
- * 将 schemeItem.dataSourceId 按符号「,」逗号分割为数组,分割为: [code, displayField, valueField]
- * 数据源需要请求 API 来获取,请求需要带上数据源的编号 code
- * displayField、valueField 分别为展示字段和值绑定字段
- *
- * 选单数据有两种格式:
- * 1、对于 radio、select、checkbox 来说:
- * 只需要一个数组,数组形如: [{ text: '选项文字', value: '选项值' }, ...]
- * 将获取的数据绑定到组件的 range 属性上即可
- * 全局数据中默认是对象形式,使用 Object.values() 转化即可
- *
- * 2、对于 layer 来说:
- * 返回一个对象,形如 { source, layerData, selfField }
- * source: 为弹层中列出的数据,是一个数组
- * layerData: 需要在弹层窗口中展示的字段及标题文字,形如: [{ name:'要展示的字段名', label:'标题文字' }]
- * selfField: 该表单值绑定哪个字段,默认为绑定到自身的字段
- */
- async getSourceData(schemeItem) {
- if (['radio', 'select', 'checkbox'].includes(schemeItem.type)) {
- // radio select checkbox 三种情况
- if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) {
- // dataSource 为 0,使用 clientData
- return Object
- .values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode])
- .map(t => ({ value: t.value, text: t.text }))
-
- } else {
- // dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段
- const [code, displayField = schemeItem.showField, valueField = schemeItem.saveField] = schemeItem.dataSourceId
- .split(',')
- const sourceData = await this.FETCH_DATASOURCE(code)
- if (!sourceData) { return [] }
-
- return sourceData.data.map(t => ({ text: t[displayField], value: t[valueField] }))
- }
-
- } else if (['layer'].includes(schemeItem.type)) {
- // layer 需要更多属性
- if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) {
- // dataSource 为 0,使用 clientData
- // clientData 对象转数组后,隐含 key:item.text 和 value:item.value 的关系
- const [keyItem, valueItem] = schemeItem.layerData
- const source = Object
- .values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode])
- .map(t => ({ value: t.value, text: t.text }))
-
- return {
- source,
- layerData: [
- { name: 'text', label: keyItem.label || '', value: keyItem.value || '' },
- { name: 'value', label: valueItem.label || '', value: valueItem.value || '' }
- ]
- }
- } else {
- // dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段
- const [code] = schemeItem.dataSourceId.split(',')
- const sourceData = await this.FETCH_DATASOURCE(code)
- if (!sourceData) { return [] }
-
- const source = sourceData.data
-
- return { source, layerData: schemeItem.layerData.filter(t => (!t.hide) && (t.value || t.label)) }
- }
- }
-
- return []
- },
-
- /**
- * 获取一个 scheme 表单项的默认值 (用户新建表单时使用,或是编辑草稿)
- * 参数: 单个 schemeItem , { processId }
- *
- * 每种类别的表单项分别获取的默认值:
- *
- * currentInfo: 根据类别取当前用户/部门/公司/时间日期
- * datetime: 根据 dfValue 字段表示昨天/今天/明天,格式化为字符串
- * radio、select: 有 dfValue 则使用,否则取第一条
- * checkbox: 有 dfValue 则使用,否则为空数组
- * encode: 根据 rulecode 请求表单编码
- * upload: 空数组
- * guid: 赋值第二个参数中的 processId,但是如果在子表格中,赋空字符串
- * girdtable: 递归所有表格项 scheme 依次为它们生成默认值
- * datetimerange: 字符串 0
- */
- async getDefaultData(item, prop) {
- const { processId } = prop
- switch (item.type) {
- case 'currentInfo':
- switch (item.dataType) {
- case 'user':
- return this.GET_GLOBAL('loginUser').userId
- case 'department':
- return this.GET_GLOBAL('loginUser').departmentId
- case 'company':
- return this.GET_GLOBAL('loginUser').companyId
- case 'time':
- return moment().format('YYYY-MM-DD HH:mm:ss')
- default:
- return ''
- }
-
- case 'datetime':
- const datetimeFormat = item.table ?
- (Number(item.dateformat) === 0 ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss') :
- (item.datetime === 'datetime' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')
- const today = moment()
- const dfDatetime = [
- today.subtract(1, 'day'),
- today,
- today.add(1, 'day')
- ][Number(item.dfvalue)] || today
-
- return dfDatetime.format(datetimeFormat) || ''
-
- case 'radio':
- case 'select':
- const radioItem = item.__sourceData__.find(t => t.value === item.dfvalue) || item.__sourceData__[0]
- return item.type === 'radio' ? radioItem.value : ''
-
- case 'checkbox':
- if (!item.dfvalue) {
- return []
- }
- return item.dfvalue.split(',').filter(t => item.__sourceData__.find(s => s.value === t))
-
- case 'encode':
- const result = await this.FETCH_ENCODE(item.rulecode)
- return result
-
- case 'upload':
- return []
-
- case 'guid':
- return item.table ? processId : ''
-
- case 'girdtable':
- const tableItemObj = {}
- for (const fieldItem of item.fieldsData) {
- tableItemObj[fieldItem.field] = await this.getDefaultData(fieldItem, prop)
- }
- return this.COPY(tableItemObj)
-
- case 'datetimerange':
- return '0'
-
- default:
- return item.dfvalue || ''
- }
- },
-
- /**
- * 将单条 formData 值转化为 formValue 值 (拉取表单数据时使用)
- * 参数: 单个 schemeItem , 数据值
- *
- * 具体执行逻辑:
- * radio、select: 剔除无效值
- * checkbox: 分割成数组并剔除无效值
- * upload: 分割成数组,拉取其中所有文件的信息
- * datetime: 按照时间日期格式进行格式化字符串
- * 其他类型: 保留原值
- */
- async convertToFormValue(item, val) {
- switch (item.type) {
- case 'upload':
- if (!val) { return [] }
- const uidList = val.split(',')
- const fileList = []
-
- for (const uid of uidList || []) {
- const fileInfo = await this.FETCH_FILEINFO(uid)
- if (!fileInfo) { continue }
-
- const fileType = fileInfo.F_FileType
- const fileSize = fileInfo.F_FileSize
- const fileName = fileInfo.F_FileName
-
- const path = this.API + 'learun/adms/annexes/wxdown?' + this.URL_QUERY(uid, true)
-
- fileList.push({ path, type: fileType, uid, size: fileSize, name:fileName })
- }
- return fileList
-
- case 'select':
- case 'radio':
- if (!val || !item.__sourceData__.map(t => t.value).includes(val)) {
- return ''
- }
- return val
-
- case 'checkbox':
- const validValue = item.__sourceData__.map(t => t.value)
- const checkboxVal = val.split(',') || []
- return checkboxVal.filter(t => validValue.includes(t))
-
- case 'datetime':
- if (!val) {
- return ''
- }
- return moment(val).format(
- Number(item.dateformat) === 0 || item.datetime === 'date' ?
- 'YYYY-MM-DD' :
- 'YYYY-MM-DD HH:mm:ss'
- )
-
- default:
- return val || ''
- }
- },
-
- /**
- * 将一个 formValue 值转化为 post 提交值(提交表单数据时使用)
- * 参数: 单个 schemeItem , 表单项值 , 所有 formValue , scheme
- *
- * 具体执行逻辑:
- * checkbox: 将数组使用符号「,」逗号拼接成字符串
- * datetimerange: 获取开始日期、结束日期,计算差值天数并保留整数
- * datetime: 格式化为完整时间日期字符串
- * upload: 依次上传文件,将返回的文件 ID 使用符号「,」逗号拼接成字符串
- * 其他类型: 保留原值
- */
- async convertToPostData(item, val, formValue, scheme) {
- switch (item.type) {
- case 'checkbox':
- return val ? val.join(',') : ''
-
- case 'datetimerange':
- const startTime = get(formValue, scheme.find(t => t.id === item.startTime).__valuePath__, null)
- const endTime = get(formValue, scheme.find(t => t.id === item.endTime).__valuePath__, null)
- if (!startTime || !endTime || moment(endTime).isBefore(startTime)) {
- return ''
- } else {
- return moment.duration(moment(endTime).diff(moment(startTime))).asDays().toFixed(0)
- }
-
- case 'datetime':
- return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : ''
-
- case 'upload':
- const valArray = val.map(item=>{
- return {
- uid:item.uid,
- path:item.path===undefined?item:item.path
- }
- })
- const uploadUid = []
- for (const { path, uid } of valArray) {
- if (uid) {
- uploadUid.push(uid)
- continue
- }
-
- const fileId = await this.HTTP_UPLOAD(path)
- if (fileId) {
- uploadUid.push(fileId)
- }
- }
-
- return uploadUid.join(',')
-
- default:
- return val || ''
- }
- }
- }
- }
|