|
- import get from 'lodash/get'
- import set from 'lodash/set'
- import customForm from '@/common/customform.js'
-
- /**
- * 工作流表单数据处理相关方法
- * (用于工作流表单页面,包含拉取、提交等函数,注意不可用于自定义应用和代码生成器页面)
- *
- * 用户新建表单的流程:
- * 1、拉取流程信息
- * 调用 fetchProcessInfo、 getCurrentNode
- * 2、根据流程信息里的表单相关定义来拉取表单 scheme
- * 调用 fetchSchemeData
- * (如果是使用移动端本地表单,则无需拉取表单,且略去后续所有步骤)
- * 3、加载选单数据 (例如 checkbox、select 这些表单项有选单数据)
- * 4、赋予默认值 (例如 currentInfo 类表单项,自动把当前用户的信息填入)
- * 5、生成表单
- * 调用 getCustomForm 即可完成步骤 3~4
- *
- * 用户打开已经填写的表单/草稿的流程:
- * 1、拉取流程信息
- * 调用 fetchProcessInfo、 getCurrentNode
- * 2、拉取表单 scheme;如果是使用移动端本地表单则无需此步骤
- * 调用 fetchSchemeData
- * 3、加载选单数据
- * 调用 fetchFormData
- * 4、拉取表单中已填入的值
- * 5、如果打开的是草稿,可能要把部分未填的项赋默认值
- * 6、生成表单
- * 调用 getCustomForm 即可完成步骤 4~5
- *
- * (以上只是简单介绍;实际使用中,如果打开子流程,需要拉取父/子两个流程信息)
- */
- export default {
- mixins: [customForm],
-
- methods: {
- /**
- * 从流程信息中生成 scheme、formValue
- * 参数: { schemeData (必填), processId, currentNode, formData (新建时为 null), code, useDefault }
- * 返回: { scheme, formValue, rel }
- *
- * 参数:
- * schemeData: 使用 fetchSchemeData 方法拉取到的原始 scheme 数据,未经过格式化处理
- * processId: 表单 GUID;如果是新建表单,可以用 this.GUID('-') 生成一个
- * currentNode: 使用 getCurrentNode 方法拉取到的当前节点信息,用于权限控制
- * formData: 填入表单的表单值,新建表单时此项为 null 即可
- * code: 表单编号 code,会被赋值到返回的 formValue.code;重新发起流程的场合赋 null
- * useDefault: 如果 formData 中某一项为空,是否对这一项填入默认值;通常在编辑草稿时启用
- *
- * 该方法返回的 scheme 项可能带有以下属性:
- * __valuePath__: 表单值在 formValue 中的路径,使用 lodash 的 get、set 方法即可读写
- * __sourceData__: 表单值的选单数据
- * __defaultItem__: 类型为 girdtable 的表单项带有此属性,表示添加一行表格时候表格项的默认值
- * __schemeIndex__: (暂时用不到)表单项位于 schemeData 根级内的第几个子项中
- * __dataIndex__: (暂时用不到)表单项位于 F_Scheme.data 中的第几个子项中
- */
- async getCustomForm(prop) {
- const { schemeData, formData, currentNode, code, processId, useDefault } = prop
-
- // 处理字段之间的级联、绑定关系
- // 需要绑定 change 事件的:
- // datetime: 修改后重新计算 datetimerange
- // organize: 修改后重设级联到该组件的其他组件的值,user 一级无需处理
- // 需要绑定某值的:
- // organize: 级联到某个组件,company 一级无需处理
- const schemeRef = {}
- const refList = []
-
- // 最终返回值:scheme、rel、formValue
- const scheme = []
- const rel = {}
- const formValue = { processId, formreq: [] }
- if (code) {
- formValue.code = code
- }
-
- // 遍历 schemeData 中所有的 scheme
- const schemeList = Array.isArray(schemeData) ? schemeData : Object.values(schemeData)
- for (let schemeIndex = 0; schemeIndex < schemeList.length; ++schemeIndex) {
- const schemeItem = schemeList[schemeIndex]
- schemeItem.F_Scheme = JSON.parse(schemeItem.F_Scheme)
- // 已有表单值的时候,舍弃掉不存在表单值中的 scheme
- if (formData && !formData[schemeItem.F_SchemeInfoId]) {
- continue
- }
-
- // 设置 formreq 的内容,非新建模式下需要设置 keyValue
- const { formId, field } = get(currentNode, `wfForms.${schemeIndex}`, {})
- const formreqObj = { schemeInfoId: formId, processIdName: field, formData: {} }
- if (formData) {
- if (Object.values(get(formData, `${schemeItem.F_SchemeInfoId}`, {})).some(t => t && t.length > 0)) {
- formreqObj.keyValue = processId
- }
- }
- formValue.formreq[schemeIndex] = formreqObj
-
- for (let dataIndex = 0; dataIndex < schemeItem.F_Scheme.data.length; ++dataIndex) {
- const { componts } = schemeItem.F_Scheme.data[dataIndex]
- for (const t of componts) {
- // 之后的 t 即表示每个 scheme 项
- t.__valuePath__ = `formreq.${schemeIndex}.formData.${t.id}`
- // 以下两个属性暂时用不到
- t.__schemeIndex__ = schemeIndex
- t.__dataIndex__ = dataIndex
-
- if (t.type === 'girdtable' && t.table) {
- // 数据项是表格的情况
- // 先设置源数据,不然无法获取默认值
- for (const fieldItem of t.fieldsData) {
- fieldItem.__sourceData__ = await this.getSourceData(fieldItem)
- }
- t.__defaultItem__ = await this.getDefaultData(t, prop)
- if (formData) {
- // 有表单值的情况,从表单值中获取数据
- const val = []
- for (const valueItem of get(formData, `${schemeItem.F_SchemeInfoId}.${t.table}`, [])) {
- const tableItemValue = {}
- for (const fieldItem of t.fieldsData.filter(t => t.field)) {
- const formDataValue = get(valueItem, fieldItem.field.toLowerCase())
- tableItemValue[fieldItem.field] = await this.convertToFormValue(fieldItem, formDataValue)
- }
-
- val.push(tableItemValue)
- }
-
- // useDefault 表示在从 formData 取不到值的时候使用默认值
- if ((!val || val.length <= 0) && useDefault) {
- set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)])
- } else {
- set(formValue, t.__valuePath__, val)
- }
-
- } else {
- // 无表单值的情况,默认值
- set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)])
- }
-
- } else if (t.field) {
- // 数据项不是表格的情况
- // 先设置源数据,不然无法获取默认值
- t.__sourceData__ = await this.getSourceData(t)
- if (formData) {
- // 有表单值的情况,从表单值中获取数据
- const path = `${schemeItem.F_SchemeInfoId}.${t.table}.${dataIndex}.${t.field.toLowerCase()}`
- const formDataValue = get(formData, path)
-
- // useDefault 表示在从 formData 取不到值的时候使用默认值
- if (!formDataValue && useDefault) {
- set(formValue, t.__valuePath__, await this.getDefaultData(t, prop))
- } else {
- set(formValue, t.__valuePath__, await this.convertToFormValue(t, formDataValue))
- }
-
- } else {
- // 无表单值的情况,默认值
- set(formValue, t.__valuePath__, await this.getDefaultData(t, prop))
- }
- }
-
- // 权限控制
- const authObj = get(currentNode, `wfForms.${schemeIndex}.authorize.${t.id}`, {})
- t.edit = authObj.isEdit
- if (Number(t.isHide) !== 1 && authObj.isLook !== 0) {
- // 加入 scheme
- scheme.push(t)
-
- // organize、datetime 可能作为其他 organize 或 datetimerange 的依赖项,引用它们
- if (['organize', 'datetime'].includes(t.type)) {
- schemeRef[t.id] = t
- }
-
- // datetimerange、带有 relation 级联字段的 organize,依赖其他项
- if ((t.type === 'datetimerange' && t.startTime && t.endTime) || (t.type === 'organize' && t.relation)) {
- refList.push(t)
- }
- }
- }
- }
- }
-
- // 依次处理表单关联
- refList.forEach(t => {
- if (t.type === 'organize') {
- // 处理组件结构级联
- // 给当前组件赋上级级联的值路径 __relationPath__
- const parent = schemeRef[t.relation]
- t.__relationPath__ = parent.__valuePath__
- // 给上级级联的组件注册自动重置当前组件的 change 事件
- const relItem = { type: 'organize', id: t.id, path: t.__valuePath__ }
- rel[parent.id] = rel[parent.id] ? rel[parent.id].concat(relItem) : [relItem]
-
- } else if (t.type === 'datetimerange') {
- // 处理日期区间
- const start = schemeRef[t.startTime]
- const end = schemeRef[t.endTime]
-
- const relItem = {
- type: 'datetimerange',
- path: t.__valuePath__,
- id: t.id,
- startPath: start.__valuePath__,
- endPath: end.__valuePath__,
- }
-
- rel[start.id] = rel[start.id] ? rel[start.id].concat(relItem) : [relItem]
- rel[end.id] = rel[end.id] ? rel[end.id].concat(relItem) : [relItem]
-
- }
- })
-
- return { scheme, formValue, rel }
- },
-
- /**
- * 获取最终需要 POST 的数据
- * 参数:formValue, scheme
- * 返回:用于提交的数据
- *
- * 遍历 formValue,将其中的表单值依次使用 convertToPostData 这个方法转化为提交值
- */
- async getPostData(originFormValue, scheme) {
- const formValue = this.COPY(originFormValue)
-
- // 依次按照 scheme 项目遍历
- for (const item of scheme) {
- if (item.field) {
- // 不是表格的情况
- const path = item.__valuePath__
- const val = get(formValue, path)
- const result = await this.convertToPostData(item, val, originFormValue, scheme)
- set(formValue, path, result)
-
- } else if (item.table && item.fieldsData) {
- // 是表格的情况
- const tableValue = get(formValue, item.__valuePath__, [])
- for (let valueIndex = 0; valueIndex < tableValue.length; ++valueIndex) {
- for (const schemeItem of item.fieldsData) {
- const path = `${item.__valuePath__}.${valueIndex}.${schemeItem.field}`
- const val = get(formValue, path)
- const result = await this.convertToPostData(schemeItem, val, originFormValue, scheme)
- set(formValue, path, result)
- }
- }
- }
- }
-
- formValue.formreq.forEach(t => { t.formData = JSON.stringify(t.formData) })
- formValue.formreq = JSON.stringify(formValue.formreq)
-
- return formValue
- },
-
- /**
- * 获取流程信息
- * 参数: { code, processId, taskId }
- *
- */
- async fetchProcessInfo({ code, processId, taskId }) {
- const url = processId ? 'learun/adms/newwf/processinfo' : 'learun/adms/newwf/scheme'
- const reqObj = { processId }
- if (taskId) {
- reqObj.taskId = taskId
- }
- const data = processId ? reqObj : code
- const result = await this.HTTP_GET(url, data)
-
- if (!result) { return {} }
-
- if (result.info) {
- result.info.Scheme = JSON.parse(result.info.Scheme)
- } else if (result.F_Content) {
- result.F_Content = JSON.parse(result.F_Content)
- }
-
- return result
- },
-
- /**
- * 从 processInfo 流程信息中,提取出 currentNode
- * 参数: processInfo
- *
- */
- getCurrentNode(processInfo) {
- if (processInfo.info) {
- return processInfo.info.Scheme.nodes.find(t => t.id === processInfo.info.CurrentNodeId)
- } else if (processInfo.F_Content) {
- return processInfo.F_Content.nodes.find(t => t.type === 'startround')
- }
-
- return {}
- },
-
- /**
- * 拉取表单的 schemeData
- * 参数: currentNode
- *
- * 从当前节点 currentNode 中提取出表单 id,然后自 API 地址 /form/scheme 中拉取表单数据并返回
- */
- async fetchSchemeData(currentNode, currentTask, type) {
- const { wfForms } = currentNode
-
- const data = wfForms.filter(t => t.formId).map(t => ({ id: t.formId, ver: '' }))
- const schemeData = await this.HTTP_GET('learun/adms/form/scheme', data)
-
- return schemeData || {}
- },
-
- /**
- * 拉取表单的 formData
- * 参数: currentNode, keyValue
- *
- * 提取当前节点信息、表单主键信息,从 API 地址 /form/data 中拉取表单数据
- */
- async fetchFormData({ wfForms }, keyValue) {
- const reqData = wfForms
- .filter(t => t.formId)
- .map(t => ({
- schemeInfoId: t.formId,
- processIdName: t.field,
- keyValue
- }))
-
- const formData = await this.HTTP_GET('learun/adms/form/data', reqData)
-
- return formData || {}
- }
- }
- }
|