@@ -40,8 +40,7 @@ namespace Learun.Application.WebApi.Modules | |||||
public Response WxUpload(dynamic _) | public Response WxUpload(dynamic _) | ||||
{ | { | ||||
var files = (List<HttpFile>)this.Context.Request.Files; | var files = (List<HttpFile>)this.Context.Request.Files; | ||||
//var folderId = this.GetReqData(); | |||||
string folderId = Guid.NewGuid().ToString(); | |||||
string folderId = Request.Form["folderId"]; | |||||
string filePath = Config.GetValue("AnnexesFile"); | string filePath = Config.GetValue("AnnexesFile"); | ||||
string uploadDate = DateTime.Now.ToString("yyyyMMdd"); | string uploadDate = DateTime.Now.ToString("yyyyMMdd"); | ||||
string fileEextension = Path.GetExtension(files[0].Name); | string fileEextension = Path.GetExtension(files[0].Name); | ||||
@@ -24,274 +24,310 @@ import moment from 'moment' | |||||
*/ | */ | ||||
export default { | 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 path = this.API + '/annexes/wxdown?' + this.URL_QUERY(uid, true) | |||||
fileList.push({ path, type: fileType, uid, size: fileSize }) | |||||
} | |||||
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 uploadUid = [] | |||||
for (const item of val) { | |||||
if (item.uid) { | |||||
uploadUid.push(item.uid) | |||||
continue | |||||
} | |||||
const fileId = await this.HTTP_UPLOAD(item.path||item) | |||||
if (fileId) { | |||||
uploadUid.push(fileId) | |||||
} | |||||
} | |||||
return uploadUid.join(',') | |||||
default: | |||||
return val || '' | |||||
} | |||||
} | |||||
} | |||||
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; | |||||
const fileList = [] | |||||
const wxlist = await this.FETCH_FILEList(uidList); | |||||
for (const wxfile of wxlist) { | |||||
const fileInfo = await this.FETCH_FILEINFO(wxfile.F_Id) | |||||
if (!fileInfo) { | |||||
continue | |||||
} | |||||
const fileType = fileInfo.F_FileType | |||||
const fileSize = fileInfo.F_FileSize | |||||
const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(wxfile.F_Id, true) | |||||
fileList.push({ | |||||
path, | |||||
type: fileType, | |||||
uid:wxfile.F_Id, | |||||
folderId:wxfile.F_FolderId, | |||||
size: fileSize | |||||
}) | |||||
} | |||||
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, guid) { | |||||
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': | |||||
var uploadUid = ''; | |||||
for (const item of val) { | |||||
if (item.uid) { | |||||
uploadUid = item.uid | |||||
continue | |||||
} | |||||
const fileId = await this.HTTP_UPLOAD(item.path || item, undefined, guid || '') | |||||
if (fileId) { | |||||
uploadUid = fileId; | |||||
} | |||||
} | |||||
return uploadUid; | |||||
default: | |||||
return val || '' | |||||
} | |||||
} | |||||
} | |||||
} | } |
@@ -257,7 +257,6 @@ export default { | |||||
const fileSize = fileInfo.F_FileSize | const fileSize = fileInfo.F_FileSize | ||||
const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(uid, true) | const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(uid, true) | ||||
fileList.push({ path, type: fileType, uid, size: fileSize }) | fileList.push({ path, type: fileType, uid, size: fileSize }) | ||||
} | } | ||||
return fileList | return fileList | ||||
@@ -229,6 +229,14 @@ export default { | |||||
return await this.HTTP_GET('learun/adms/annexes/wxfileinfo', fileId) | return await this.HTTP_GET('learun/adms/annexes/wxfileinfo', fileId) | ||||
}, | }, | ||||
//获取文件夹下文件列表 | |||||
async FETCH_FILEList(folderId) { | |||||
if (!folderId) { | |||||
return null | |||||
} | |||||
return await this.HTTP_GET('learun/adms/annexes/wxlist', folderId) | |||||
}, | |||||
// 封装的 GET 请求,集成了验证信息 | // 封装的 GET 请求,集成了验证信息 | ||||
// 返回请求结果或 null | // 返回请求结果或 null | ||||
@@ -258,8 +266,8 @@ export default { | |||||
// url 为请求地址 | // url 为请求地址 | ||||
// filePath 为临时文件的路径 | // filePath 为临时文件的路径 | ||||
// formData 为请求附带的提交数据 | // formData 为请求附带的提交数据 | ||||
async HTTP_UPLOAD(filePath, formData) { | |||||
const [err, res] = await this.UPLOAD('/learun/adms/annexes/wxupload', filePath, formData) | |||||
async HTTP_UPLOAD(filePath, formData,guid) { | |||||
const [err, res] = await this.UPLOAD('/learun/adms/annexes/wxupload', filePath, formData,guid) | |||||
return this.handleResult(err, res) | return this.handleResult(err, res) | ||||
}, | }, | ||||
@@ -308,11 +316,12 @@ export default { | |||||
// 返回结果是一个数组: [error, result] | // 返回结果是一个数组: [error, result] | ||||
// error 表示错误,一般是网络错误,请求很可能根本没有发出 | // error 表示错误,一般是网络错误,请求很可能根本没有发出 | ||||
// result 包含 { statusCode, data } 分别表示状态码、接口返回的数据 | // result 包含 { statusCode, data } 分别表示状态码、接口返回的数据 | ||||
async UPLOAD(url, filePath, formData) { | |||||
async UPLOAD(url, filePath, formData,guid) { | |||||
const uploadUrl = this.handleUrl(url) | const uploadUrl = this.handleUrl(url) | ||||
const query = { | const query = { | ||||
loginMark: this.getLoginMark(), | loginMark: this.getLoginMark(), | ||||
token: this.GET_GLOBAL('token') | |||||
token: this.GET_GLOBAL('token'), | |||||
folderId:guid | |||||
} | } | ||||
if (formData && typeof formData === 'object') { | if (formData && typeof formData === 'object') { | ||||
@@ -21,8 +21,8 @@ export default { | |||||
// "http://192.168.2.98:8088/" | // "http://192.168.2.98:8088/" | ||||
// ], | // ], | ||||
"apiHost": [ | "apiHost": [ | ||||
// "http://localhost:31173/" | |||||
"http://192.168.10.68:8002/" | |||||
"http://localhost:31173/" | |||||
//"http://192.168.10.68:8002/" | |||||
], | ], | ||||
"webHost":"http://localhost:20472/", | "webHost":"http://localhost:20472/", | ||||
// 开发环境下自动填充登录账号密码,与接口地址一一对应,只在开发环境下显示 | // 开发环境下自动填充登录账号密码,与接口地址一一对应,只在开发环境下显示 | ||||
@@ -132,7 +132,7 @@ export default { | |||||
return null | return null | ||||
} | } | ||||
return this.API + `/user/img?data=${item.F_OtherUserId}` | |||||
return this.API + `/learun/adms/user/img?data=${item.F_OtherUserId}` | |||||
} | } | ||||
}, | }, | ||||
@@ -186,7 +186,7 @@ export default { | |||||
// 获取用户头像图片 url | // 获取用户头像图片 url | ||||
avatar(id) { | avatar(id) { | ||||
return id === this.chatUserId && this.isSystem ? null : this.API + `/user/img?data=${id}` | |||||
return id === this.chatUserId && this.isSystem ? null : this.API + `/learun/adms/user/img?data=${id}` | |||||
} | } | ||||
}, | }, | ||||
@@ -156,7 +156,7 @@ export default { | |||||
return '' | return '' | ||||
} | } | ||||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||||
} | } | ||||
}, | }, | ||||
@@ -34,7 +34,7 @@ export default { | |||||
// 头像图片 url | // 头像图片 url | ||||
avatarSrc() { | avatarSrc() { | ||||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -30,7 +30,7 @@ export default { | |||||
// 头像图片 url | // 头像图片 url | ||||
avatar() { | avatar() { | ||||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||||
}, | }, | ||||
// 用户公司部门 tag | // 用户公司部门 tag | ||||
@@ -95,7 +95,6 @@ export default { | |||||
// t.formId 使用表单,根据这个 formId 来获取 scheme 等信息 | // t.formId 使用表单,根据这个 formId 来获取 scheme 等信息 | ||||
// t.appurl 使用移动页面,直接跳转到本地的页面;表单结构等均写死在页面里 | // t.appurl 使用移动页面,直接跳转到本地的页面;表单结构等均写死在页面里 | ||||
const { wfForms } = this.currentNode | const { wfForms } = this.currentNode | ||||
console.log(wfForms); | |||||
// 处理没有有效表单的情况,停止加载 | // 处理没有有效表单的情况,停止加载 | ||||
if (!wfForms || wfForms.every(t => !t.formId && !t.appurl)) { | if (!wfForms || wfForms.every(t => !t.formId && !t.appurl)) { | ||||
@@ -144,7 +143,6 @@ export default { | |||||
code: this.code, | code: this.code, | ||||
useDefault: true | useDefault: true | ||||
}) | }) | ||||
console.log("formValue",formValue,"scheme",scheme) | |||||
this.scheme = scheme | this.scheme = scheme | ||||
this.formValue = formValue | this.formValue = formValue | ||||
this.rel = rel | this.rel = rel | ||||
@@ -152,8 +150,6 @@ export default { | |||||
// 不是子流程,可以直接渲染 | // 不是子流程,可以直接渲染 | ||||
const schemeData = await this.fetchSchemeData(this.currentNode) | const schemeData = await this.fetchSchemeData(this.currentNode) | ||||
const formData = await this.fetchFormData(this.currentNode, this.processId) | const formData = await this.fetchFormData(this.currentNode, this.processId) | ||||
console.log(schemeData) | |||||
console.log(formData) | |||||
const { formValue, scheme, rel } = await this.getCustomForm({ | const { formValue, scheme, rel } = await this.getCustomForm({ | ||||
formData, | formData, | ||||
schemeData, | schemeData, | ||||
@@ -161,7 +157,6 @@ export default { | |||||
processId: this.processId, | processId: this.processId, | ||||
code: null | code: null | ||||
}) | }) | ||||
console.log("formValue",formValue,"scheme",scheme) | |||||
this.scheme = scheme | this.scheme = scheme | ||||
this.formValue = formValue | this.formValue = formValue | ||||
this.rel = rel | this.rel = rel | ||||
@@ -110,7 +110,9 @@ export default { | |||||
this.needTitle = this.type !== 'again' && Number(currentNode.isTitle) === 1 | this.needTitle = this.type !== 'again' && Number(currentNode.isTitle) === 1 | ||||
const formData = await this.fetchFormData(currentNode, processId) | const formData = await this.fetchFormData(currentNode, processId) | ||||
const schemeData = await this.fetchSchemeData(currentNode) | const schemeData = await this.fetchSchemeData(currentNode) | ||||
const { formValue, scheme, rel } = await this.getCustomForm({ | const { formValue, scheme, rel } = await this.getCustomForm({ | ||||
schemeData, | schemeData, | ||||
processId, | processId, | ||||
@@ -119,14 +121,16 @@ export default { | |||||
code: this.type === 'again' ? null : code, | code: this.type === 'again' ? null : code, | ||||
useDefault: true | useDefault: true | ||||
}) | }) | ||||
this.rel = rel | this.rel = rel | ||||
this.scheme = scheme | this.scheme = scheme | ||||
this.formValue = formValue | this.formValue = formValue | ||||
this.code = code | this.code = code | ||||
this.processId = processId | this.processId = processId | ||||
console.log(this.formValue,'=====',this.scheme ,) | |||||
this.ready = true | this.ready = true | ||||
this.HIDE_LOADING() | this.HIDE_LOADING() | ||||
}, | }, | ||||
// 提交草稿按钮 | // 提交草稿按钮 | ||||
@@ -194,7 +198,6 @@ export default { | |||||
verifyValue() { | verifyValue() { | ||||
const errList = this.$refs.form.verifyValue() | const errList = this.$refs.form.verifyValue() | ||||
console.log(errList,'errList') | |||||
if (this.needTitle && !this.title) { | if (this.needTitle && !this.title) { | ||||
errList.push(`流程的标题不能为空`) | errList.push(`流程的标题不能为空`) | ||||
} | } | ||||
@@ -32,301 +32,355 @@ import customForm from '@/common/customform.js' | |||||
* (以上只是简单介绍;实际使用中,如果打开子流程,需要拉取父/子两个流程信息) | * (以上只是简单介绍;实际使用中,如果打开子流程,需要拉取父/子两个流程信息) | ||||
*/ | */ | ||||
export default { | 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 | |||||
console.log(prop,'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) | |||||
console.log(val,'val=======') | |||||
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) | |||||
var guid =this.newguid(); | |||||
// 依次按照 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, 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 || {} | |||||
} | |||||
} | |||||
} | } |