Quellcode durchsuchen

1. 永久材料相关
2. 报表数据源,变更清单相关数据,新增原数量2

MaiXinRong vor 11 Monaten
Ursprung
Commit
10f1ba851a

+ 47 - 0
app/controller/stage_extra_controller.js

@@ -85,6 +85,53 @@ module.exports = app => {
         }
 
         /**
+         * 永久材料(Get)
+         *
+         * @param {Object} ctx - egg全局变量
+         */
+        async yjcl (ctx) {
+            try {
+                const renderData = {
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.stageExtra.yjcl)
+                };
+                await this.layout('stage_extra/yjcl.ejs', renderData);
+            } catch (err) {
+                ctx.helper.log(err);
+            }
+        }
+
+        /**
+         * 获取永久材料页面数据 (Get)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async loadYjcl (ctx) {
+            try {
+                const data = await ctx.service.stageYjcl.getStageData(ctx.stage);
+                ctx.body = {err: 0, msg: '', data: data};
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '获取永久材料数据失败,请刷新');
+            }
+        }
+
+        /**
+         * 提交永久材料数据 (Ajaz)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async updateYjcl (ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const result = await ctx.service.stageYjcl.updateDatas(data);
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '提交永久材料数据失败,请重试');
+            }
+        }
+
+        /**
          * 奖罚金(Get)
          *
          * @param {Object} ctx - egg全局变量

+ 2 - 0
app/lib/rm/change.js

@@ -61,6 +61,8 @@ class rptMemChange extends RptMemBase {
         for (const d of changeBills) {
             d.o_qty = d.oamount;
             d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+            d.o_qty2 = d.oamount2;
+            d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
             d.c_qty = d.camount;
             d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
             d.s_qty = d.samount ? parseFloat(d.samount) : 0;

+ 439 - 0
app/public/js/se_yjcl.js

@@ -0,0 +1,439 @@
+'use strict';
+
+/**
+ * 期 - 甲供材料
+ *
+ * @author Mai
+ * @date 2020/2/12
+ * @version
+ */
+
+$(document).ready(() => {
+    autoFlashHeight();
+    const spreadSetting = {
+        cols: [
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 100, formatter: '@'},
+            {title: '规格型号', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 100, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '除税单价', colSpan: '1', rowSpan: '2', field: 'ex_tax_up', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '税率', colSpan: '1', rowSpan: '2', field: 'tax', hAlign: 1, width: 50, type: 'Number'},
+            {title: '到场|数量',  colSpan: '2|1', rowSpan: '1|1', field: 'arrive_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额',  colSpan: '|1', rowSpan: '|1', field: 'arrive_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '截止本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '到场信息|到场时间', colSpan: '5|1', rowSpan: '1|1', field: 'arrive_time', hAlign: 1, width: 80, formatter: '@'},
+            {title: '|材料来源', colSpan: '|1', rowSpan: '|1', field: 'source', hAlign: 0, width: 150, formatter: '@', wordWrap: true},
+            {title: '|单据号', colSpan: '|1', rowSpan: '|1', field: 'bills_code', hAlign: 0, width: 100, formatter: '@', wordWrap: true},
+            {title: '|存放位置', colSpan: '|1', rowSpan: '|1', field: 'location', hAlign: 0, width: 80, formatter: '@', wordWrap: true},
+            {title: '|拟用于部位', colSpan: '|1', rowSpan: '|1', field: 'prepare_pos', hAlign: 0, width: 150, formatter: '@', wordWrap: true},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
+        ],
+        emptyRows: readOnly ? 0 : 3,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: readOnly,
+        localCache: {
+            key: 'stage-extra-yjcl',
+            colWidth: true,
+        },
+        getColor: function (sheet, data, row, col, defaultColor) {
+            if (!data || !data.end_tp) return defaultColor;
+
+            return data.end_qty >= 0
+                ? data.end_qty > data.arrive_qty ? '#f8d7da' : defaultColor
+                : data.end_qty < data.arrive_qty ? '#f8d7da' : defaultColor;
+        },
+    };
+    const yjclSpread = SpreadJsObj.createNewSpread($('#yjcl-spread')[0]);
+    const yjclSheet = yjclSpread.getActiveSheet();
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(spreadSetting);
+    SpreadJsObj.initSheet(yjclSheet, spreadSetting);
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            yjclSpread.refresh();
+        }
+    });
+
+    class Yjcl {
+        constructor () {
+            this.data = [];
+        }
+        resortData() {
+            this.data.sort(function (a, b) {
+                return a.m_order - b.m_order;
+            });
+        }
+        calculateAll() {
+            for (const d of this.data) {
+                d.end_qty = ZhCalc.add(d.pre_qty, d.qty);
+                d.end_tp = ZhCalc.add(d.pre_tp, d.tp);
+            }
+        }
+        loadDatas(datas) {
+            this.data = datas;
+            this.calculateAll();
+            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.calculateAll();
+            this.resortData();
+        }
+    }
+    const yjclObj = new Yjcl();
+
+    postData(window.location.pathname + '/load', null, function (result) {
+        yjclObj.loadDatas(result);
+        SpreadJsObj.loadSheetData(yjclSheet, SpreadJsObj.DataType.Data, yjclObj.data);
+    });
+
+    if (!readOnly) {
+        const yjclOprObj = {
+            /**
+             * 删除按钮响应事件
+             * @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;
+
+                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') {
+                                toastr.error('名称不能为空,如需删除材料请使用右键删除');
+                                return;
+                            }
+                            const style = sheet.getStyle(iRow, iCol);
+                            if (!style.locked) {
+                                const colSetting = sheet.zh_setting.cols[iCol];
+                                data[colSetting.field] = colSetting.type === 'Number' ? 0 : '';
+                                bDel = true;
+                            }
+                        }
+                        if (bDel) {
+                            datas.push(data);
+                        }
+                    }
+                }
+                if (datas.length > 0) {
+                    postData(window.location.pathname + '/update', {update: datas}, function (result) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    });
+                }
+            },
+            delete: 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 = {
+                    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.pre_used || !checkZero(node.end_qty) || !checkZero(node.end_qty)) {
+                        toastMessageUniq(hint.isOld);
+                        continue;
+                    } else {
+                        if (node.add_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) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    });
+                }
+            },
+            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.m_order = info.row + 1;
+                    data.add.name = trimInvalidChar(info.editingText);
+                }
+
+                postData(window.location.pathname + '/update', data, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                });
+            },
+            editStarting(e, info) {
+                if (!info.sheet.zh_setting || !info.sheet.zh_data) {
+                    info.cancel = true;
+                    return;
+                }
+
+                const col = info.sheet.zh_setting.cols[info.col];
+                const node = info.sheet.zh_data[info.row];
+                if (!node) return;
+
+                switch (col.field) {
+                    case 'name':
+                    case 'spec':
+                    case 'unit':
+                    case 'tax':
+                    case 'arrive_qty':
+                    case 'arrive_tp':
+                    case 'arrive_time':
+                    case 'source':
+                    case 'bills_code':
+                    case 'position':
+                    case 'prepare_pos':
+                        info.cancel = readOnly || node.add_sid !== stageId;
+                        break;
+                }
+            },
+            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: '材料名称不可为空,已过滤'},
+                    tax: {type: 'warning', msg: '输入的 税率 非法,已过滤'},
+                    arrive: {type: 'warning', msg: '输入的 到场数量/金额 非法,已过滤'},
+                    qty: {type: 'warning', msg: '输入的 本期计量-数量 非法,已过滤'},
+                };
+
+                const uDatas = [], iDatas = [];
+                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.m_order = curRow + 1;
+                            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) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(info.sheet);
+                    });
+                } else {
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }
+            },
+            upMove: function () {
+                const sels = yjclSheet.getSelections(), sortData = yjclSheet.zh_data;
+                const node = sortData[sels[0].row];
+                const preNode = sortData[sels[0].row - 1];
+                const data = [
+                    { id: node.id, m_order: preNode.m_order },
+                    { id: preNode.id, m_order: node.m_order }
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(yjclSheet, [sels[0].row, sels[0].row - 1]);
+                    yjclSheet.setSelection(sels[0].row - 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            },
+            downMove: function () {
+                const sels = yjclSheet.getSelections(), sortData = yjclSheet.zh_data;
+                const node = sortData[sels[0].row];
+                const nextNode = sortData[sels[0].row + 1];
+                const data = [
+                    {id: node.id, m_order: nextNode.m_order},
+                    {id: nextNode.id, m_order: node.m_order}
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(yjclSheet, [sels[0].row, sels[0].row + 1]);
+                    yjclSheet.setSelection(sels[0].row + 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            }
+        };
+        yjclSheet.bind(spreadNS.Events.EditEnded, yjclOprObj.editEnded);
+        yjclSheet.bind(spreadNS.Events.EditStarting, yjclOprObj.editStarting);
+        yjclSheet.bind(spreadNS.Events.ClipboardPasting, yjclOprObj.clipboardPasting);
+        SpreadJsObj.addDeleteBind(yjclSpread, yjclOprObj.deletePress);
+        $.contextMenu({
+            selector: '#yjcl-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, yjclSpread);
+                return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+            },
+            items: {
+                del: {
+                    name: '删除',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        yjclOprObj.delete(yjclSheet);
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0]) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                sprDel: '------------',
+                upMove: {
+                    name: '上移',
+                    icon: 'fa-arrow-up',
+                    callback: function (key, opt) {
+                        yjclOprObj.upMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row === 0) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                downMove: {
+                    name: '下移',
+                    icon: 'fa-arrow-down',
+                    callback: function (key, opt) {
+                        yjclOprObj.downMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row >= yjclObj.data.length - 1) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                }
+            },
+        })
+    }
+
+    $('#exportExcel').click(function () {
+        SpreadExcelObj.exportSimpleXlsxSheet(spreadSetting, yjclObj.data, $('.sidebar-title').attr('data-original-title') + "-永久材料.xlsx");
+    });
+});

+ 6 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -521,6 +521,7 @@ const SpreadJsObj = {
             data.waitingLoading = true;
             return;
         }
+        let autoFit = false;
         sheet.zh_setting.cols.forEach(function (col, j) {
             const cell = sheet.getCell(row, j);
             if (col.getValue && Object.prototype.toString.apply(col.getValue) === "[object Function]") {
@@ -567,8 +568,13 @@ const SpreadJsObj = {
             cell.foreColor(SpreadJsObj._getForeColor(sheet, data, row, col));
 
             cell.setBorder(sheet.borderLine, {all: true});
+            if (col.wordWrap) {
+                cell.wordWrap(true);
+                autoFit = true;
+            }
             data.waitingLoading = false;
         });
+        if (autoFit) sheet.autoFitRow(row);
     },
     _addActivePaintEvents: function (sheet, cellType) {
         if (!sheet.ActiveType) {

+ 4 - 0
app/router.js

@@ -407,6 +407,10 @@ module.exports = app => {
     app.get('/tender/:id/measure/stage/:order/extra/jgcl', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.jgcl');
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadJgcl');
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateJgcl');
+    // 永久材料
+    app.get('/tender/:id/measure/stage/:order/extra/yjcl', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.yjcl');
+    app.post('/tender/:id/measure/stage/:order/extra/yjcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadYjcl');
+    app.post('/tender/:id/measure/stage/:order/extra/yjcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateYjcl');
     // 奖罚金
     app.get('/tender/:id/measure/stage/:order/extra/bonus', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.bonus');
     app.post('/tender/:id/measure/stage/:order/extra/bonus/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadBonus');

+ 3 - 0
app/service/report_memory.js

@@ -927,6 +927,8 @@ module.exports = app => {
                 for (const d of changeBills) {
                     d.o_qty = d.oamount;
                     d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+                    d.o_qty2 = d.oamount2;
+                    d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
                     d.c_qty = d.camount;
                     d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
                     d.s_qty = d.samount ? parseFloat(d.samount) : 0;
@@ -1033,6 +1035,7 @@ module.exports = app => {
                     const bills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: c.cid } });
                     for (const b of bills) {
                         b.o_qty = b.oamount;
+                        d.o_qty2 = d.oamount2;
                         b.c_qty = b.camount;
                         b.s_qty = b.samount ? parseFloat(b.samount) : 0;
                         b.sp_qty = b.spamount;

+ 2 - 0
app/service/rpt_gather_memory.js

@@ -1299,6 +1299,8 @@ module.exports = app => {
                     d.tender_name = tender.name;
                     d.o_qty = d.oamount;
                     d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+                    d.o_qty2 = d.oamount2;
+                    d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
                     d.c_qty = d.camount;
                     d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
                     d.s_qty = d.samount ? parseFloat(d.samount) : 0;

+ 2 - 0
app/service/stage.js

@@ -570,6 +570,8 @@ module.exports = app => {
                 if (preCheckedStage) {
                     const jgclResult = await this.ctx.service.stageJgcl.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!jgclResult) throw '初始化甲供材料数据失败';
+                    const yjclResult = await this.ctx.service.stageYjcl.addInitialStageData(newStage, preCheckedStage, transaction);
+                    if (!yjclResult) throw '初始化甲供材料数据失败';
                     const otherResult = await this.ctx.service.stageOther.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!otherResult) throw '初始化其他台账数据失败';
                     const safeResult = await this.ctx.service.stageSafeProd.addInitialStageData(newStage, preCheckedStage, transaction);

+ 10 - 0
app/service/stage_audit.js

@@ -328,6 +328,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.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -498,6 +499,7 @@ module.exports = app => {
                         // 复制一份下一审核人数据
                         await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, nextAudits[0].order, transaction);
                         await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                        await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -576,6 +578,7 @@ module.exports = app => {
                                 await this.ctx.service.stageOther.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageSafeProd.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageJgcl.addInitialStageData(ns, this.ctx.stage, transaction);
+                                await this.ctx.service.stageYjcl.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageTempLand.addInitialStageData(ns, this.ctx.stage, transaction);
                             }
                             const preStageTp = {
@@ -727,6 +730,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.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -881,6 +885,7 @@ module.exports = app => {
                 // 复制一份最新数据给下一人
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, selfAudit.order + 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -1037,6 +1042,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, finalAudit.order + 1, transaction);
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, finalAudit.order + 2, transaction);
                 await this.ctx.service.stageJgcl.updateHistory4CheckAgain(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4CheckAgain(this.ctx.stage, transaction);
@@ -1276,6 +1282,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(stage, stage.times, selfAuditor.order + 2, transaction, stage.times, selfAuditor.order + 1);
                 // 其他台账明细:更新两份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1366,6 +1373,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(stage, stage.times, selfAuditor.order + 2, transaction, stage.times, selfAuditor.order + 1);
                 // 其他台账明细:更新一份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1468,6 +1476,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.deleteAuditStagePays(stage, stage.times, 0, transaction);
                 // 其他台账明细:更新一份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1861,6 +1870,7 @@ module.exports = app => {
             await transaction.delete(this.ctx.service.stageAuditAss.tableName, { sid, times });
             // 其他台账
             await this.ctx.service.stageJgcl.deleteStageTimesData(sid, times, transaction);
+            await this.ctx.service.stageYjcl.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageOther.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageBonus.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageSafeProd.deleteStageTimesData(sid, times, transaction);

+ 260 - 0
app/service/stage_yjcl.js

@@ -0,0 +1,260 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const auditConst = require('../const/audit').stage;
+const decimal = { up: 6, qty: 3 };
+
+module.exports = app => {
+    class StageYjcl extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'stage_yjcl';
+        }
+
+        async getStageData(stage) {
+            const data = await this.getAllDataByCondition({ where: { sid: stage.id } });
+            if (!stage.readOnly) return data;
+
+            for (const d of data) {
+                const his = d.shistory ? JSON.parse(d.shistory) : [];
+
+                const h = this.ctx.helper._.find(his, {
+                    stimes: stage.curTimes, sorder: stage.curOrder,
+                });
+                d.qty = h ? h.qty : 0;
+                d.tp = h ? h.tp : 0;
+            }
+            return data;
+        }
+
+        async _addDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
+            const datas = data instanceof Array ? data : [data];
+            const insertData = [];
+            for (const d of datas) {
+                if (!d.name || !d.m_order) throw '新增永久材料,提交的数据错误';
+                const nd = {
+                    uuid: this.uuid.v4(),
+                    add_sid: this.ctx.stage.id,
+                    add_sorder: this.ctx.stage.order,
+                    add_uid: this.ctx.session.sessionUser.accountId,
+                    tid: this.ctx.tender.id,
+                    sid: this.ctx.stage.id,
+                    sorder: this.ctx.stage.order,
+                };
+                nd.name = d.name;
+                nd.m_order = d.m_order;
+                nd.spec = d.spec || '';
+                nd.unit = d.unit || '';
+                nd.tax = d.tax ? this.ctx.helper.round(d.tax, 0) : 0;
+                nd.arrive_time = d.arrive_time || '';
+                nd.source = d.source || '';
+                nd.bills_code = d.bills_code || '';
+                nd.location = d.location || '';
+                nd.prepare_pos = d.prepare_pos || '';
+                nd.memo = d.memo || '';
+                const extraPre = 1 + this.ctx.helper.div(nd.tax, 100, 2);
+                nd.arrive_qty = d.arrive_qty ? this.ctx.helper.round(d.arrive_qty, decimal.qty) : 0;
+                nd.arrive_tp = d.arrive_tp ? this.ctx.helper.round(d.arrive_tp, tpDecimal) : 0;
+                nd.unit_price = d.arrive_qty ? this.ctx.helper.div(d.arrive_tp, d.arrive_qty, decimal.up) : 0;
+                nd.ex_tax_up = d.arrive_qty ? this.ctx.helper.div(this.ctx.helper.div(d.arrive_tp, d.arrive_qty), extraPre, decimal.up) : 0;
+                // nd.unit_price = d.unit_price ? this.ctx.helper.round(d.unit_price, decimal.up) : 0;
+                // const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, d.unit);
+                // if (d.arrive_qty) {
+                //     nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, decimal.qty);
+                //     nd.arrive_tp = this.ctx.helper.mul(this.ctx.helper.mul(nd.unit_price, nd.arrive_qty), extraPre, tpDecimal);
+                // }
+                nd.qty = d.qty ? this.ctx.helper.round(d.qty, decimal.qty) : 0;
+                // nd.tp = this.ctx.helper.mul(this.ctx.helper.mul(nd.unit_price, nd.qty), extraPre, tpDecimal);
+                nd.tp = this.ctx.helper.mul(nd.unit_price, nd.qty, tpDecimal);
+                insertData.push(nd);
+            }
+            await this.db.insert(this.tableName, insertData);
+            return await this.getAllDataByCondition({
+                where: { sid: this.ctx.stage.id, uuid: this.ctx.helper._.map(insertData, 'uuid') },
+            });
+        }
+
+        async _delDatas(data) {
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({
+                where: { sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id') },
+            });
+            for (const od of orgDatas) {
+                if (od.pre_used) throw '永久材料往期已经计量,不可删除';
+            }
+            await this.db.delete(this.tableName, { id: datas });
+            return datas;
+        }
+
+        async _updateDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({
+                where: { 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 !== undefined) nd.name = d.name;
+                if (d.m_order !== undefined) nd.m_order = d.m_order;
+                if (d.spec !== undefined) nd.spec = d.spec || '';
+                if (d.unit !== undefined) nd.unit = d.unit || '';
+                if (d.tax !== undefined) nd.tax = this.ctx.helper.round(d.tax, 0);
+
+                if (d.arrive_time !== undefined) nd.arrive_time = d.arrive_time || '';
+                if (d.source !== undefined) nd.source = d.source || '';
+                if (d.bills_code !== undefined) nd.bills_code = d.bills_code || '';
+                if (d.location !== undefined) nd.location = d.location || '';
+                if (d.prepare_pos !== undefined) nd.prepare_pos = d.prepare_pos || '';
+                if (d.memo !== undefined)nd.memo = d.memo || '';
+
+                if (d.arrive_qty !== undefined) nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, decimal.qty);
+                if (d.arrive_tp !== undefined) nd.arrive_tp = this.ctx.helper.round(d.arrive_tp, tpDecimal);
+                let unit_price = od.unit_price, ex_tax_up = od.ex_tax_up;
+                if (nd.arrive_qty !== undefined || nd.arrive_tp !== undefined) {
+                    const tp = nd.arrive_tp !== undefined ? nd.arrive_tp : od.arrive_tp;
+                    const qty = nd.arrive_qty !== undefined ? nd.arrive_qty : od.arrive_qty;
+                    const extraPre = nd.tax !== undefined ? 1 + this.ctx.helper.div(nd.tax, 100, 2) : 1 + this.ctx.helper.div(od.tax, 100, 2);
+                    nd.unit_price = qty ? this.ctx.helper.div(tp, qty, decimal.up) : 0;
+                    nd.ex_tax_up = qty ? this.ctx.helper.div(this.ctx.helper.div(tp, qty), extraPre, decimal.up) : 0;
+                    unit_price = nd.unit_price;
+                    ex_tax_up = nd.ex_tax_up;
+                }
+                if (d.qty !== undefined) nd.qty = d.qty ? this.ctx.helper.round(d.qty, decimal.qty) : 0;
+                if (nd.qty !== undefined) nd.tp = this.ctx.helper.mul(unit_price, nd.qty, tpDecimal);
+                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 updateHistory4TimesOrder(stage, times, order, transaction) {
+            const datas = await this.getStageData(stage);
+            if (datas.length === 0) return;
+
+            const updateDatas = [];
+            for (const d of datas) {
+                for (const curOrder of order) {
+                    const history = d.shistory ? JSON.parse(d.shistory) : [];
+                    const his = history.find(function (x) {
+                        return x.stimes === times && x.sorder === curOrder;
+                    });
+                    if (his) {
+                        his.qty = d.qty;
+                        his.tp = d.tp;
+                    } else {
+                        history.push({ stimes: times || 1, sorder: curOrder || 0, qty: d.qty, tp: d.tp });
+                    }
+                    updateDatas.push({ id: d.id, shistory: JSON.stringify(history) });
+                }
+            }
+            await transaction.updateRows(this.tableName, updateDatas);
+        }
+
+        async updateHistory(stage, transaction) {
+            await this.updateHistory4TimesOrder(stage, stage.curTimes, [stage.curOrder], transaction);
+        }
+
+        async updateHistory4CheckAgain(stage, transaction) {
+            await this.updateHistory4TimesOrder(stage, stage.curTimes, [stage.curOrder + 1], transaction);
+        }
+
+        async addInitialStageData(stage, preStage, transaction) {
+            if (!stage || !preStage) {
+                throw '标段数据有误';
+            }
+            const preDatas = await this.getAllDataByCondition({
+                columns: ['uuid', 'add_sid', 'add_sorder', 'add_uid', 'tid', 'name', 'm_order', 'unit', 'tax', 'arrive_time', 'source', 'bills_code', 'location', 'prepare_pos', 'memo',
+                    'arrive_qty', 'deduct_qty', 'unit_price', 'ex_tax_tp', 'qty', 'tp', 'pre_qty', 'pre_tp', 'pre_used'],
+                where: { sid: preStage.id },
+            });
+            if (preDatas.length > 0) {
+                for (const pd of preDatas) {
+                    pd.pre_used = pd.pre_used || !this.ctx.helper.checkZero(pd.qty);
+                    pd.pre_qty = this.ctx.helper.add(pd.qty, pd.pre_qty);
+                    pd.pre_tp = this.ctx.helper.add(pd.tp, pd.pre_tp);
+                    delete pd.qty;
+                    delete pd.tp;
+                    pd.sid = stage.id;
+                    pd.sorder = stage.order;
+                }
+                await transaction.delete(this.tableName, { sid: stage.id });
+                const result = await transaction.insert(this.tableName, preDatas);
+                return result.affectedRows === preDatas.length;
+            } else {
+                return true;
+            }
+        }
+
+        async deleteStageTimesData(sid, times, transaction) {
+            const datas = await this.getAllDataByCondition({ where: { sid } });
+            if (datas.length === 0) return;
+
+            const updateDatas = [];
+            for (const d of datas) {
+                const history = d.shistory && d.shistory !== '' ? JSON.parse(d.shistory) : [];
+                const his = history.filter(x => { return x.stimes && x.stimes < times; });
+                his.sort(function(x, y) {
+                    return (x.stimes * 1000 + x.sorder) - (y.stimes * 1000 + y.sorder);
+                });
+                const ud = {
+                    id: d.id,
+                    shistory: JSON.stringify(his),
+                    qty: his.length > 0 ? his[his.length - 1].qty : 0,
+                    tp: his.length > 0 ? his[his.length - 1].tp : 0,
+                };
+                updateDatas.push(ud);
+            }
+            await transaction.updateRows(this.tableName, updateDatas);
+        }
+    }
+
+    return StageYjcl;
+};

+ 1 - 0
app/view/stage_extra/sub_menu_list.ejs

@@ -1,5 +1,6 @@
 <nav-menu title="返回" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order %>" tclass="text-primary" ml="1" icon="fa-chevron-left"></nav-menu>
 <nav-menu title="甲供材料" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/jgcl'%>" ml="3" active="<%= ctx.url.indexOf('extra/jgcl') %>"></nav-menu>
+<nav-menu title="永久材料" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/yjcl'%>" ml="3" active="<%= ctx.url.indexOf('extra/yjcl') %>"></nav-menu>
 <nav-menu title="奖罚金" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/bonus'%>" ml="3" active="<%= ctx.url.indexOf('extra/bonus') %>"></nav-menu>
 <nav-menu title="安全生产" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/safeProd'%>" ml="3" active="<%= ctx.url.indexOf('extra/safeProd') %>"></nav-menu>
 <nav-menu title="临时占地" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/tempLand'%>" ml="3" active="<%= ctx.url.indexOf('extra/tempLand') %>"></nav-menu>

+ 39 - 0
app/view/stage_extra/yjcl.ejs

@@ -0,0 +1,39 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex">
+            <% include ./sub_mini_menu.ejs %>
+            <div>
+                永久材料
+            </div>
+            <% if (ctx.app.config.is_debug) { %>
+            <div class="d-inline-block ml-3">
+                <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出永久材料Excel</a>
+            </div>
+            <% } %>
+            <div class="ml-auto"></div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header p-0"></div>
+        <div class="w-100 sub-content row">
+            <div class="c-body col-12">
+                <div class="sjs-height-0" id="yjcl-spread">
+                </div>
+            </div>
+            <!--<div class="c-body col-3">-->
+                <!--<table class="table table-bordered" style="width: 99%">-->
+                    <!--<tr class="text-center"><th width="66.6%">名称</th><th>规格</th><th>数量</th><th>金额</th></tr>-->
+                    <!--<tbody id="sum">-->
+                    <!--</tbody>-->
+                <!--</table>-->
+            <!--</div>-->
+        </div>
+    </div>
+</div>
+<script>
+    const stageId = <%- ctx.stage.id %>;
+    const stageUserId = <%- ctx.stage.user_id %>;
+    const readOnly = <%- ctx.stage.readOnly || ctx.stage.revising || (ctx.stage.order > 1 && (!ctx.stage.preCheckedStage || ctx.stage.preCheckedStage.order < ctx.stage.order - 1)) %>;
+    const thousandth = <%- ctx.tender.info.display.thousandth %>;
+</script>

+ 18 - 0
config/web.js

@@ -535,6 +535,24 @@ const JsFiles = {
                 ],
                 mergeFile: 'se_jgcl',
             },
+            yjcl: {
+                files: [
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
+                    '/public/js/component/menu.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/se_yjcl.js',
+                ],
+                mergeFile: 'se_yjcl',
+            },
             bonus: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',

+ 1 - 0
sql/update.sql

@@ -9,6 +9,7 @@ CREATE TABLE `zh_stage_yjcl`  (
   `sorder` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '期序号',
   `name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
   `m_order` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序',
+  `spec` varchar(255) NOT NULL DEFAULT '' COMMENT '规格型号',
   `unit` varchar(20) NOT NULL DEFAULT '' COMMENT '单位',
   `tax` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '税率',
   `arrive_time` varchar(50) NOT NULL DEFAULT '' COMMENT '到场时间',