diff --git a/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/nworkflow/workflow.js b/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/nworkflow/workflow.js index c3689c50f..0b6531b31 100644 --- a/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/nworkflow/workflow.js +++ b/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/nworkflow/workflow.js @@ -32,298 +32,383 @@ import customForm from '@/common/customform.js' * (以上只是简单介绍;实际使用中,如果打开子流程,需要拉取父/子两个流程信息) */ 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 || {} - } - } + 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 + } + }, + newguid() { + return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, + v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + }, + /** + * 获取最终需要 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) + var guid = undefined + if (item.type == 'upload') { + // 先生成一个guid + guid = this.newguid(); + // 取出当前列对应的labelId + var labeId = item.id + // 从缓存取出当前审批流程所有的guid + var guids = JSON.parse(uni.getStorageSync('guids')) + if (guids&&JSON.stringify(guids)!=='{}'&&guids[labeId]) { + guid = guids[labeId] + } + } + const result = await this.convertToPostData(item, val, originFormValue, scheme, guid) + 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, + guid) + 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 || {} + }, + async fetchFolderkeyData(currentNode, keyValue) { + const { + wfForms + } = currentNode + + const reqData = wfForms + .filter(t => t.formId) + .map(t => ({ + id: t.formId, + ver: '', + schemeInfoId: t.formId, + processIdName: t.field, + keyValue + })) + const folderkeyData = await this.HTTP_GET('learun/adms/form/folderkey', reqData) + return folderkeyData || {} + }, + } }