Просмотр исходного кода

feat: 待办事项/工作台,新增“合同管理”待办

caipin 19 часов назад
Родитель
Сommit
f59d200333

+ 50 - 1
app/controller/dashboard_controller.js

@@ -48,6 +48,10 @@ module.exports = app => {
             const allAuditCostStageBook = await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId);
             const allAuditCostStageBook = await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId);
             const allAuditCostStageAnalysis = await ctx.service.costStageAudit.getAuditStage('analysis', ctx.session.sessionUser.accountId);
             const allAuditCostStageAnalysis = await ctx.service.costStageAudit.getAuditStage('analysis', ctx.session.sessionUser.accountId);
             const allAuditCostStageDuty = await ctx.service.costStageAudit.getAuditStage('duty', ctx.session.sessionUser.accountId);
             const allAuditCostStageDuty = await ctx.service.costStageAudit.getAuditStage('duty', ctx.session.sessionUser.accountId);
+            // 获取所有待审批的合同列表
+            const allAuditContracts = await ctx.service.contractSpAudit.getAuditContract(ctx.session.sessionUser.accountId);
+            // 获取所有待审批的合同支付(回款)列表
+            const allAuditContractPays = await ctx.service.contractSpAudit.getAuditContractPay(ctx.session.sessionUser.accountId);
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const auditShenpiTenders = await ctx.service.ledgerAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiTenders = await ctx.service.ledgerAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiStages = await ctx.service.stageAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiStages = await ctx.service.stageAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
@@ -68,6 +72,8 @@ module.exports = app => {
             const auditShenpiCostStageBook = await ctx.service.costStageAudit.getDonesByAudit('book', ctx.session.sessionUser.accountId);
             const auditShenpiCostStageBook = await ctx.service.costStageAudit.getDonesByAudit('book', ctx.session.sessionUser.accountId);
             const auditShenpiCostStageAnalysis = await ctx.service.costStageAudit.getDonesByAudit('analysis', ctx.session.sessionUser.accountId);
             const auditShenpiCostStageAnalysis = await ctx.service.costStageAudit.getDonesByAudit('analysis', ctx.session.sessionUser.accountId);
             const auditShenpiCostStageDuty = await ctx.service.costStageAudit.getDonesByAudit('duty', ctx.session.sessionUser.accountId);
             const auditShenpiCostStageDuty = await ctx.service.costStageAudit.getDonesByAudit('duty', ctx.session.sessionUser.accountId);
+            const auditShenpiContracts = await ctx.service.contractSpAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
+            const auditShenpiContractPays = await ctx.service.contractSpAudit.getDonesByAuditPay(ctx.session.sessionUser.accountId);
             const dashboardStatus = {
             const dashboardStatus = {
                 all: 0,
                 all: 0,
                 dashboard: 0,
                 dashboard: 0,
@@ -93,6 +99,9 @@ module.exports = app => {
                     costStageBook: 0,
                     costStageBook: 0,
                     costStageAnalysis: 0,
                     costStageAnalysis: 0,
                     costStageDuty: 0,
                     costStageDuty: 0,
+                    contract: 0,
+                    contractPay: 0,
+                    contractReceipt: 0,
                 },
                 },
             };
             };
             let noticeList = [];
             let noticeList = [];
