From a8fc43ef59729bbc04ad6f552e1a942cd13b1337 Mon Sep 17 00:00:00 2001 From: wenlele Date: Fri, 2 Dec 2022 11:26:31 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/client/src/layout/components/sider/index.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/client/src/layout/components/sider/index.jsx b/web/client/src/layout/components/sider/index.jsx index 08e5ef0..c253fd2 100644 --- a/web/client/src/layout/components/sider/index.jsx +++ b/web/client/src/layout/components/sider/index.jsx @@ -18,9 +18,9 @@ const Sider = (props) => { let nextItems = leftItems setItems(nextItems) scrollbar = new PerfectScrollbar('#page-slider', { suppressScrollX: true }); - if (pathname == '/') { - dispatch(push(homePath)) - } + // if (pathname == '/') { + // dispatch(push(homePath)) + // } }, [leftItems]) let routeSelectedKey = useLocation().pathname.split('/'); // let routeSelectedKey = [useLocation().pathname.split('/')[1]]//没有子目录的 From 4b4412fe3597d5687c5baaf4ab0084325d277615 Mon Sep 17 00:00:00 2001 From: zhangminghua Date: Fri, 2 Dec 2022 14:33:46 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E8=A1=A8=E5=B7=B2=E5=AD=98=E5=9C=A8=E7=BC=96=E5=8F=B7=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/report/achievement.js | 4 +++- api/app/lib/routes/report/index.js | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/app/lib/controllers/report/achievement.js b/api/app/lib/controllers/report/achievement.js index a5c2e70..32fded1 100644 --- a/api/app/lib/controllers/report/achievement.js +++ b/api/app/lib/controllers/report/achievement.js @@ -259,8 +259,10 @@ async function exportAchievementDetail(ctx, dataList) { async function getReceivedNumbers(ctx) { try { + const { tableModel } = ctx.query; const models = ctx.fs.dc.models; - let list = await models.ReceivableDetail.findAll({//查编号 + let model = tableModel || 'ReceivableDetail' + let list = await models[model].findAll({//查编号 attributes: ['number'] }); ctx.status = 200 diff --git a/api/app/lib/routes/report/index.js b/api/app/lib/routes/report/index.js index aedc624..c2e8e89 100644 --- a/api/app/lib/routes/report/index.js +++ b/api/app/lib/routes/report/index.js @@ -16,10 +16,7 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/detail/achievement'] = { content: '查询业绩明细表', visible: false }; router.get('/detail/achievement', achieve.getAchievementDetail); - - - - app.fs.api.logAttr['GET/detail/received/numbers'] = { content: '查询业绩明细已有的编号集合', visible: false }; + app.fs.api.logAttr['GET/detail/received/numbers'] = { content: '查询明细表已有的编号集合', visible: false }; router.get('/detail/received/numbers', achieve.getReceivedNumbers); app.fs.api.logAttr['POST/add/received/back/bulk'] = { content: '导入回款明细', visible: true }; @@ -38,4 +35,5 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/export/invoicing/detail'] = { content: '导出开票明细表', visible: false }; router.get('/export/invoicing/detail', achieve.exportInvoicingDetail); + }; \ No newline at end of file From d753cc2bea84880b55b62ef9f3af9b21840348ed Mon Sep 17 00:00:00 2001 From: zhangminghua Date: Fri, 2 Dec 2022 15:14:57 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E8=A1=A8=E6=8E=A5=E5=8F=A3=E8=B0=83=E6=95=B4=EF=BC=8C=E5=90=88?= =?UTF-8?q?=E5=90=8C=E3=80=81=E5=BC=80=E7=A5=A8=E3=80=81=E5=9B=9E=E6=AC=BE?= =?UTF-8?q?=E9=80=9A=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/report/achievement.js | 31 ++++++++++++------- api/app/lib/routes/report/index.js | 4 +-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/api/app/lib/controllers/report/achievement.js b/api/app/lib/controllers/report/achievement.js index 32fded1..5fd87e0 100644 --- a/api/app/lib/controllers/report/achievement.js +++ b/api/app/lib/controllers/report/achievement.js @@ -256,13 +256,17 @@ async function exportAchievementDetail(ctx, dataList) { } } } - +/** + * 查询明细表已存在编号数据,回款、合同、开票通用 + * @param {*} ctx ctx ctx.query:{tableModel表模型名} + */ async function getReceivedNumbers(ctx) { + let errorMsg = { name: 'FindError', message: '查询失败' }; try { const { tableModel } = ctx.query; const models = ctx.fs.dc.models; - let model = tableModel || 'ReceivableDetail' - let list = await models[model].findAll({//查编号 + let modelName = tableModel || 'ReceivableDetail' + let list = await models[modelName].findAll({//查编号 attributes: ['number'] }); ctx.status = 200 @@ -270,20 +274,23 @@ async function getReceivedNumbers(ctx) { } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } + ctx.body = errorMsg; } } - +/** + * 导入明细表数据,回款、合同、开票通用 + * @param {*} ctx ctx ctx.query:{tableModel表模型名} + */ async function importBackDetails(ctx) { - let errorMsg = { message: '导入回款明细失败' }; + let errorMsg = { message: '导入失败' }; const transaction = await ctx.fs.dc.orm.transaction(); try { const models = ctx.fs.dc.models; const data = ctx.request.body; + const { tableModel } = ctx.query; + let modelName = tableModel || 'ReceivableDetail' let addArr = []; - let dataList = await models.ReceivableDetail.findAll({//查编号 + let dataList = await models[modelName].findAll({//查编号 attributes: ['number'] }); data.map(d => { @@ -294,7 +301,7 @@ async function importBackDetails(ctx) { }) //只处理新增的 if (addArr.length) { - await models.ReceivableDetail.bulkCreate(addArr); + await models[modelName].bulkCreate(addArr, { transaction }); } await transaction.commit(); ctx.status = 204; @@ -440,8 +447,8 @@ module.exports = { getReceivedDetail,//回款 getAchievementDetail,//业绩 - getReceivedNumbers,//查询回款明细表 已有的所有编号 - importBackDetails,//导入回款明细 + getReceivedNumbers,//查询回款、合同、开票明细表 已有的所有编号 + importBackDetails,//导入回款、合同、开票明细 importAchieveDetails,//导入业绩明细 getContractDetail, getInvoicingDetail, diff --git a/api/app/lib/routes/report/index.js b/api/app/lib/routes/report/index.js index c2e8e89..18a089f 100644 --- a/api/app/lib/routes/report/index.js +++ b/api/app/lib/routes/report/index.js @@ -19,11 +19,12 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/detail/received/numbers'] = { content: '查询明细表已有的编号集合', visible: false }; router.get('/detail/received/numbers', achieve.getReceivedNumbers); - app.fs.api.logAttr['POST/add/received/back/bulk'] = { content: '导入回款明细', visible: true }; + app.fs.api.logAttr['POST/add/received/back/bulk'] = { content: '导入明细表', visible: true }; router.post('/add/received/back/bulk', achieve.importBackDetails); app.fs.api.logAttr['POST/add/achievement/bulk'] = { content: '导入业绩明细', visible: true }; router.post('/add/achievement/bulk', achieve.importAchieveDetails); + app.fs.api.logAttr['GET/contract/detail'] = { content: '查询合同明细表', visible: false }; router.get('/contract/detail', achieve.getContractDetail); @@ -35,5 +36,4 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/export/invoicing/detail'] = { content: '导出开票明细表', visible: false }; router.get('/export/invoicing/detail', achieve.exportInvoicingDetail); - }; \ No newline at end of file From f0ef5f9f487031c81face6b57a5a235ce76e80a9 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 2 Dec 2022 15:24:47 +0800 Subject: [PATCH 4/8] =?UTF-8?q?(*)=E4=B8=9A=E7=BB=A9=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 2 +- api/app/lib/controllers/report/achievement.js | 12 ++++++------ web/client/src/sections/business/constants/index.js | 6 +++--- .../performanceReport/achievementDetails.jsx | 2 +- .../performanceReport/backMoneyDetails.jsx | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index cd44ee8..9a66814 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -45,7 +45,7 @@ "-g postgres://FashionAdmin:123456@10.8.30.36:5432/data_center", "--redisHost localhost", "--redisPort 6379", - "--apiEmisUrl http://10.8.30.103:14000", //开发 + "--apiEmisUrl http://localhost:14000", //开发 // "--apiEmisUrl http://10.8.30.161:1111", //测试 // 镇江研发结束 // 测试 diff --git a/api/app/lib/controllers/report/achievement.js b/api/app/lib/controllers/report/achievement.js index a5c2e70..d415ce2 100644 --- a/api/app/lib/controllers/report/achievement.js +++ b/api/app/lib/controllers/report/achievement.js @@ -102,7 +102,7 @@ async function exportReceivedDetail(ctx, dataList) { exportData.push(item) } const fileName = `回款明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx' - const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName }) + const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName, needIndexCell: false }) const fileData = fs.readFileSync(filePath); ctx.status = 200; ctx.set('Content-Type', 'application/x-xls'); @@ -225,20 +225,20 @@ async function exportAchievementDetail(ctx, dataList) { title: '是否可复制的业务路径', key: 'reproducible', }, { - title: '省外业务1.1', + title: '省外业务', key: 'outProvince', }, { - title: '复购业务1.05', + title: '复购业务', key: 'repurchase', }, { - title: '可复制的业务路径1.1', + title: '可复制的业务路径', key: 'isreproduce', }] const { utils: { simpleExcelDown } } = ctx.app.fs; let exportData = [] for (let { dataValues: item } of dataList) { - item.isApproval = item.isApproval ? '是' : '否'; - item.reproducible = item.reproducible ? '是' : '否'; + item.isApproval = JSON.stringify(item.isApproval) === 'null' ? '-' : item.isApproval ? '是' : '否'; + item.reproducible = JSON.stringify(item.reproducible) === 'null' ? '-' : item.reproducible ? '是' : '否'; exportData.push(item) } const fileName = `业绩明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx' diff --git a/web/client/src/sections/business/constants/index.js b/web/client/src/sections/business/constants/index.js index 4cf96c3..c0fd58b 100644 --- a/web/client/src/sections/business/constants/index.js +++ b/web/client/src/sections/business/constants/index.js @@ -116,7 +116,7 @@ export const achievementColumnKeys = { cusAttribute: '客户属性', repurchaseCount: '复购次数', reproducible: '是否可复制的业务路径', - outProvince: '省外业务1.1', - repurchase: '复购业务1.05', - isreproduce: '可复制的业务路径1.1', + outProvince: '省外业务', + repurchase: '复购业务', + isreproduce: '可复制的业务路径', } \ No newline at end of file diff --git a/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx b/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx index c27d7a9..3fa9b7a 100644 --- a/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx +++ b/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx @@ -46,7 +46,7 @@ const AchievementDetails = (props) => { switch (key) { default: columns.push({ - title: columnKeys[key], dataIndex: key, key: key, width: 130, + title: columnKeys[key], dataIndex: key, key: key, width: 120, render: (text, record) => ['isApproval', 'reproducible'].indexOf(key) != -1 ? JSON.stringify(text) === 'null' ? '-' : text ? '是' : '否' : text === 0 ? text : text ? text : '-' }); diff --git a/web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx b/web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx index bd516ec..cfe3eb2 100644 --- a/web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx +++ b/web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx @@ -45,7 +45,7 @@ const BackMoneyDetails = (props) => { switch (key) { default: columns.push({ - title: columnKeys[key], dataIndex: key, key: key, width: 130, + title: columnKeys[key], dataIndex: key, key: key, width: 115, render: (text, record) => text === 0 ? text : text ? text : '-' }); break; From 47bf0628d08d4e7705e9709e18b151efbef861a8 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 2 Dec 2022 15:53:22 +0800 Subject: [PATCH 5/8] =?UTF-8?q?(*)=E5=9B=9E=E6=AC=BE=E5=92=8C=E4=B8=9A?= =?UTF-8?q?=E7=BB=A9=E6=98=8E=E7=BB=86=E5=AF=BC=E5=85=A5=20=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=AD=97=E6=AE=B5=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../performanceReport/importAchieveModal.jsx | 6 ++++ .../performanceReport/importBackModal.jsx | 32 +++++++++---------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/web/client/src/sections/business/containers/performanceReport/importAchieveModal.jsx b/web/client/src/sections/business/containers/performanceReport/importAchieveModal.jsx index 51036af..a3f754b 100644 --- a/web/client/src/sections/business/containers/performanceReport/importAchieveModal.jsx +++ b/web/client/src/sections/business/containers/performanceReport/importAchieveModal.jsx @@ -163,6 +163,7 @@ const ImportAchieveModal = props => { return } let postData = []; + let zzsPattern = /^[+]{0,1}(\d+)$/;//正整数 for (let i = 0; i < res.length; i++) { let d = res[i]; let obj = {}; @@ -183,6 +184,11 @@ const ImportAchieveModal = props => { error(`第${i + 2}行【价格是否特批】错误,请填写是或否`) return } + //复购次数 正整数 + if (obj.repurchaseCount && !zzsPattern.test(obj.repurchaseCount)) { + error(`第${i + 2}行【复购次数】填写错误,需要为非负整数`) + return + } if (obj.reproducible && ['是', '否'].indexOf(obj.reproducible) == -1) { error(`第${i + 2}行【是否可复制的业务路径】错误,请填写是或否`) diff --git a/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx b/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx index 0299946..661c268 100644 --- a/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx +++ b/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx @@ -171,7 +171,9 @@ const ImportBackModal = props => { return } let postData = []; - const numPattern = /^\d+(\.\d+)?$/;//非负浮点数 判断金额 + //const numPattern = /^\d+(\.\d+)?$/;//非负浮点数 判断金额 + let zzsPattern = /^[+]{0,1}(\d+)$/;//正整数 + let yearPattern = /^(19|20)\d{2}$/;//1900-2099年 for (let i = 0; i < res.length; i++) { let d = res[i]; let obj = {}; @@ -187,6 +189,16 @@ const ImportBackModal = props => { error(`第${i + 2}行【年度】、【序号】、【编号】存在空值,请填写`) return } + //年份 + if (obj.year && !yearPattern.test(obj.year)) { + error(`第${i + 2}行【年份】填写错误`) + return + } + //序号 正整数 + if (obj.serialNo && !zzsPattern.test(obj.serialNo)) { + error(`第${i + 2}行【序号】填写错误,需要为非负整数`) + return + } let exist = allNumbers.find(m => m.number == obj.number);//数据库中 已有该编号 if (exist) { error(`第${i + 2}行的【编号】在系统中已存在`) @@ -196,21 +208,9 @@ const ImportBackModal = props => { error(`第${i + 2}行【编号】重复,请更改后重新上传`) return } - //金额 数字 - if (obj.amount && !numPattern.test(obj.amount)) { - error(`第${i + 2}行【合同金额】填写错误,需要为数字`) - return - } - if (obj.changeAmount && !numPattern.test(obj.changeAmount)) { - error(`第${i + 2}行【变更后合同金额】填写错误,需要为数字`) - return - } - if (obj.receivableAmount && !numPattern.test(obj.receivableAmount)) { - error(`第${i + 2}行【回款金额】填写错误,需要为数字`) - return - } - if (obj.remainConAmount && !numPattern.test(obj.remainConAmount)) { - error(`第${i + 2}行【剩余合同金额】填写错误,需要为数字`) + //回款年份 + if (obj.receivableYear && !yearPattern.test(obj.receivableYear)) { + error(`第${i + 2}行【回款年份】填写错误`) return } //时间 From 3eb9bfcbe4a4134e58f175d7d35283e0426bbc89 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 2 Dec 2022 16:18:20 +0800 Subject: [PATCH 6/8] =?UTF-8?q?(*)=E5=9B=9E=E6=AC=BE=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=20=E7=BB=86=E8=8A=82=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../containers/performanceReport/importBackModal.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx b/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx index 661c268..9b3f34f 100644 --- a/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx +++ b/web/client/src/sections/business/containers/performanceReport/importBackModal.jsx @@ -189,9 +189,9 @@ const ImportBackModal = props => { error(`第${i + 2}行【年度】、【序号】、【编号】存在空值,请填写`) return } - //年份 + //年度 if (obj.year && !yearPattern.test(obj.year)) { - error(`第${i + 2}行【年份】填写错误`) + error(`第${i + 2}行【年度】填写错误`) return } //序号 正整数 @@ -216,12 +216,12 @@ const ImportBackModal = props => { //时间 let tValid = judgeTimeValid(obj.receivableDate); if (!tValid) { - error(`第${i + 2}行回款日期错误,请填写yyyy/mm/dd格式`) + error(`第${i + 2}行【回款日期】错误,请填写yyyy/mm/dd格式`) return } let cValid = judgeTimeValid(obj.incomeConfirmdate); if (!cValid) { - error(`第${i + 2}行收入确认时间错误,请填写yyyy/mm/dd格式`) + error(`第${i + 2}行【收入确认时间】错误,请填写yyyy/mm/dd格式`) return } postData.push(obj); From 603d93af6358e621febe20fc1f83bb97597be755 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 2 Dec 2022 16:49:20 +0800 Subject: [PATCH 7/8] =?UTF-8?q?(*)=E6=8A=A5=E8=A1=A8=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20=E4=BF=AE=E6=94=B9=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/report/achievement.js | 12 ++++++------ api/app/lib/controllers/report/index.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/app/lib/controllers/report/achievement.js b/api/app/lib/controllers/report/achievement.js index a2acf0d..8cfedb1 100644 --- a/api/app/lib/controllers/report/achievement.js +++ b/api/app/lib/controllers/report/achievement.js @@ -12,7 +12,7 @@ async function getReceivedDetail(ctx) { } let findOption = { where: where, - order: [['id', 'DESC']] + order: [['id', 'ASC']] } if (!toExport) {//非导出时考虑分页 if (limit) { @@ -132,7 +132,7 @@ async function getAchievementDetail(ctx) { } let findOption = { where: where, - order: [['id', 'DESC']] + order: [['id', 'ASC']] } if (!toExport) {//非导出时考虑分页 if (limit) { @@ -349,7 +349,7 @@ async function getContractDetail(ctx) { where: where, offset: Number(page) * Number(limit), limit: Number(limit), - order: [['id', 'DESC']] + order: [['id', 'ASC']] }); ctx.status = 200 ctx.body = contractDetail; @@ -376,7 +376,7 @@ async function getInvoicingDetail(ctx) { where: where, offset: Number(page) * Number(limit), limit: Number(limit), - order: [['id', 'DESC']] + order: [['id', 'ASC']] }); ctx.status = 200 ctx.body = invoiceDetail; @@ -394,7 +394,7 @@ async function exportContractDetail(ctx) { try { const { models } = ctx.fs.dc; let exportData = await models.ContractDetail.findAll({ - order: [['id', 'DESC']] + order: [['id', 'ASC']] }); const { utils: { simpleExcelDown, contractDetailsColumnKeys } } = ctx.app.fs; let header = []; @@ -423,7 +423,7 @@ async function exportInvoicingDetail(ctx) { try { const { models } = ctx.fs.dc; let exportData = await models.InvoiceDetail.findAll({ - order: [['id', 'DESC']] + order: [['id', 'ASC']] }); const { utils: { simpleExcelDown, invoicingDetailsColumnKeys } } = ctx.app.fs; let header = []; diff --git a/api/app/lib/controllers/report/index.js b/api/app/lib/controllers/report/index.js index 460b1cf..ac36f7c 100644 --- a/api/app/lib/controllers/report/index.js +++ b/api/app/lib/controllers/report/index.js @@ -58,7 +58,7 @@ async function getSalersReport(ctx) { const salersRes = await clickHouse.hr.query(` SELECT * from sales_distribution as sales ${innerSelectQuery} - order by id desc + order by id asc ${!toExport && limit ? `LIMIT ${limit}` : ''} ${!toExport && limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} `).toPromise() From ea7772d573fd563f42693d45326af215c4da9146 Mon Sep 17 00:00:00 2001 From: zhangminghua Date: Fri, 2 Dec 2022 17:09:05 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=9A=82=E4=BA=A4=E5=90=88=E5=90=8C?= =?UTF-8?q?=E6=98=8E=E7=BB=86=E5=AF=BC=E5=85=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/actions/achievement-report.js | 6 +- .../performanceReport/contractDetails.jsx | 5 +- .../importContractDetailsModal.js | 94 ++++++++++++++++--- 3 files changed, 90 insertions(+), 15 deletions(-) diff --git a/web/client/src/sections/business/actions/achievement-report.js b/web/client/src/sections/business/actions/achievement-report.js index 66c27f3..6f570da 100644 --- a/web/client/src/sections/business/actions/achievement-report.js +++ b/web/client/src/sections/business/actions/achievement-report.js @@ -29,10 +29,11 @@ export function getAchievementDetail(query) { } //回款明细 编号集合 -export function getReceivedNumbers() { +export function getReceivedNumbers(query = {}) { return (dispatch) => basicAction({ type: "get", dispatch: dispatch, + query: query, actionType: "GET_RECEIVED_DETAIL_NUMBERS", url: `${ApiTable.getReceivedNumbers}`, msg: { option: "查询回款明细编号集合" }, @@ -40,10 +41,11 @@ export function getReceivedNumbers() { }); } //导入回款明细 -export function importBackDetails(values) { +export function importBackDetails(values, query = {}) { return dispatch => basicAction({ type: 'post', dispatch: dispatch, + query: query, actionType: 'RECEIVED_DETAIL_BULK_ADD', url: ApiTable.importBackDetails, data: values, diff --git a/web/client/src/sections/business/containers/performanceReport/contractDetails.jsx b/web/client/src/sections/business/containers/performanceReport/contractDetails.jsx index 3e9bc77..3556a56 100644 --- a/web/client/src/sections/business/containers/performanceReport/contractDetails.jsx +++ b/web/client/src/sections/business/containers/performanceReport/contractDetails.jsx @@ -34,8 +34,8 @@ const ContractDetails = (props) => { default: columns.push({ title: columnKeys[key], dataIndex: key, key: key, - render: (text, record) => text === 0 ? text : text ? text : '—', - width: 32 + columnKeys[key].length * 16 + render: (text, record) => text === 0 ? text : text ? text : '-', + width: 32 + columnKeys[key].length * 32 }); break; } @@ -218,6 +218,7 @@ const ContractDetails = (props) => { importModalV ? { setImportModalV(false); + getContractDetailData(); }} /> : '' } { diff --git a/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js b/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js index a3b22c9..0dab5c7 100644 --- a/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js +++ b/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js @@ -4,27 +4,40 @@ import { connect } from 'react-redux'; import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; import { IconUpload } from '@douyinfe/semi-icons'; import XLSX from 'xlsx'; +import moment from 'moment'; import { contractDetailsColumnKeys } from '../../constants/index'; +const ColumnDateKey = ['applyDate', 'recConDate', 'acceptanceDate', 'backConfirmDate']; +const ColumnDateName = ['申请日期', '收到合同日期', '验收日期', '收入确认时间']; //下载模板和上传文件读取 const ImportContractDetailsModal = props => { const { dispatch, actions, onCancel } = props; - const { humanAffairs } = actions; + const { businessManagement } = actions; const [msg, setMsg] = useState(''); const [loading, setLoading] = useState(''); const [postData, setPostData] = useState([]); + const [uploadAble, setUploadAble] = useState(false); + const [allNumbers, setAllNumbers] = useState([]); //初始化 useEffect(() => { + //查询明细表已存在编号数据接口通用 + dispatch(businessManagement.getReceivedNumbers({ tableModel: 'ContractDetail' })).then(r => { + if (r.success) { + setUploadAble(true); + setAllNumbers(r.payload.data); + } + }) }, []); const confirm = () => { if (postData.length) { setLoading(true) - // dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => { - // if (res.success) { - // onCancel() - // } - // setLoading(false) - // }) + //导入明细接口通用 + dispatch(businessManagement.importBackDetails(postData, { tableModel: 'ContractDetail' })).then(res => { + if (res.success) { + onCancel() + } + setLoading(false) + }) } else { Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) } @@ -94,9 +107,29 @@ const ImportContractDetailsModal = props => { }) } + const judgeNullTime = (v) => { + //注意的点:xlsx将excel中的时间内容解析后,会小一天 + //如2020/8/1,xlsx会解析成 Fri Jul 31 2020 23:59:17 GMT+0800 小了43秒 + let a = new Date(v); + a.setTime(a.getTime() + 43 * 1000); + return v ? a : null; + } - const judgeNull = (value) => { - return value ? String(value).trim().replace(/\s*/g, "") : null; + const judgeTimeValid = (time) => { + let valid = true; + if (!time) { + return valid;//可以不填 + } + const ymd = /^((19|20)[0-9]{2})[\/\-]((0[1-9])|(1[0-2]))[\/\-]((0[1-9])|((1|2)[0-9])|(3[0-1]))$/;//年月日 + if (time instanceof Date) { + let timeStr = moment(time).format('YYYY/MM/DD'); + if (!ymd.test(timeStr)) { + valid = false; + } + } else { + valid = false; + } + return valid; } return ( @@ -137,12 +170,51 @@ const ImportContractDetailsModal = props => { return } let postData = []; + let yearPattern = /^(19|20)\d{2}$/;//1900-2099年 + let zzsPattern = /^[+]{0,1}(\d+)$/;//正整数 for (let i = 0; i < res.length; i++) { let d = res[i]; let obj = {}; Object.keys(contractDetailsColumnKeys).map(key => { - obj[key] = d[contractDetailsColumnKeys[key]] || ''; + //四个日期验证“申请日期”、“收到合同日期”、“验收日期”、“收入确认时间” + if (ColumnDateKey.indexOf(key) != -1) {//两个时间 + obj[key] = judgeNullTime(d[contractDetailsColumnKeys[key]]); + } else { + obj[key] = d[contractDetailsColumnKeys[key]] || null; + } }) + //年度 序号 编号必填 + if (!obj.year || !obj.serialNo || !obj.number) { + error(`第${i + 2}行【年度】、【序号】、【编号】存在空值,请填写`) + return + } + //年度 + if (obj.year && !yearPattern.test(obj.year)) { + error(`第${i + 2}行【年度】填写错误`) + return + } + //序号 正整数 + if (obj.serialNo && !zzsPattern.test(obj.serialNo)) { + error(`第${i + 2}行【序号】填写错误,需要为非负整数`) + return + } + let exist = allNumbers.find(m => m.number == obj.number);//数据库中 已有该编号 + if (exist) { + error(`第${i + 2}行的【编号】在系统中已存在`) + return + } + if (postData.some(p => p.number == obj.number)) {//编号 唯一 + error(`第${i + 2}行【编号】重复,请更改后重新上传`) + return + } + + for (let k = 0; k < ColumnDateKey.length; k++) { + let cValid = judgeTimeValid(obj[ColumnDateKey[k]]); + if (!cValid) { + error(`第${i + 2}行【${ColumnDateName[k]}】错误,请填写yyyy/mm/dd格式`) + return + } + } postData.push(obj); } setPostData(postData) @@ -151,7 +223,7 @@ const ImportContractDetailsModal = props => { onSuccess({ message: msg }) }) }}> -