Преглед изворни кода

app2.0审批页面表单逻辑js

娄底高职分支
ndbs пре 2 година
родитељ
комит
861ee55c54
1 измењених фајлова са 379 додато и 294 уклоњено
  1. +379
    -294
      Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/nworkflow/workflow.js

+ 379
- 294
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 || {}
},
}
}

Loading…
Откажи
Сачувај