@@ -138,6 +147,13 @@ module.exports = app => {
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageAnalysis, 'shenpi_type', 'costStageAnalysis'));
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageAnalysis, 'shenpi_type', 'costStageAnalysis'));
                 const spCostStageDuty = subProject.page_show.cost ? ctx.helper._.filter(auditShenpiCostStageDuty, { spid: subProject.id }) : [];
                 const spCostStageDuty = subProject.page_show.cost ? ctx.helper._.filter(auditShenpiCostStageDuty, { spid: subProject.id }) : [];
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageDuty, 'shenpi_type', 'costStageDuty'));
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageDuty, 'shenpi_type', 'costStageDuty'));
+                const spContracts = subProject.page_show.openContract ? ctx.helper._.filter(auditShenpiContracts, { spid: subProject.id }) : [];
+                noticeList.push(...ctx.helper.addKeyValue4ObjArray(spContracts, 'shenpi_type', 'contract'));
+                const spContractPays = (subProject.page_show.openContractTenderShenpi || subProject.page_show.openContractSubProjectShenpi) ? ctx.helper._.filter(auditShenpiContractPays, { spid: subProject.id }) : [];
+                for (const pay of spContractPays) {
+                    pay.shenpi_type = pay.contract_type === 2 ? 'contractReceipt' : 'contractPay';
+                }
+                noticeList.push(...spContractPays);
             }
             }
             const noticeDayList = [];
             const noticeDayList = [];
             noticeList = ctx.helper._.orderBy(noticeList, ['shenpi_time'], ['desc']);
             noticeList = ctx.helper._.orderBy(noticeList, ['shenpi_time'], ['desc']);
@@ -187,6 +203,20 @@ module.exports = app => {
             dashboardShenpis.push(...auditCostStageAnalysis);
             dashboardShenpis.push(...auditCostStageAnalysis);
             const auditCostStageDuty = await this.auditSet(ctx, allAuditCostStageDuty, subProjects, dashboardStatus, 'costStageDuty');
             const auditCostStageDuty = await this.auditSet(ctx, allAuditCostStageDuty, subProjects, dashboardStatus, 'costStageDuty');
             dashboardShenpis.push(...auditCostStageDuty);
             dashboardShenpis.push(...auditCostStageDuty);
+
+            // 处理合同审批数据,转换为统一格式
+            const auditContracts = await this.auditSet(ctx, allAuditContracts, subProjects, dashboardStatus, 'contract');
+            dashboardShenpis.push(...auditContracts);
+
+            // 处理合同支付/回款审批数据,转换为统一格式
+            const auditContractPays = await this.auditSet(ctx, allAuditContractPays, subProjects, dashboardStatus, 'contractPay');
+            // 将回款数据的shenpi_type改为contractReceipt
+            for (const pay of auditContractPays) {
+                if (pay.contract_type === 2) {
+                    pay.shenpi_type = 'contractReceipt';
+                }
+            }
+            dashboardShenpis.push(...auditContractPays);
             // console.log(ctx.helper._.orderBy(dashboardShenpis, ['start_audit', 'shenpi_time'], ['desc', 'desc']));
             // console.log(ctx.helper._.orderBy(dashboardShenpis, ['start_audit', 'shenpi_time'], ['desc', 'desc']));
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             // 获取销售人员数据
             // 获取销售人员数据
@@ -346,6 +376,15 @@ module.exports = app => {
                             if (!sp.page_show.cost) closeType = true;
                             if (!sp.page_show.cost) closeType = true;
                             calcTime = t.create_time;
                             calcTime = t.create_time;
                             break;
                             break;
+                        case 'contract':
+                            if (!sp.page_show.openContract) closeType = true;
+                            calcTime = t.begin_time;
+                            break;
+                        case 'contractPay':
+                        case 'contractReceipt':
+                            if (!sp.page_show.openContractTenderShenpi && !sp.page_show.openContractSubProjectShenpi) closeType = true;
+                            calcTime = t.begin_time;
+                            break;
                         default:
                         default:
                             closeType = true;
                             closeType = true;
                     }
                     }
@@ -361,7 +400,7 @@ module.exports = app => {
                             dashboardStatus.early += 1;
                             dashboardStatus.early += 1;
                         }
                         }
                     }
                     }
