Browse Source

奖罚金1.0

MaiXinRong 5 years ago
parent
commit
60ffb4d4ba

+ 15 - 2
app/controller/stage_extra_controller.js

@@ -99,7 +99,13 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async loadBonus (ctx) {
-
+            try {
+                const data = await ctx.service.stageBonus.getEndStageData(ctx.stage.order);
+                ctx.body = {err: 0, msg: '', data: data};
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '获取甲供材料数据失败,请刷新');
+            }
         }
 
         /**
@@ -108,7 +114,14 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async updateBonus (ctx) {
-
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const result = await ctx.service.stageBonus.updateDatas(data);
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '提交甲供材料数据失败,请重试');
+            }
         }
 
         /**

+ 365 - 9
app/public/js/se_bonus.js

@@ -8,16 +8,23 @@
  * @version
  */
 
+const isPre = function (data) {
+    return data.sid !== stageId;
+};
 const spreadSetting = { 
     cols: [
-        {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 185, formatter: '@'},
-        {title: '金额', colSpan: '1', rowSpan: '1', field: 'e_type', hAlign: 1, width: 80, formatter: '@'},
-        {title: '本期金额', colSpan: '1', rowSpan: '1', field: 'quantity', hAlign: 2, width: 100, type: 'Number'},
-        {title: '截止本期金额', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 100, type: 'Number', readOnly: true},
-        {title: '时间', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 100, type: 'Number'},
-        {title: '编号', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 100, type: 'Number'},
-        {title: '依据材料证明', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 100, type: 'Number'},
-        {title: '备注', colSpan: '1', rowSpan: '1', field: 'memo', hAlign: 0, width: 150, formatter: '@', cellType: 'ellipsisAutoTip'}
+        {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 235, formatter: '@', readOnly: isPre, },
+        {title: '金额', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 100, type: 'Number', readOnly: isPre, },
+        {title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 1, width: 150, formatter: '@', readOnly: isPre, },
+        {title: '编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 150, formatter: '@', readOnly: isPre, },
+        {title: '依据材料证明', colSpan: '1', rowSpan: '1', field: 'proof', hAlign: 0, width: 180, formatter: '@', readOnly: isPre, },
+        {
+            title: '计量期', colSpan: '1', rowSpan: '1', field: 'sorder', hAlign: 1, width: 100, formatter: '@',
+            getValue: function (data) {
+                return '第' + data.sorder + '期';
+            }, readOnly: true,
+        },
+        {title: '备注', colSpan: '1', rowSpan: '1', field: 'memo', hAlign: 0, width: 180, formatter: '@', cellType: 'ellipsisAutoTip', readOnly: isPre, }
     ],
     emptyRows: 3,
     headRows: 1,
@@ -30,6 +37,7 @@ $(document).ready(() => {
     autoFlashHeight();
     const bonusSpread = SpreadJsObj.createNewSpread($('#bonus-spread')[0]);
     const bonusSheet = bonusSpread.getActiveSheet();
+    spreadSetting.readOnly = readOnly;
     SpreadJsObj.initSheet(bonusSheet, spreadSetting);
 
     $.subMenu({
@@ -48,5 +56,353 @@ $(document).ready(() => {
             autoFlashHeight();
             bonusSpread.refresh();
         }
-    }); 
+    });
+
+    class Bonus {
+        constructor () {
+            this.data = [];
+        }
+        resortData() {
+            this.data.sort(function (a, b) {
+                return a.sorder !== b.sorder ? a.sorder - b.sorder : a.order - b.order;
+            });
+        }
+        loadDatas(datas) {
+            this.data = datas;
+            this.resortData();
+        }
+        loadUpdateData(updateData) {
+            if (updateData.add) {
+                for (const a of updateData.add) {
+                    this.data.push(a);
+                }
+            }
+            if (updateData.update) {
+                for (const u of updateData.update) {
+                    const d = this.data.find(function (x) {
+                        return u.id === x.id;
+                    });
+                    if (d) {
+                        _.assign(d, u);
+                    } else {
+                        this.data.push(d);
+                    }
+                }
+            }
+            if (updateData.del) {
+                _.remove(this.data, function (d) {
+                    return updateData.del.indexOf(d.id) >= 0;
+                });
+            }
+            this.resortData();
+        }
+        getCurStageNewOrder() {
+            const cur = this.data.filter(function (x) {
+                return x.sid === stageId;
+            });
+            return cur && cur.length > 0 ? cur.length + 1 : 1;
+        }
+        checkCurFirst(bonusData) {
+            const cur = this.data.filter(function (x) {
+                return x.sid === stageId;
+            });
+            return cur.indexOf(bonusData) === 0;
+        }
+        checkCurLast(bonusData) {
+            const cur = this.data.filter(function (x) {
+                return x.sid === stageId;
+            });
+            return cur.indexOf(bonusData) === cur.length - 1;
+        }
+    }
+    const bonusObj = new Bonus();
+
+    postData(window.location.pathname + '/load', null, function (result) {
+        bonusObj.loadDatas(result);
+        SpreadJsObj.loadSheetData(bonusSheet, SpreadJsObj.DataType.Data, bonusObj.data);
+    });
+
+    if (!readOnly) {
+        const bonusOprObj = {
+            /**
+             * 删除按钮响应事件
+             * @param sheet
+             */
+            deletePress: function (sheet) {
+                if (!sheet.zh_setting || readOnly) return;
+
+                const sortData = sheet.zh_data;
+                const datas = [];
+                const sels = sheet.getSelections();
+                if (!sels || !sels[0]) return;
+                const hint = {
+                    name: {type: 'warning', msg: '名称不能为空,如需删除甲供材料请使用右键删除'},
+                };
+
+                for (let iRow = sels[0].row; iRow < sels[0].row + sels[0].rowCount; iRow++) {
+                    let bDel = false;
+                    const node = sortData[iRow];
+                    if (node) {
+                        const data = {id: node.id};
+                        for (let iCol = sels[0].col; iCol < sels[0].col + sels[0].colCount; iCol++) {
+                            const colSetting = sheet.zh_setting.cols[iCol];
+                            if (colSetting.field === 'name') {
+                                toastMessageUniq(hint.name);
+                                return;
+                            }
+                            const style = sheet.getStyle(iRow, iCol);
+                            if (!style.locked) {
+                                const colSetting = sheet.zh_setting.cols[iCol];
+                                data[colSetting.field] = null;
+                                bDel = true;
+                            }
+                        }
+                        if (bDel) {
+                            datas.push(data);
+                        }
+                    }
+                }
+                if (datas.length > 0) {
+                    postData(window.location.pathname + '/update', {updateType: 'update', updateData: datas}, function (result) {
+                        bonusObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(bonusSheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(bonusSheet);
+                    });
+                }
+            },
+            delete: function () {
+                const sheet = bonusSheet;
+                if (!sheet.zh_setting || readOnly) return;
+
+                const sortData = sheet.zh_data;
+                const datas = [];
+                const sels = sheet.getSelections();
+                if (!sels || !sels[0]) return;
+                const hint = {
+                    isOld: {type: 'warning', msg: '本项为往期数据,不可删除'},
+                    invalidDel: {type: 'warning', msg: '本项不是您新增的,只有原报和新增人可删除'},
+                };
+
+                for (let iRow = sels[0].row, iLen = sels[0].row + sels[0].rowCount; iRow < iLen; iRow++) {
+                    const node = sortData[iRow];
+                    if (node.sid !== stageID) {
+                        toastMessageUniq(hint.isOld);
+                        continue;
+                    } else {
+                        if (node.uid !== userID || stageUserId !== userID) {
+                            toastMessageUniq(hint.invalidDel);
+                            continue;
+                        }
+                        datas.push(node.id);
+                    }
+                }
+                if (datas.length > 0) {
+                    postData(window.location.pathname + '/update', {del: datas}, function (result) {
+                        bonusObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(sheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(sheet);
+                    });
+                }
+            },
+            editEnded: function (e, info) {
+                if (!info.sheet.zh_setting || !info.sheet.zh_data) return;
+
+                const node = info.sheet.zh_data[info.row];
+                const col = info.sheet.zh_setting.cols[info.col];
+                const data = {};
+
+                if (node) {
+                    data.update = {};
+                    data.update.id = node.id;
+
+                    const oldValue = node ? node[col.field] : null;
+                    const newValue = trimInvalidChar(info.editingText);
+                    if (oldValue == info.editingText || ((!oldValue || oldValue === '') && (newValue === ''))) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    data.update[col.field] = newValue;
+                } else {
+                    if (col.field !== 'name') {
+                        toastr.warning('新增奖罚金,请先输入名称');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    data.add = {};
+                    data.add.order = bonusObj.getCurStageNewOrder();
+                    data.add.name = trimInvalidChar(info.editingText);
+                }
+
+                postData(window.location.pathname + '/update', data, function (result) {
+                    bonusObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                });
+            },
+            clipboardPasting(e, info) {
+                const setting = info.sheet.zh_setting, sortData = info.sheet.zh_data;
+                info.cancel = true;
+
+                if (!setting || !sortData) return;
+                const pasteData = info.pasteData.html
+                    ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
+                    : (info.pasteData.text === ''
+                        ? SpreadJsObj.Clipboard.getAnalysisPasteText()
+                        : SpreadJsObj.analysisPasteText(info.pasteData.text));
+                const hint = {
+                    name: {type: 'warning', msg: '奖罚金名称不可为空,已过滤'},
+                    tp: {type: 'warning', msg: '输入的 金额 非法,已过滤'},
+                };
+
+                const uDatas = [], iDatas = [], maxOrder = bonusObj.getCurStageNewOrder();
+                for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                    const curRow = info.cellRange.row + iRow;
+                    const node = sortData[curRow];
+
+                    let bPaste = false;
+                    const data = {};
+                    for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
+                        const curCol = info.cellRange.col + iCol;
+                        const colSetting = setting.cols[curCol];
+                        const value = trimInvalidChar(pasteData[iRow][iCol]);
+
+                        if (colSetting.field === 'name' && (!value || value === '')) {
+                            toastMessageUniq(hint.name);
+                            break;
+                        }
+                        if (colSetting.type === 'Number') {
+                            const num = _.toNumber(value);
+                            if (num) {
+                                data[colSetting.field] = num;
+                                bPaste = true;
+                            }
+                        } else {
+                            data[colSetting.field] = value;
+                            bPaste = true;
+                        }
+                    }
+                    if (bPaste) {
+                        if (node) {
+                            data.id = node.id;
+                            uDatas.push(data);
+                        } else {
+                            data.order = maxOrder + iRow;
+                            iDatas.push(data);
+                        }
+                    }
+                }
+                const updateData = {};
+                if (uDatas.length > 0) updateData.update = uDatas;
+                if (iDatas.length > 0) updateData.add = iDatas;
+                if (uDatas.length > 0 || iDatas.length > 0) {
+                    postData(window.location.pathname + '/update', updateData, function (result) {
+                        bonusObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(info.sheet);
+                    });
+                } else {
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }
+            },
+            upMove: function () {
+                const sheet = bonusSheet;
+                const sels = sheet.getSelections(), sortData = sheet.zh_data;
+                const node = sortData[sels[0].row];
+                const preNode = sortData[sels[0].row - 1];
+                const data = [
+                    {id: node.id, order: preNode.order},
+                    {id: preNode.id, order: node.order}
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    bonusObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(sheet, [sels[0].row, sels[0].row - 1]);
+                    sheet.setSelection(sels[0].row - 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            },
+            downMove: function () {
+                const sheet = bonusSheet;
+                const sels = sheet.getSelections(), sortData = sheet.zh_data;
+                const node = sortData[sels[0].row];
+                const nextNode = sortData[sels[0].row + 1];
+                const data = [
+                    {id: node.id, order: nextNode.order},
+                    {id: nextNode.id, order: node.order}
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    bonusObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(sheet, [sels[0].row, sels[0].row + 1]);
+                    sheet.setSelection(sels[0].row + 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            }
+        };
+        bonusSheet.bind(spreadNS.Events.EditEnded, bonusOprObj.editEnded);
+        bonusSheet.bind(spreadNS.Events.ClipboardPasting, bonusOprObj.clipboardPasting);
+        SpreadJsObj.addDeleteBind(bonusSpread, bonusOprObj.deletePress);
+        $.contextMenu({
+            selector: '#bonus-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, bonusSpread);
+                return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+            },
+            items: {
+                del: {
+                    name: '删除',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        bonusOprObj.delete();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = bonusSheet.getSelections();
+                        if (!sels || !sels[0]) return true;
+
+                        const row = sels[0].row;
+                        const node = bonusObj.data[row];
+                        return node === undefined || node === null || node.sid !== stageId;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                sprDel: '------------',
+                upMove: {
+                    name: '上移',
+                    icon: 'fa-arrow-up',
+                    callback: function (key, opt) {
+                        bonusOprObj.upMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = bonusSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row === 0) return true;
+
+                        const row = sels[0].row;
+                        const node = bonusObj.data[row];
+                        return node === undefined || node === null || node.sid !== stageId || bonusObj.checkCurFirst(node);
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                downMove: {
+                    name: '下移',
+                    icon: 'fa-arrow-down',
+                    callback: function (key, opt) {
+                        bonusOprObj.downMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = bonusSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row >= bonusObj.data.length - 1) return true;
+
+                        const row = sels[0].row;
+                        const node = bonusObj.data[row];
+                        return node === undefined || node === null || node.sid !== stageId || bonusObj.checkCurLast(node);
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                }
+            },
+        });
+    }
 });

+ 1 - 1
app/public/js/se_jgcl.js

@@ -57,7 +57,7 @@ $(document).ready(() => {
     });
 
     class Jgcl {
-        constructor (setting) {
+        constructor () {
             this.data = [];
         }
         resortData() {

+ 4 - 0
app/router.js

@@ -200,7 +200,11 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadJgcl');
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateJgcl');
     app.get('/tender/:id/measure/stage/:order/extra/bonus', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.bonus');
+    app.post('/tender/:id/measure/stage/:order/extra/bonus/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadBonus');
+    app.post('/tender/:id/measure/stage/:order/extra/bonus/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateBonus');
     app.get('/tender/:id/measure/stage/:order/extra/other', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.other');
+    app.post('/tender/:id/measure/stage/:order/extra/other/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadOther');
+    app.post('/tender/:id/measure/stage/:order/extra/other/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateOther');
 
     // 报表
     app.get('/tender/:id/report', sessionAuth, tenderCheck, 'reportController.index');

+ 5 - 0
app/service/stage_audit.js

@@ -213,6 +213,7 @@ module.exports = app => {
                 // 复制一份下一审核人数据
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 // 更新期数据
                 const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
                 await transaction.update(this.ctx.service.stage.tableName, {
@@ -266,6 +267,7 @@ module.exports = app => {
                     // 复制一份下一审核人数据
                     await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, nextAudit.order, transaction);
                     await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                    await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                     // 流程至下一审批人
                     await transaction.update(this.tableName, {id: nextAudit.id, status: auditConst.status.checking, begin_time: time});
                     // 同步 期信息
@@ -381,6 +383,7 @@ module.exports = app => {
                 // 复制一份最新数据给原报
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times + 1, 0, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
 
                 // 添加短信通知-审批退回提醒功能
                 const mobile_array = [];
@@ -471,6 +474,7 @@ module.exports = app => {
                 // 复制一份最新数据给下一人
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, audit.order + 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
 
                 // 同步 期信息
                 await transaction.update(this.ctx.service.stage.tableName, {
@@ -679,6 +683,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, audit.order + 1, transaction);
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, audit.order + 2, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
 
                 // 本期结束
                 // 生成截止本期数据 final数据

+ 146 - 0
app/service/stage_bonus.js

@@ -0,0 +1,146 @@
+'use strict';
+
+/**
+ *  奖罚金
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+    class StageBonus extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'stage_bonus';
+        }
+
+        async getStageData(sid) {
+            const data = await this.getAllDataByCondition({where: { sid: sid }});
+            return data;
+        }
+
+        async getPreStageData(sorder) {
+            const sql = 'SELECT * From ' + this.tableName + ' WHERE sorder < ? And tid = ?';
+            const sqlParam = [sorder, this.ctx.tender.id];
+            const data = await this.db.query(sql, sqlParam);
+            return data;
+        }
+
+        async getEndStageData(sorder) {
+            const sql = 'SELECT * From ' + this.tableName + ' WHERE sorder <= ? And tid = ?';
+            const sqlParam = [sorder, this.ctx.tender.id];
+            const data = await this.db.query(sql, sqlParam);
+            return data;
+        }
+
+        async _addDatas(data) {
+            const datas = data instanceof Array ? data : [data];
+            const insertData = [];
+            for (const d of datas) {
+                if (!d.name || !d.order) throw '新增甲供材料,提交的数据错误';
+                const nd = {
+                    id: this.uuid.v4(),
+                    tid: this.ctx.tender.id,
+                    sid: this.ctx.stage.id,
+                    sorder: this.ctx.stage.order,
+                    uid: this.ctx.session.sessionUser.accountId,
+                    create_time: new Date(),
+                    name: d.name,
+                    order: d.order,
+                };
+                nd.tp = d.tp ? this.ctx.helper.round(d.to, this.ctx.tender.info.decimal.tp) : 0;
+                nd.code = d.code ? d.code: null;
+                nd.proof = d.proof ? d.proof : null;
+                nd.real_time = d.real_time ? d.real_time : null;
+                nd.memo = d.memo ? d.memo : null;
+                insertData.push(nd);
+            }
+            await this.db.insert(this.tableName, insertData);
+            return insertData;
+        }
+
+        async _delDatas (data) {
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id')});
+            for (const od of orgDatas) {
+                if (od.sid !== this.ctx.stage.id) throw '非本期新增数据,不可删除';
+            }
+            await this.db.delete(this.tableName, {id: datas});
+            return datas;
+        }
+
+        async _updateDatas (data) {
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id')});
+
+            const uDatas = [];
+            for (const d of datas) {
+                const od = this.ctx.helper._.find(orgDatas, {id: d.id});
+                if (!od) continue;
+
+                const nd = {id: od.id};
+                if (d.name) nd.name = d.name;
+                if (d.tp) nd.tp = this.ctx.helper.round(d.tp, this.ctx.tender.info.decimal.tp);
+                if (d.code) nd.code = d.code;
+                if (d.proof) nd.proof = d.proof;
+                if (d.real_time) nd.real_time = d.real_time;
+                if (d.memo) nd.memo = d.memo;
+                if (d.order) nd.order = d.order;
+                uDatas.push(nd);
+            }
+            if (uDatas.length > 0) {
+                await this.db.updateRows(this.tableName, uDatas);
+                return uDatas;
+            } else {
+                return [];
+            }
+        }
+
+        async updateDatas(data) {
+            const result = {add: [], del: [], update: []};
+            try {
+                if (data.add) {
+                    result.add = await this._addDatas(data.add);
+                }
+                if (data.update) {
+                    result.update = await this._updateDatas(data.update);
+                }
+                if (data.del) {
+                    result.del = await this._delDatas(data.del);
+                }
+                return result;
+            } catch (err) {
+                if (err) result.err = err;
+                return result;
+            }
+        }
+
+        async updateHistory(stage, transaction) {
+            const datas = await this.getStageData(stage.id);
+            if (datas.length === 0) return;
+
+            const filter = {stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder};
+            const updateDatas = [];
+            for (const d of datas) {
+                const history = d.shistory && d.shistory !== '' ? JSON.parse(d.shistory) : [];
+                const his = this.ctx.helper._.find(datas, filter);
+                if (his) {
+                    his.tp = d.tp;
+                } else {
+                    history.push({ stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder, tp: d.tp });
+                }
+                updateDatas.push({ id: d.id, shistory: JSON.stringify(history) });
+            }
+            await transaction.updateRows(this.tableName, updateDatas);
+        }
+    }
+
+    return StageBonus;
+};

+ 1 - 5
app/service/stage_jgcl.js

@@ -8,10 +8,6 @@
  * @version
  */
 
-
-const timesLen = require('../const/audit').stage.timesLen;
-const payConst = require('../const/deal_pay');
-
 module.exports = app => {
     class StageJgcl extends app.BaseService {
         /**
@@ -108,7 +104,7 @@ module.exports = app => {
 
                 const nd = {id: od.id};
                 if (d.name) nd.name = d.name;
-                if (od.sid === od.add_sid) {
+                if (od.pre_used === null || od.pre_used === undefined || od.pre_used === 0) {
                     if (d.unit) nd.unit = d.unit;
                     nd.unit_price = d.unit_price ? this.ctx.helper.round(d.unit_price, info.decimal.up) : od.unit_price;
                 }

+ 6 - 1
app/view/stage_extra/bonus.ejs

@@ -16,4 +16,9 @@
             </div>
         </div>
     </div>
-</div>
+</div>
+<script>
+    const stageId = <%- ctx.stage.id %>;
+    const stageUserId = <%- ctx.stage.user_id %>;
+    const readOnly = <%- ctx.stage.readOnly %>;
+</script>

+ 0 - 2
config/web.js

@@ -373,7 +373,6 @@ const JsFiles = {
                     "/public/js/sub_menu.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
                     "/public/js/se_jgcl.js",
                 ],
                 mergeFile: 'se_jgcl',
@@ -387,7 +386,6 @@ const JsFiles = {
                     "/public/js/sub_menu.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
                     "/public/js/se_bonus.js",
                 ],
                 mergeFile: 'se_bonus',