diff --git a/src/main/resources/templates/admin/business/process-edit.ftl b/src/main/resources/templates/admin/business/process-edit.ftl
index 30ad4c4..4fe93dc 100644
--- a/src/main/resources/templates/admin/business/process-edit.ftl
+++ b/src/main/resources/templates/admin/business/process-edit.ftl
@@ -204,20 +204,20 @@
-
-
-
@@ -261,7 +261,7 @@
+ v-model="scope.row.totalAmount" controls-position="right">
@@ -277,7 +277,7 @@
+ v-model="scope.row.taxRate" controls-position="right">
@@ -292,32 +292,33 @@
-
-
- {{scope.row.attachment.name}}
-
-
-
+
上传附件
+
+
+
+
+
+
+
+
+ style="float: right;margin: 10px 10px 0 0">
-
+
返回上一级
保存草稿
提交
@@ -381,7 +382,7 @@
- {{scope.row.parent.amountCurrent}}
+
@@ -539,7 +540,7 @@
// 销售合同收入明细
incomeDetails: [],
supplierMaterialsForm: [],
- procurementDetailsRowKey: 0,
+ rowKeyCounter: 0,
procurementDetails: [],
filteredProcurementDetails: [],
}
@@ -628,7 +629,10 @@
.then(checkStatus)
.then(parseJSON)
.then(data => {
- const { incomeDetails, process, contract, procurementDetails, attachments, ...form } = data
+ const {
+ incomeDetails, process, supplierMaterials,
+ contract, procurementDetails, attachments, ...form
+ } = data
// 转换数据
// @formatter:off
const computeType = type => {
@@ -662,6 +666,12 @@
name: item.name, url: item.uri
}))
+ this.supplierMaterialsForm = supplierMaterials && supplierMaterials.map(material => ({
+ ...material, attachment: material.attachment && JSON.parse(material.attachment).map(item => ({
+ name: item.name, url: item.uri
+ }))
+ }))
+
let rowKey = 0
const convertCommon = detail => {
@@ -682,12 +692,13 @@
// mapChildren
let { purchaseDetails } = parent
if (isNotEmpty(purchaseDetails)) {
+ // 先取出第一个合并
+ const first = purchaseDetails.shift();
+ // 再处理剩余的子元素
purchaseDetails = purchaseDetails.map(purchase => ({
...purchase, ...convertCommon(detail), parent, newRow: true
}))
-
// 合并第一行到父级
- const first = purchaseDetails.shift();
Object.assign(parent, first)
delete parent['parent']
delete parent['purchaseDetails']
@@ -700,7 +711,7 @@
}
this.procurementDetails = computeProcurementDetails(procurementDetails)
- this.procurementDetailsRowKey = rowKey
+ this.rowKeyCounter = rowKey
if (process.processType === saleContract) {
this.changeMode(saleContractProcess)
@@ -711,10 +722,15 @@
})
.catch(err => {
- parseJSON(err.response)
- .then(json => {
- this.$message.error(json.message || "项目加载失败");
- })
+ if (err.response) {
+ parseJSON(err.response)
+ .then(json => {
+ this.$message.error(json.message || "项目加载失败");
+ })
+ }
+ else {
+ this.$message.error("项目加载失败")
+ }
})
.finally(() => loading.close())
},
@@ -735,116 +751,171 @@
},
submit(needValid) {
- this.$refs["contractProcessForm"].validate((valid) => {
- if (valid || !needValid) {
- const fileList = this.fileList
- if (needValid && fileList.length === 0) {
- this.$message.error("未上传附件");
- return false
- }
-
- const processType = this.processType
- const processForm = this.processForm
- if (needValid && processType === procurementContract) {
- const { procurementMode } = processForm
-
- // specify_purchase("指定采购"),
- // simple_price_comparison("简单比价"),
- // price_comparison("比价"),
- // competitive_evaluation("竞争性评估");
- // 当“采购模式”为“指定采购”“简单比价”时,本模块为非必填模块,当为“比价”“竞争性评估”时,本模块为必填项(“备注”除外)
- if (procurementMode === 'price_comparison'
- || procurementMode === 'competitive_evaluation') {
-
- if (isEmpty(this.supplierMaterialsForm)) {
- this.$message.error("供应商比选材料未填写")
+ const processForm = this.processForm
+ const processType = this.processType
+ const fileList = this.fileList
+ let validStatus = !needValid
+ if (needValid) {
+ // 校验表单
+ this.$refs["contractProcessForm"].validate((valid) => {
+ if (valid) {
+ if (fileList.length === 0) {
+ this.$message.error("未上传附件");
+ return false
+ }
+ if (processType === saleContract) {
+ if (!this.checkExpirationDate()) {
return false
}
- for (const item in this.supplierMaterialsForm) {
- if (isEmpty(Object.keys(item))) {
- this.$message.error("供应商比选材料未填写")
+ }
+
+ // 采购合同需要验证 供应商比选材料
+ if (processType === procurementContract) {
+ if (!this.checkProcurementDetails()) {
+ return false
+ }
+ const { procurementMode } = processForm
+
+ // specify_purchase("指定采购"),
+ // simple_price_comparison("简单比价"),
+ // price_comparison("比价"),
+ // competitive_evaluation("竞争性评估");
+ // 当“采购模式”为“指定采购”“简单比价”时,本模块为非必填模块,当为“比价”“竞争性评估”时,本模块为必填项(“备注”除外)
+ if (procurementMode === 'price_comparison'
+ || procurementMode === 'competitive_evaluation') {
+
+ if (isEmpty(this.supplierMaterialsForm)) {
+ this.$message.error("供应商比选材料未填写,请检查表单")
return false
}
- for (const [key, value] of Object.entries(item)) {
- if (value) {
- if (typeof value === 'string') {
- if (isBlank(value)) {
- this.$message.error("有未填写的表单,请检查表单");
- return false
+
+ let idx = 0
+ for (const item in this.supplierMaterialsForm) {
+ idx++
+ if (isEmptyObject(item)) {
+ this.$message.error("供应商比选材料第'" + idx + "'行未填写,请检查表单")
+ return false
+ }
+ for (const [key, value] of Object.entries(item)) {
+ if (value) {
+ if (typeof value === 'string') {
+ if (isBlank(value)) {
+ this.$message.error("供应商比选材料第'" + idx + "'行有数据未填写,请检查表单")
+ return false
+ }
+ }
+ }
+ else {
+ // 没有值
+ if (key !== 'remark') {
+ this.$message.error("供应商比选材料第'" + idx + "'行有数据未填写,请检查表单")
}
}
}
- else {
- // 没有值
- if (key !== 'remark') {
- this.$message.error("有未填写的表单,请检查表单");
- }
- }
- }
+ }
}
}
- }
- if (needValid && !processForm.applyDeptId) {
- this.$message.error("申请部门还未选择");
+ if (!processForm.applyDeptId) {
+ this.$message.error("申请部门还未选择");
+ return false
+ }
+
+ // 验证通过
+ validStatus = true
+ return true;
+ }
+ else {
return false
}
+ })
- const loading = this.$loading({
- lock: true,
- text: processForm.status === 'draft' ? '正在保存草稿' : "正在提交",
- spinner: 'el-icon-loading',
- background: 'rgba(0, 0, 0, 0.7)'
+ }
+
+ if (!validStatus) {
+ return false
+ }
+
+ const loading = this.$loading({
+ lock: true,
+ text: processForm.status === 'draft' ? '正在保存草稿' : "正在提交",
+ spinner: 'el-icon-loading',
+ background: 'rgba(0, 0, 0, 0.7)'
+ })
+
+ const budgetCostIdMap = new Map()
+ this.procurementDetails.forEach(detail => {
+ budgetCostIdMap.set(detail.budgetCostId, detail)
+ })
+
+ const computePurchaseAmountDetail = budgetCostId => {
+ const detail = budgetCostIdMap.get(budgetCostId)
+ const ret = []
+ const map = detail => {
+ const ret = {}
+ procurementDetailProperties.forEach(property => {
+ ret[property] = detail[property]
})
+ return ret
+ }
- const applyDeptId = processForm.applyDeptId.join(',') // (逗号分割)
+ ret.push(map(detail))
+ detail.children.forEach(detail => {
+ ret.push(map(detail))
+ })
+ return ret
+ }
- const form = {
- ...this.processForm,
- applyDeptId,
- attachments: fileList.map(file => {
- if (file.url) {
- return {
- uri: file.url,
- name: file.name
- }
- }
- return {
- uri: file.response.data.url,
- name: file.name
- }
- }),
- incomeDetails: this.incomeDetails.map(detail => ({
- id: detail.id, expirationDate: detail.expirationDate
- }))
+ const form = {
+ ...processForm,
+ processType,
+ applyDeptId: processForm.applyDeptId?.join(','), // (逗号分割),
+ attachments: fileList.map(file => {
+ if (file.url) {
+ return { uri: file.url, name: file.name }
}
+ return { uri: file.response.data.url, name: file.name }
+ }),
+ incomeDetails: this.incomeDetails.map(detail => ({
+ id: detail.id, expirationDate: detail.expirationDate
+ })),
+ purchaseAmount: this.filteredProcurementDetails.map(detail => ({
+ amount: detail.amount,
+ budgetCostId: detail.budgetCostId,
+ amountAlready: detail.amountAlready,
+ amountCurrent: detail.amountCurrent,
+ details: computePurchaseAmountDetail(detail.budgetCostId)
+ })),
+ supplierMaterials: this.supplierMaterialsForm.filter(hasProperties), // 剔除空行
+ }
- fetch("${base}/process", {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(form),
- }).then(response => {
- if (response.ok) {
- this.$message({
- showClose: true,
- message: '提交成功',
- type: 'success'
+ fetch("${base}/process", {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(form),
+ }).then(checkStatus).then(data => {
+ this.$message({
+ showClose: true,
+ message: processForm.status === 'draft' ? '草稿保存成功' : "提交成功",
+ type: 'success'
+ })
+ }).catch(({ response }) => {
+ const defaultMessage = () => {
+ return processForm.status === 'draft' ? '草稿保存失败' : "项目提交失败"
+ }
+ if (response) {
+ parseJSON(response)
+ .then(json => {
+ this.$message.error(json.message || defaultMessage())
})
- }
- else {
- return Promise.reject("失败")
- }
- }).catch(err => {
- this.$message.error("项目提交失败");
- }).finally(() => loading.close())
}
else {
- return false;
+ this.$message.error(defaultMessage())
}
- })
+ }).finally(() => loading.close())
},
submitToSaleContractProcess() {
@@ -873,12 +944,36 @@
}
},
+ handleSupplierMaterialRemove(scope, fileList) {
+ scope.row['attachment'] = fileList
+ },
+
+ handleSupplierMaterialExceed(scope, files, fileList) {
+ this.$message.warning("当前限制选择只能选择10个文件");
+ scope.row['attachment'] = fileList
+ },
+
+ beforeSupplierMaterialRemove(scope, file, fileList) {
+ return this.$confirm("确定移除 " + file.name + "?");
+ },
+
+ handleSupplierMaterialFileUploaded(scope, response, file, fileList) {
+ if (response.success) {
+ scope.row['attachment'] = fileList
+ }
+ else {
+ this.$message.warning("上传失败");
+ }
+ },
+
indexMethod(index) {
return index * 1;
},
addSupplierRow() {
- this.supplierMaterialsForm.push({})
+ this.supplierMaterialsForm.push({
+ rowKey: this.rowKeyCounter++,
+ })
},
addProcurementDetailRow(scope) {
@@ -886,7 +981,7 @@
const { children } = row
const newRow = {
...row,
- rowKey: this.procurementDetailsRowKey++,
+ rowKey: this.rowKeyCounter++,
newRow: true,
parent: row // 记录上一级元素,在删除的时候使用
}
@@ -916,6 +1011,11 @@
return '';
},
+ removeSupplierMaterialRow(scope) {
+ const { rowKey } = scope.row
+ this.supplierMaterialsForm = this.supplierMaterialsForm.filter(child => child.rowKey !== rowKey)
+ },
+
applyDeptSelected(value) {
if (value.length === 0) {
this.processForm['applyDept'] = null
diff --git a/src/main/resources/templates/admin/business/process-new.ftl b/src/main/resources/templates/admin/business/process-new.ftl
index f634fb1..dbffe22 100644
--- a/src/main/resources/templates/admin/business/process-new.ftl
+++ b/src/main/resources/templates/admin/business/process-new.ftl
@@ -341,11 +341,11 @@
+ :on-remove="handleRemove"
+ :on-exceed="handleExceed"
+ :before-remove="beforeRemove"
+ :on-success="handleFileUploaded">
点击上传
只能上传PDF、excel、word、图片、压缩包,且不超过50MB
@@ -411,24 +411,30 @@
{{scope.row.attachment.name}}
-
+
上传附件
+
+
+
+
+
+
+
+
+ style="float: right;margin: 10px 10px 0 0">
@@ -624,6 +630,29 @@
return !isBlank(obj)
}
+ const hasProperties = obj => {
+ return isNotEmpty(Object.keys(obj));
+ }
+
+ const isEmptyObject = obj => {
+ return isEmpty(Object.keys(obj));
+ }
+
+ function checkStatus(response) {
+ if (response.status >= 200 && response.status < 300) {
+ return response
+ }
+ else {
+ const error = new Error(response.statusText);
+ error.response = response
+ throw error
+ }
+ }
+
+ function parseJSON(response) {
+ return response.json()
+ }
+
const data = () => {
return {
mode: "btn", // btn , procurementContractProcess
@@ -641,7 +670,7 @@
processType: "",
procurementProjectSelectorVisible: false,
procurementDetailSelectorVisible: false,
- procurementDetailsRowKey: 0,
+ rowKeyCounter: 0,
}
}
@@ -867,7 +896,7 @@
rowKey: rowKey++, children: []
}))
- this.procurementDetailsRowKey = rowKey
+ this.rowKeyCounter = rowKey
})
.catch(err => {
@@ -938,19 +967,22 @@
|| procurementMode === 'competitive_evaluation') {
if (isEmpty(this.supplierMaterialsForm)) {
- this.$message.error("供应商比选材料未填写")
+ this.$message.error("供应商比选材料未填写,请检查表单")
return false
}
+
+ let idx = 0
for (const item in this.supplierMaterialsForm) {
- if (isEmpty(Object.keys(item))) {
- this.$message.error("供应商比选材料未填写")
+ idx++
+ if (isEmptyObject(item)) {
+ this.$message.error("供应商比选材料第'" + idx + "'行未填写,请检查表单")
return false
}
for (const [key, value] of Object.entries(item)) {
if (value) {
if (typeof value === 'string') {
if (isBlank(value)) {
- this.$message.error("有未填写的表单,请检查表单");
+ this.$message.error("供应商比选材料第'" + idx + "'行有数据未填写,请检查表单")
return false
}
}
@@ -958,7 +990,7 @@
else {
// 没有值
if (key !== 'remark') {
- this.$message.error("有未填写的表单,请检查表单");
+ this.$message.error("供应商比选材料第'" + idx + "'行有数据未填写,请检查表单")
}
}
}
@@ -1000,7 +1032,6 @@
budgetCostIdMap.set(detail.budgetCostId, detail)
})
- debugger
const computePurchaseAmountDetail = budgetCostId => {
const detail = budgetCostIdMap.get(budgetCostId)
const ret = []
@@ -1019,16 +1050,14 @@
return ret
}
- const applyDeptId = processForm.applyDeptId?.join(',') // (逗号分割)
const form = {
...processForm,
processType,
- applyDeptId,
+ applyDeptId: processForm.applyDeptId?.join(','),// (逗号分割),
attachments: fileList.map(file => ({
uri: file.response.data.url,
name: file.response.data.originName
})),
- supplierMaterials: this.supplierMaterialsForm,
incomeDetails: this.incomeDetails.map(detail => ({
id: detail.id, expirationDate: detail.expirationDate
})),
@@ -1038,7 +1067,8 @@
amountAlready: detail.amountAlready,
amountCurrent: detail.amountCurrent,
details: computePurchaseAmountDetail(detail.budgetCostId)
- }))
+ })),
+ supplierMaterials: this.supplierMaterialsForm.filter(hasProperties), // 剔除空行
}
fetch("${base}/process", {
@@ -1047,19 +1077,25 @@
'Content-Type': 'application/json',
},
body: JSON.stringify(form),
- }).then(response => {
- if (response.ok) {
- this.$message({
- showClose: true,
- message: '提交成功',
- type: 'success'
- })
+ }).then(checkStatus).then(data => {
+ this.$message({
+ showClose: true,
+ message: processForm.status === 'draft' ? '草稿保存成功' : "提交成功",
+ type: 'success'
+ })
+ }).catch(({ response }) => {
+ const defaultMessage = () => {
+ return processForm.status === 'draft' ? '草稿保存失败' : "项目提交失败"
+ }
+ if (response) {
+ parseJSON(response)
+ .then(json => {
+ this.$message.error(json.message || defaultMessage())
+ })
}
else {
- return Promise.reject("失败")
+ this.$message.error(defaultMessage())
}
- }).catch(err => {
- this.$message.error("项目提交失败");
}).finally(() => loading.close())
},
@@ -1101,12 +1137,38 @@
}
},
+ handleSupplierMaterialRemove(scope, fileList) {
+ scope.row['fileList'] = fileList
+ },
+
+ handleSupplierMaterialExceed(scope, files, fileList) {
+ this.$message.warning("当前限制选择只能选择10个文件");
+ scope.row['fileList'] = fileList
+ },
+
+ beforeSupplierMaterialRemove(scope, file, fileList) {
+ return this.$confirm("确定移除 " + file.name + "?");
+ },
+
+ handleSupplierMaterialFileUploaded(scope, response, file, fileList) {
+ if (response.success) {
+ scope.row['fileList'] = fileList
+
+ this.fileListSupplierMaterial = fileList
+ }
+ else {
+ this.$message.warning("上传失败");
+ }
+ },
+
indexMethod(index) {
return index * 1;
},
addSupplierRow() {
- this.supplierMaterialsForm.push({})
+ this.supplierMaterialsForm.push({
+ rowKey: this.rowKeyCounter++,
+ })
},
addProcurementDetailRow(scope) {
@@ -1114,7 +1176,7 @@
const { children } = row
const newRow = {
...row,
- rowKey: this.procurementDetailsRowKey++,
+ rowKey: this.rowKeyCounter++,
newRow: true,
parent: row // 记录上一级元素,在删除的时候使用
}
@@ -1131,8 +1193,8 @@
},
removeProcurementDetailRow(scope) {
- const { rowKey, parent } = scope.row
- parent.children = parent.children.filter(child => child.rowKey !== rowKey)
+ const { rowKey } = scope.row
+ .filter(child => child.rowKey !== rowKey)
},
// 区别子项
@@ -1144,6 +1206,11 @@
return '';
},
+ removeSupplierMaterialRow(scope) {
+ const { rowKey } = scope.row
+ this.supplierMaterialsForm = this.supplierMaterialsForm.filter(child => child.rowKey !== rowKey)
+ },
+
applyDeptSelected(value) {
if (value.length === 0) {
this.processForm['applyDept'] = null