-                    const calcType = type === 'stageAss' ? 'stage' : type;
+                    const calcType = type === 'stageAss' ? 'stage' : (type === 'contractReceipt' ? 'contractReceipt' : (type === 'contractPay' ? 'contractPay' : type));
                     dashboardStatus.shenpi[calcType] += 1;
                     dashboardStatus.shenpi[calcType] += 1;
                     t.shenpi_time = calcTime;
                     t.shenpi_time = calcTime;
                     t.shenpi_type = type;
                     t.shenpi_type = type;
@@ -399,6 +438,11 @@ module.exports = app => {
             const auditCostStageBook = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditCostStageBook = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditCostStageAnalysis = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('analysis', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditCostStageAnalysis = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('analysis', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditCostStageDuty = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('duty', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditCostStageDuty = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('duty', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            // 获取待审批的合同列表
+            const auditContracts = ctx.subProject.page_show.openContract ? await ctx.service.contractSpAudit.getAuditContract(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            // 获取待审批的合同支付(回款)列表
+            const auditContractPays = (ctx.subProject.page_show.openContractTenderShenpi || ctx.subProject.page_show.openContractSubProjectShenpi) ? await ctx.service.contractSpAudit.getAuditContractPay(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id, pa.id, ctx.subProject.id);
             const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id, pa.id, ctx.subProject.id);
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
@@ -432,6 +476,7 @@ module.exports = app => {
             if (ctx.subProject.page_show.safeInspection) shenpi_count.push({ count: await ctx.service.safeInspectionAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全巡检' });
             if (ctx.subProject.page_show.safeInspection) shenpi_count.push({ count: await ctx.service.safeInspectionAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全巡检' });
             if (ctx.subProject.page_show.safePayment) shenpi_count.push({ count: await ctx.service.safeStageAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全计量' });
             if (ctx.subProject.page_show.safePayment) shenpi_count.push({ count: await ctx.service.safeStageAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全计量' });
             if (ctx.subProject.page_show.phasePay) shenpi_count.push({ count: await ctx.service.phasePayAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '合同支付' });
             if (ctx.subProject.page_show.phasePay) shenpi_count.push({ count: await ctx.service.phasePayAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '合同支付' });
+            if (ctx.subProject.page_show.openContract) shenpi_count.push({ count: await ctx.service.contractSpAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '合同审批' });
             if (ctx.subProject.page_show.cost) {
             if (ctx.subProject.page_show.cost) {
                 shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('ledger', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '成本报审' });
                 shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('ledger', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '成本报审' });
                 shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '财务账面' });
                 shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '财务账面' });
@@ -459,6 +504,7 @@ module.exports = app => {
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('analysis', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('analysis', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('duty', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('duty', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
+                ctx.subProject.page_show.openContract ? await ctx.service.contractSpAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
             ];
             ];
             const last_time = ctx.app._.max(shenpi_lastime);
             const last_time = ctx.app._.max(shenpi_lastime);
             // console.log(ctx.app._.max(shenpi_lastime), ctx.helper.calcDayNum(last_time));
             // console.log(ctx.app._.max(shenpi_lastime), ctx.helper.calcDayNum(last_time));
@@ -483,6 +529,8 @@ module.exports = app => {
                 auditCostStageBook,
                 auditCostStageBook,
                 auditCostStageAnalysis,
                 auditCostStageAnalysis,
                 auditCostStageDuty,
                 auditCostStageDuty,
+                auditContracts,
+                auditContractPays,
                 shenpi_count,
                 shenpi_count,
                 total_count,
                 total_count,
                 last_day: ctx.helper.calcDayNum(last_time),
                 last_day: ctx.helper.calcDayNum(last_time),
@@ -502,6 +550,7 @@ module.exports = app => {
                 acSafeStage: auditConst.safeStage,
                 acSafeStage: auditConst.safeStage,
                 acPhasePay: auditConst.phasePay,
                 acPhasePay: auditConst.phasePay,
                 acCostStage: auditConst.costStage,
                 acCostStage: auditConst.costStage,
+                acContract: auditConst.contract,
                 noticeList,
                 noticeList,
                 pushType: auditConst.pushType,
                 pushType: auditConst.pushType,
                 projectData,
                 projectData,

+ 15 - 0
app/public/js/contract_detail.js

@@ -1,5 +1,20 @@
 const copyBlockTag = 'zh.calc.copyBlock';
 const copyBlockTag = 'zh.calc.copyBlock';
 $(document).ready(function() {
 $(document).ready(function() {
+    // 检查URL参数,如果tab=pay则自动切换到合同支付/回款选项卡
+    const urlParams = new URLSearchParams(window.location.search);
+    if (urlParams.get('tab') === 'pay') {
+        // 延迟执行,确保DOM完全加载
+        setTimeout(function() {
+            // 移除所有active类
+            $('.bc-bar .nav li a').removeClass('active');
+            $('.tab-content .tab-pane').removeClass('active');
+            
+            // 激活htpay选项卡
+            $('.bc-bar .nav li a[href="#htpay"]').addClass('active');
+            $('#htpay').addClass('active');
+        }, 100);
+    }
+    
     let stdXmj;
     let stdXmj;
     const ckBillsSpread = '/contract/' + window.location.pathname.split('/')[2] + '/' + contractConst.typeMap[contract_type] + '/detail/contract-billsSelect';
     const ckBillsSpread = '/contract/' + window.location.pathname.split('/')[2] + '/' + contractConst.typeMap[contract_type] + '/detail/contract-billsSelect';
     autoFlashHeight();
     autoFlashHeight();

Разница между файлами не показана из-за своего большого размера
+ 160 - 16
app/service/contract_sp_audit.js


Разница между файлами не показана из-за своего большого размера
+ 53 - 1
app/view/dashboard/index.ejs


+ 66 - 0
app/view/dashboard/workspace.ejs

@@ -157,6 +157,9 @@
                                             <% if (dashboardStatus.shenpi.costStageDuty !== 0) { %>
                                             <% if (dashboardStatus.shenpi.costStageDuty !== 0) { %>
                                             <option value="costStageDuty">责任成本(<%- dashboardStatus.shenpi.costStageDuty %>)</option>
                                             <option value="costStageDuty">责任成本(<%- dashboardStatus.shenpi.costStageDuty %>)</option>
                                             <% } %>
                                             <% } %>
+                                            <% if (dashboardStatus.shenpi.contract !== 0 || dashboardStatus.shenpi.contractPay !== 0 || dashboardStatus.shenpi.contractReceipt !== 0) { %>
+                                                <option value="contract">合同管理(<%- (dashboardStatus.shenpi.contract || 0) + (dashboardStatus.shenpi.contractPay || 0) + (dashboardStatus.shenpi.contractReceipt || 0) %>)</option>
+                                            <% } %>
                                         </select>
                                         </select>
                                     </div>
                                     </div>
                                 </div>
                                 </div>
@@ -528,6 +531,57 @@
                                                             <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
                                                             <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
                                                             <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/duty/1/stage" class="btn btn-sm btn-table <%- (am.audit_order === 0 ? 'btn-outline-warning text-warning' : 'btn-outline-primary') %>" role="button"><%- (am.audit_order === 0 ? '重新上报' : '审批')%></a></td>
                                                             <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/duty/1/stage" class="btn btn-sm btn-table <%- (am.audit_order === 0 ? 'btn-outline-warning text-warning' : 'btn-outline-primary') %>" role="button"><%- (am.audit_order === 0 ? '重新上报' : '审批')%></a></td>
                                                         </tr>
                                                         </tr>
+                                                    <% } else if (db.shenpi_type === 'contract') { %>
+                                                        <% const ct = db; %>
+                                                        <tr data-type="contract">
+                                                            <% if (ct.start_audit === 2) { %><td class="text-center text-danger"><i class="fa fa-exclamation-triangle"></i></td><% } else if (ct.start_audit === 1) { %><td class="text-center text-warning"><i class="fa fa-bell"></i></td><% } else { %><td></td><% } %>
+                                                            <td><span class="badge text-width" style="background-color: #e3f2fd; color: #1976d2;">合同审批</span></td>
+                                                            <td><a href="/sp/<%- ct.spid %>/dashboard"><%- ct.sp_name || '项目合同' %></a></td>
+                                                            <td>
+                                                                <% if (ct.is_project_contract) { %>
+                                                                    <a href="/contract/<%- ct.id %>"><%- ct.name %></a>
+                                                                <% } else { %>
+                                                                    <a href="/tender/<%- ct.tid %>"><%- ct.tender_name %></a> - <a href="/contract/<%- ct.id %>"><%- ct.name %></a>
+                                                                <% } %>
+                                                            </td>
+                                                            <td><%- ct.status_text %></td>
+                                                            <td><%- (ct.begin_time ? ctx.moment(ct.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/contract/<%- ct.id %>/audit" class="btn btn-outline-primary btn-sm btn-table" role="button">审批</a></td>
+                                                        </tr>
+                                                    <% } else if (db.shenpi_type === 'contractPay') { %>
+                                                        <% const cp = db; %>
+                                                        <tr data-type="contract">
+                                                            <% if (cp.start_audit === 2) { %><td class="text-center text-danger"><i class="fa fa-exclamation-triangle"></i></td><% } else if (cp.start_audit === 1) { %><td class="text-center text-warning"><i class="fa fa-bell"></i></td><% } else { %><td></td><% } %>
+                                                            <td><span class="badge text-width" style="background-color: #fff3e0; color: #f57c00;">合同支付</span></td>
+                                                            <td><a href="/sp/<%- cp.spid %>/dashboard"><%- cp.sp_name %></a></td>
+                                                            <td>
+                                                                <% if (cp.is_project_contract) { %>
+                                                                    <a href="/contract/<%- cp.cid %>"><%- cp.contract_name %></a> - 第<%- cp.times %>期
+                                                                <% } else { %>
+                                                                    <a href="/tender/<%- cp.tid %>"><%- cp.tender_name %></a> - <a href="/contract/<%- cp.cid %>"><%- cp.contract_name %></a> - 第<%- cp.times %>期
+                                                                <% } %>
+                                                            </td>
+                                                            <td>支付</td>
+                                                            <td><%- (cp.begin_time ? ctx.moment(cp.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/contract/<%- cp.cid %>/pay/<%- cp.id %>/audit" class="btn btn-outline-primary btn-sm btn-table" role="button">审批</a></td>
+                                                        </tr>
+                                                    <% } else if (db.shenpi_type === 'contractReceipt') { %>
+                                                        <% const cr = db; %>
+                                                        <tr data-type="contract">
+                                                            <% if (cr.start_audit === 2) { %><td class="text-center text-danger"><i class="fa fa-exclamation-triangle"></i></td><% } else if (cr.start_audit === 1) { %><td class="text-center text-warning"><i class="fa fa-bell"></i></td><% } else { %><td></td><% } %>
+                                                            <td><span class="badge text-width" style="background-color: #e8f5e9; color: #388e3c;">合同回款</span></td>
+                                                            <td><a href="/sp/<%- cr.spid %>/dashboard"><%- cr.sp_name %></a></td>
+                                                            <td>
+                                                                <% if (cr.is_project_contract) { %>
+                                                                    <a href="/contract/<%- cr.cid %>"><%- cr.contract_name %></a> - 第<%- cr.times %>期
+                                                                <% } else { %>
+                                                                    <a href="/tender/<%- cr.tid %>"><%- cr.tender_name %></a> - <a href="/contract/<%- cr.cid %>"><%- cr.contract_name %></a> - 第<%- cr.times %>期
+                                                                <% } %>
+                                                            </td>
+                                                            <td>回款</td>
+                                                            <td><%- (cr.begin_time ? ctx.moment(cr.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/contract/<%- cr.cid %>/pay/<%- cr.id %>/audit" class="btn btn-outline-primary btn-sm btn-table" role="button">审批</a></td>
+                                                        </tr>
                                                     <% } %>
                                                     <% } %>
                                                 <% } %>
                                                 <% } %>
                                                 </tbody>
                                                 </tbody>
@@ -987,6 +1041,18 @@
                                         html.push(`<li class="list-group-item">
                                         html.push(`<li class="list-group-item">
                                             <span class="${acCostStage.auditStringClass[n.audit_status]}">${acCostStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/cost/tender/${n.id}/duty/1/stage" target="_blank">${n.name}</a> 责任成本 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
                                             <span class="${acCostStage.auditStringClass[n.audit_status]}">${acCostStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/cost/tender/${n.id}/duty/1/stage" target="_blank">${n.name}</a> 责任成本 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
                                         break;
                                         break;
+                                    case 'contract':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="text-warning">审批中</span> <a href="/contract/${n.id}/audit" target="_blank">${n.name}</a> 合同审批<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
+                                    case 'contractPay':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="text-warning">审批中</span> <a href="/contract/${n.cid}/pay/${n.id}/audit" target="_blank">${n.contract_name || n.tender_name}</a> 合同支付 第${n.times}期<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
+                                    case 'contractReceipt':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="text-warning">审批中</span> <a href="/contract/${n.cid}/pay/${n.id}/audit" target="_blank">${n.contract_name || n.tender_name}</a> 合同回款 第${n.times}期<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
                                     default: continue;
                                     default: continue;
                                 }
                                 }
                             }
                             }

+ 22 - 0
deploy/Dockerfile

@@ -0,0 +1,22 @@
+FROM node:12
+
+# 设置工作目录
+WORKDIR /app/calc
+
+# 复制 package.json 和 package-lock.json(如果存在)以利用 Docker 缓存
+COPY package*.json ./
+
+# 安装依赖,使用淘宝镜像加速
+RUN npm install --registry=https://registry.npmmirror.com
+
+# 复制所有源代码
+COPY . .
+
+# 暴露端口 7005(与 dev-docker 命令一致)
+EXPOSE 7005
+
+# 设置环境变量为 weapp(用于 weapp 测试环境)
+ENV EGG_SERVER_ENV=weapp
+
+# 启动应用
+CMD ["npm", "run", "dev-weapp"]

+ 10 - 0
deploy/build.sh

@@ -0,0 +1,10 @@
+docker buildx build --platform linux/amd64 \
+  --load \
+  -t registry.cn-shenzhen.aliyuncs.com/prod_cp/calculation_weapp_dev:latest \
+  -f deploy/Dockerfile .
+
+  docker push registry.cn-shenzhen.aliyuncs.com/prod_cp/calculation_weapp_dev:latest
+
+
+docker cp ./config.weapp.js 5fb7277c5aa9:/app/calc/config/config.weapp.js
+  

+ 42 - 0
deploy/cal.conf

@@ -0,0 +1,42 @@
+upstream calculation_weapp {
+    server 127.0.0.1:7005;
+}
+
+server {
+    listen 80;
+    server_name jluat.cal.com;
+
+    charset utf-8;
+
+    access_log /var/log/nginx/jluat_cal_access.log;
+    error_log /var/log/nginx/jluat_cal_error.log;
+
+    client_max_body_size 100m;
+
+    proxy_connect_timeout 60s;
+    proxy_send_timeout 60s;
+    proxy_read_timeout 60s;
+
+    location / {
+        proxy_pass http://calculation_weapp;
+        
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        
+        proxy_buffering off;
+        proxy_request_buffering off;
+    }
+
+    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+        proxy_pass http://calculation_weapp;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        
+        expires 30d;
+        add_header Cache-Control "public, immutable";
+    }
+}