瀏覽代碼

变更令对应清单更改和新版本变更令第一版部分

laiguoran 4 年之前
父節點
當前提交
9fc29e23fe

+ 292 - 0
app/controller/change_controller.js

@@ -355,6 +355,7 @@ module.exports = app => {
                             cl.lid,
                             cl.xmj_code,
                             cl.xmj_jldy,
+                            cl.gcl_id,
                         ];
                         ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp);
                         ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp);
@@ -521,6 +522,297 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 变更信息 新版本页面 (Get)
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async information(ctx) {
+            try {
+                const whiteList = this.ctx.app.config.multipart.whitelist;
+                const tender = await ctx.service.tender.getDataById(ctx.tender.id);
+                const change = ctx.change;
+                // 后台判断当前人查看info状态
+                const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);
+
+                // 获取附件列表
+                const attList = await ctx.service.changeAtt.getChangeAttachment(change.cid);
+
+                // 获取其他变更令数据
+                const othersChange = await ctx.service.change.getOthersChange(ctx.tender.id, change.cid);
+
+                // 根据auditStatus获取审批人列表
+                const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
+                // 获取已选清单
+                let changeList = await ctx.service.changeAuditList.getAllDataByCondition({
+                    where: { cid: change.cid },
+                    orders: [['lid', 'desc'], ['id', 'asc']],
+                });
+
+                // 获取用户人验证手机号
+                const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                const auth_mobile = pa.auth_mobile;
+                const renderData = {
+                    tender,
+                    change,
+                    othersChange,
+                    changeConst,
+                    auditStatus,
+                    auditConst: audit.flow,
+                    ledgerConsts: audit.ledger.status,
+                    attList,
+                    whiteList,
+                    auditList,
+                    changeList,
+                    tpUnit: ctx.tender.info.decimal.tp,
+                    upUnit: ctx.tender.info.decimal.up,
+                    authMobile: auth_mobile,
+                    shenpiConst,
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.change.information),
+                };
+                // 根据auditStatus状态获取的不同的数据
+                if (auditStatus === 1 || auditStatus === 2) {
+                    renderData.changeUnits = changeConst.units;
+                    renderData.precision = ctx.tender.info.precision;
+                    // renderData.accountGroup = accountGroup;
+                    // 获取所有项目参与者
+                    const accountList = await ctx.service.projectAccount.getAllDataByCondition({
+                        where: { project_id: ctx.session.sessionProject.id, enable: 1 },
+                        columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group'],
+                    });
+                    renderData.accountList = accountList;
+                    renderData.accountGroup = accountGroup.map((item, idx) => {
+                        const groupList = accountList.filter(item => item.account_group === idx);
+                        return { groupName: item, groupList };
+                    });
+                    // 重新上报获取审批流程
+                    if (auditStatus === 2) {
+                        const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
+                        // 展示页右侧审批流程列表
+                        const auditList3 = [];
+                        for (let time = 1; time <= change.times - 1; time++) {
+                            const auditTimeList = [];
+                            let max_sort = 1;
+                            for (const al of auditList2) {
+                                if (al.times === time) {
+                                    auditTimeList.push(al);
+                                    if (al.usite > max_sort) {
+                                        max_sort = al.usite;
+                                    }
+                                }
+                            }
+                            for (const i in auditTimeList) {
+                                auditTimeList[i].max_sort = max_sort;
+                            }
+                            auditList3.push(auditTimeList);
+                        }
+                        renderData.auditList3 = auditList3;
+                    }
+
+                    // 根据清单获取提交数据和计算总金额
+                    let ototalCost = 0;
+                    let ctotalCost = 0;
+                    for (const cl of changeList) {
+                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp);
+                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp);
+                    }
+                    renderData.ototalCost = ototalCost;
+                    renderData.ctotalCost = ctotalCost;
+
+                    // 获取公司列表
+                    const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                    renderData.companyList = companyList;
+                } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) {
+                    // 展示页左侧审批流程列表和清单审批列表数据
+                    const times = change.status === audit.flow.status.back ?
+                        change.times - 1 : change.times;
+                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
+
+                    // 展示页右侧审批流程列表
+                    const auditList3 = [];
+                    for (let time = 1; time <= times; time++) {
+                        const auditTimeList = [];
+                        let max_sort = 1;
+                        for (const al of auditList) {
+                            if (al.times === time) {
+                                auditTimeList.push(al);
+                                if (al.usite > max_sort) {
+                                    max_sort = al.usite;
+                                }
+                            }
+                        }
+                        for (const i in auditTimeList) {
+                            auditTimeList[i].max_sort = max_sort;
+                        }
+                        auditList3.push(auditTimeList);
+                    }
+                    renderData.auditList3 = auditList3;
+
+                    changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort();
+                    renderData.changeList = changeList;
+                    let ototalCost = 0;
+                    let ctotalCost = 0;
+                    let stotalCost = 0;
+                    const auditTotalCost = [];
+                    for (const cl of changeList) {
+                        // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
+                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit);
+                        // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
+                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit);
+                        // stotalCost += cl.samount !== '' && cl.unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.samount), renderData.tpUnit)) : 0;
+                        stotalCost += cl.samount !== '' && cl.unit_price !== null ? ctx.helper.mul(cl.unit_price, cl.samount, renderData.tpUnit) : 0;
+                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
+                        auditTotalCost.push(audit_amount);
+                    }
+                    renderData.ototalCost = ototalCost;
+                    renderData.ctotalCost = ctotalCost;
+                    renderData.stotalCost = stotalCost;
+
+                    // 清单表页赋值
+                    for (const [index, au] of auditList2.entries()) {
+                        if (au.usite !== 0) {
+                            au.list_amount = [];
+                            au.totalCost = 0;
+                            for (const [auindex, at] of auditTotalCost.entries()) {
+                                au.list_amount.push(at[index - 1]);
+                                // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
+                                au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0;
+                            }
+                        }
+                    }
+                    renderData.auditList2 = auditList2;
+                } else if (auditStatus === 6) {
+                    // 展示页左侧审批流程列表和清单审批列表数据
+                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times);
+                    renderData.auditList2 = auditList2;
+                    const auditList3 = await ctx.service.changeAudit.getListOrderByTimes(change.cid, change.times);
+                    for (const i in auditList3) {
+                        auditList3[i].max_sort = auditList2.length - 1;
+                    }
+                    renderData.auditList3 = auditList3;
+
+                    // 展示页右侧审批流程列表
+                    const auditList5 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
+                    const auditList4 = [];
+                    for (let time = 1; time <= change.times; time++) {
+                        const auditTimeList = [];
+                        let max_sort = 1;
+                        for (const al of auditList5) {
+                            if (al.times === time) {
+                                auditTimeList.push(al);
+                                if (al.usite > max_sort) {
+                                    max_sort = al.usite;
+                                }
+                            }
+                        }
+                        for (const i in auditTimeList) {
+                            auditTimeList[i].max_sort = max_sort;
+                        }
+                        if (auditTimeList.length > 0) {
+                            auditList4.push(auditTimeList);
+                        }
+                    }
+                    renderData.auditList4 = auditList4;
+
+                    changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort();
+                    renderData.changeList = changeList;
+                    let ototalCost = 0;
+                    let ctotalCost = 0;
+                    const auditTotalCost = [];
+                    const auditUnit = [];
+                    for (const cl of changeList) {
+                        // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
+                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit);
+                        // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
+                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit);
+                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
+                        auditTotalCost.push(audit_amount);
+                    }
+                    renderData.ototalCost = ototalCost;
+                    renderData.ctotalCost = ctotalCost;
+
+                    // 清单表页赋值
+                    for (const [index, au] of auditList.entries()) {
+                        if (au.usite !== 0) {
+                            au.list_amount = [];
+                            au.totalCost = 0;
+                            if (au.uid === renderData.uid) {
+                                for (const [auindex, at] of auditTotalCost.entries()) {
+                                    // if (at[index - 2] !== undefined) {
+                                    //     au.list_amount.push(at[index - 2]);
+                                    //     au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 2]), renderData.tpUnit));
+                                    // } else if (at[index - 2] === undefined) {
+                                    //     au.list_amount.push(changeList[auindex].camount);
+                                    //     au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].camount), renderData.tpUnit));
+                                    // }
+                                    au.list_amount.push(changeList[auindex].spamount);
+                                    // au.totalCost += changeList[auindex].unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].spamount), renderData.tpUnit));
+                                    au.totalCost += changeList[auindex].unit_price === null ? 0 : ctx.helper.mul(changeList[auindex].unit_price, changeList[auindex].spamount, renderData.tpUnit);
+                                }
+                            } else {
+                                for (const [auindex, at] of auditTotalCost.entries()) {
+                                    au.list_amount.push(at[index - 1]);
+                                    // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
+                                    au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0;
+                                }
+                            }
+                        }
+                    }
+                }
+                renderData.auditList = auditList;
+
+                // 获取是否已存在调用变更令
+                const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, change.cid);
+                renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.used_qty); }));
+                await this.layout('change/information.ejs', renderData, 'change/information_modal.ejs');
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/tender/' + ctx.params.id + '/change');
+            }
+        }
+
+        /**
+         * 变更清单 - 操作 (Ajax)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async saveListsData(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const responseData = {
+                    err: 0,
+                    msg: '',
+                    data: {},
+                };
+                switch (data.type) {
+                    case 'add':
+                        responseData.data = await ctx.service.changeAuditList.add(data.postData);
+                        break;
+                    case 'del':
+                        await ctx.service.changeAuditList.del(data.id);
+                        break;
+                    case 'update':
+                        await ctx.service.changeAuditList.save(data.updateData);
+                        break;
+                    case 'paste':
+                        await ctx.service.changeAuditList.saveDatas(data.updateData);
+                        // 取所有工料表
+                        responseData.data = await ctx.service.changeAuditList.getAllDataByCondition({
+                            where: { cid: ctx.change.cid },
+                            orders: [['lid', 'desc'], ['id', 'asc']],
+                        });
+                        break;
+                    default: throw '参数有误';
+                }
+
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
         async defaultBills(ctx) {
             try {
                 const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);

+ 82 - 0
app/middleware/change_check.js

@@ -0,0 +1,82 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Ellisran
+ * @date 2020/10/15
+ * @version
+ */
+
+const status = require('../const/audit').flow.status;
+const shenpiConst = require('../const/shenpi');
+const _ = require('lodash');
+
+module.exports = options => {
+    /**
+     * 标段校验 中间件
+     * 1. 读取标段数据(包括属性)
+     * 2. 检验用户是否可见标段(不校验具体权限)
+     *
+     * @param {function} next - 中间件继续执行的方法
+     * @return {void}
+     */
+    return function* changeCheck(next) {
+        try {
+            // 获取revise
+            const cid = this.params.cid || this.request.body.cid;
+            if (!cid) {
+                throw '您访问的变更令不存在';
+            }
+            const change = yield this.service.change.getDataByCondition({ cid });
+            // 读取原报、审核人数据
+            change.auditors = yield this.service.changeAudit.getListGroupByTimes(change.cid, change.times);
+            change.curAuditor = yield this.service.changeAudit.getCurAuditor(change.cid, change.times);
+
+            if (!change) throw '变更令数据有误';
+            // 权限相关
+            // todo 校验权限 (变更参与人)
+            const accountId = this.session.sessionUser.accountId,
+                auditorIds = _.map(change.auditors, 'uid'),
+                shareIds = [];
+            const permission = this.session.sessionUser.permission;
+            if (accountId === change.uid) { // 原报
+                if (change.curAuditor) {
+                    change.readOnly = change.curAuditor.uid !== accountId;
+                } else {
+                    change.readOnly = change.status !== status.uncheck && change.status !== status.back;
+                }
+            } else if (auditorIds.indexOf(accountId) !== -1) { // 审批人
+                if (change.status === status.uncheck) {
+                    throw '您无权查看该数据';
+                }
+                change.readOnly = (change.status !== status.checking && change.status !== status.back) || accountId !== change.curAuditor.uid;
+            } else if (shareIds.indexOf(accountId) !== -1 || (permission !== null && permission.tender !== undefined && permission.tender.indexOf('2') !== -1)) { // 分享人
+                if (change.status === status.uncheck) {
+                    throw '您无权查看该数据';
+                }
+                change.readOnly = true;
+            } else { // 其他不可见
+                throw '您无权查看该数据';
+            }
+
+            this.change = change;
+            yield next;
+        } catch (err) {
+            console.log(err);
+            // 输出错误到日志
+            if (err.stack) {
+                this.logger.error(err);
+            } else {
+                this.getLogger('fail').info(JSON.stringify({
+                    error: err,
+                    project: this.session.sessionProject,
+                    user: this.session.sessionUser,
+                    body: this.session.body,
+                }));
+            }
+            // 重定向值标段管理
+            this.redirect(this.request.headers.referer);
+        }
+    };
+};

+ 169 - 0
app/public/js/change_information.js

@@ -0,0 +1,169 @@
+'use strict';
+
+/**
+ * 变更令详细页js
+ *
+ * @author EllisRan.
+ * @date 2018/11/22
+ * @version
+ */
+$(document).ready(() => {
+    const cca = getLocalCache('change-checkbox-account-' + accountId);
+    if (cca !== null && cca !== undefined) {
+        $('#customCheck1').prop('checked', cca !== 'false');
+    }
+    changeSpreadSheet.setColumnVisible(3,$('#customCheck1').is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
+    // 变更详情展示和隐藏
+    $('.change-detail-checkbox').on('click', function (e) {
+        if($(e.target).is('label')){
+            return;
+        }
+        // // 设置用户项目本地记录展示和隐藏情况
+        setLocalCache('change-checkbox-account-'+ accountId, $(this).is(':checked'));
+        changeSpreadSheet.setColumnVisible(3,$(this).is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
+    });
+
+    $('#add-bj').on('click', 'input[type="checkbox"]', function () {
+        const isCheck = $(this).prop('checked');
+        if (isCheck) {
+            $('#add-bj input[type="checkbox"]').each(function () {
+                $(this).prop('checked', false)
+            });
+            $(this).prop('checked', true)
+        }
+    });
+    $('#bg-copy').click(function() {
+        const cid = $('#add-bj input:checked').data('id');
+        postData(window.location.pathname + '/copy', cid, function () {
+            window.location.reload();
+        })
+    });
+    // 上传附件
+    $('#upload-file-btn').click(function () {
+        const files = $('#upload-file')[0].files;
+        const formData = new FormData();
+        formData.append('cid', $('#changeId').val());
+        formData.append('tid', $('#tenderId').val());
+        for (const file of files) {
+            if (file === undefined) {
+                toastr.error('未选择上传文件!');
+                return false;
+            }
+            const filesize = file.size;
+            if (filesize > 30 * 1024 * 1024) {
+                toastr.error('文件大小过大!');
+                return false;
+            }
+            const fileext = '.' + file.name.toLowerCase().split('.').splice(-1)[0];
+            if (whiteList.indexOf(fileext) === -1) {
+                toastr.error('只能上传指定格式的附件!');
+                return false;
+            }
+            formData.append('size', filesize);
+            formData.append('file[]', file);
+        }
+        if (auditList.findIndex(item => item.uid === parseInt(accountId)) === -1) {
+            return toastr.error('暂无权限上传!')
+        }
+        postDataWithFile(window.location.pathname + '/file/upload', formData, function (data) {
+            $('#addfujian').modal('hide');
+            let html = '';
+            let index = $('#attList tr').length + 1;
+            for (const fileInfo of data) {
+                html += '<tr> ' +
+                    `<td width="25"><input type="checkbox" class="check-file" file-id=${fileInfo.id}></td>` +
+                    '<td>' + index + '</td> ' +
+                    `<td><a href="javascript: void(0);" class="file-atn" f-id="${fileInfo.id}">${fileInfo.filename}${fileInfo.fileext}</a></td>`+
+                    '<td>' + fileInfo.filesize + '</td> ' +
+                    '<td>' + fileInfo.in_time + '</td> ' +
+                    `<td><a href="/change/download/file/${fileInfo.id}" class="btn btn-light btn-sm" title="下载"><span class="fa fa-download text-primary"></span></a>`+
+                    ( auditStatus === 4 ?
+                        fileInfo.extra_upload ? `<a class="btn btn-light btn-sm delete-file" data-attid="${fileInfo.id}"  title="删除附件"><span class="fa fa-trash text-danger"></span></a>` : ''
+                        : ` <a class="btn btn-light btn-sm delete-file" data-attid="${fileInfo.id}"  title="删除附件"><span class="fa fa-trash text-danger"></span></a>`)+
+                    `</td>`+
+                    // '<td> <a class="btn btn-light btn-sm delete-file" data-attid="' + fileInfo.id + '"  title="删除附件"><span class="fa fa-trash text-danger"></span></a> </td> ' +
+                    '</tr>';
+                ++index;
+            }
+            $('#attList').append(html);
+        }, function () {
+        });
+        $('#upload-file').val('');
+
+    });
+
+    // 删除附件
+    $('body').on('click', '.delete-file', function () {
+        let attid = $(this).data('attid');
+        let self = $(this);
+        const data = {id: attid};
+        postData(window.location.pathname + '/file/delete', data, function (result) {
+            self.parents('tr').remove();
+            // 重新排序
+            let newsort = 1;
+            $('#attList tr').each(function(){
+                $(this).children('td').eq(1).text(newsort);
+                newsort++;
+            });
+        });
+    });
+    // /change/download/file/
+    $('#attList').on('click', '.file-atn', function() {
+        const id = $(this).attr('f-id');
+        postData(`/change/download/file/${id}`, {}, (data) => {
+            const { filepath } = data;
+            $('#file-upload').attr('href', filepath);
+            $('#file-upload')[0].click();
+        })
+    });
+
+    $('#attList').on('click', '.check-file', function() {
+        const checkedList = $('#attList').find('input:checked');
+        const childs = $('#attList').children().length;
+        const checkBox = $('#check-all-file');
+        if (checkedList.length === childs) {
+            checkBox.prop("checked", true);
+        } else {
+            checkBox.prop("checked", false);
+        }
+    });
+    $('#check-all-file').click(function() {
+        const isCheck = $(this).is(':checked');
+        $('#attList').children().each(function() {
+            $(this).find('input:checkbox').prop("checked", isCheck);
+        })
+    });
+
+    $('#bach-download').click(function() {
+        const fileIds = [];
+        $( '#attList .check-file:checked').each(function() {
+            const fileId = $(this).attr('file-id');
+            fileId && fileIds.push(fileId);
+        });
+
+        if (fileIds.length) {
+            const tid = $('#tenderId').val();
+            const cid = $('#changeId').val();
+            $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
+            $('#downloadZip')[0].click();
+        }
+    });
+
+    $.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();
+            changeSpread.refresh();
+        }
+    });
+});

+ 726 - 0
app/public/js/change_information_set.js

@@ -0,0 +1,726 @@
+'use strict';
+
+/**
+ * 变更令详细页js
+ *
+ * @author EllisRan.
+ * @date 2018/11/22
+ * @version
+ */
+// 编号排序,多重判断
+function sortByCode(a, b) {
+    let code1 = a.code.split('-');
+    let code2 = b.code.split('-');
+    let code1length = code1.length;
+    let code2length = code2.length;
+    for (let i = 0; i < code1length; i ++) {
+        if (i+1 <= code2length) {
+            if (code1[i] != code2[i]) {
+                if (!/^\d+$/.test(code1[i])) {
+                    return code1[i].charCodeAt() - code2[i].charCodeAt();
+                } else {
+                    return parseInt(code1[i]) - parseInt(code2[i]);
+                }
+            } else if (i+1 == code1length && code1[i] == code2[i]) {
+                if (code1length == code2length) {
+                    return 0;
+                } else {
+                    return code1length - code2length;
+                }
+            }
+        } else {
+            if (i+1 >= code1length) {
+                return 1;
+            } else {
+                return -1;
+            }
+        }
+    }
+}
+const is_numeric = (value) => {
+    if (typeof(value) === 'object') {
+        return false;
+    } else {
+        return !Number.isNaN(Number(value)) && value.toString().trim() !== '';
+    }
+};
+$.event.special.valuechange = {
+    teardown: function (namespaces) {
+        $(this).unbind('.valuechange');
+    },
+
+    handler: function (e) {
+        $.event.special.valuechange.triggerChanged($(this));
+    },
+
+    add: function (obj) {
+        $(this).on('keyup.valuechange cut.valuechange paste.valuechange input.valuechange', obj.selector, $.event.special.valuechange.handler)
+    },
+
+    triggerChanged: function (element) {
+        var current = element[0].contentEditable === 'true' ? element.html() : element.val()
+            , previous = typeof element.data('previous') === 'undefined' ? element[0].defaultValue : element.data('previous');
+        if (current !== previous) {
+            element.trigger('valuechange', [element.data('previous')]);
+            element.data('previous', current);
+        }
+    }
+};
+$(document).ready(() => {
+    const style1 = new GC.Spread.Sheets.Style();
+    style1.locked = true;
+    const changeCol = {
+        getValue: {
+            unit_price: function(data) {
+                return ZhCalc.round(data.unit_price, unitPriceUnit);
+            },
+            oa_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(data.unit_price, data.oamount), totalPriceUnit);
+            },
+            ca_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(data.unit_price, data.camount), totalPriceUnit);
+            },
+            oamount: function (data) {
+                return ZhCalc.round(data.oamount, findDecimal(data.unit));
+            },
+            camount: function (data) {
+                return ZhCalc.round(data.camount, findDecimal(data.unit));
+            },
+            del_list: function (data) {
+                return '移除';
+            }
+        },
+        readOnly: {
+            isEdit: function (data) {
+                return !readOnly && data.lid != 0;
+            },
+        },
+    };
+
+    const changeSpreadObj = {
+        makeSjsFooter: function () {
+            // 增加汇总行并设为锁定禁止编辑状态
+            changeSpreadSheet.addRows(changeSpreadSheet.getRowCount(), 1);
+            changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 0, '合计');
+            changeSpreadSheet.setStyle(changeSpreadSheet.getRowCount() - 1, -1, style1);
+            changeSpreadObj.countSum();
+        },
+        countSum: function() {
+            const rowCount = changeSpreadSheet.getRowCount();
+            let oSum = 0,
+                cSum = 0;
+            for(var i = 0; i < rowCount - 1; i++){
+                oSum = ZhCalc.add(oSum, changeSpreadSheet.getValue(i, 7));
+                cSum = ZhCalc.add(cSum, changeSpreadSheet.getValue(i, 9));
+            }
+            changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 7, oSum !== 0 ? oSum : null);
+            changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 9, cSum !== 0 ? cSum : null);
+        },
+        add: function () {
+            postData(window.location.pathname + '/save', {type: 'add'}, function (result) {
+                if (result) {
+                    changeList.push(result);
+                    changeSpreadSheet.addRows(changeList.length - 1, 1);
+                    SpreadJsObj.reLoadRowData(changeSpreadSheet, changeList.length - 1);
+                    changeSpreadSheet.setStyle(changeSpreadSheet.getRowCount() - 1, -1, style1);
+                    changeSpreadSheet.setSelection(changeList.length - 1, 0, 1, 1);
+                }
+            });
+        },
+        del: function () {
+            const select = SpreadJsObj.getSelectObject(changeSpreadSheet);
+            const index = changeList.indexOf(select);
+            if (index > -1) {
+                postData(window.location.pathname + '/save', {type: 'del', id: select.id}, function (result) {
+                    changeList.splice(index, 1);
+                    changeSpreadSheet.deleteRows(index, 1);
+                    const sel = changeSpreadSheet.getSelections();
+                    changeSpreadSheet.setSelection(0, 0, 1, 1);
+                    if (select.lid != 0) {
+                        tableDataRemake(changeListData);
+                    }
+                    changeSpreadObj.countSum();
+                });
+            }
+        },
+        selectionChanged: function (e, info) {
+            const sel = info.sheet.getSelections()[0];
+            const col = info.sheet.zh_setting.cols[sel.col];
+            const data = SpreadJsObj.getSelectObject(info.sheet);
+            if (col.field === 'del_list') {
+                changeSpreadObj.del();
+            }
+        },
+        editEnded: function (e, info) {
+            if (info.sheet.zh_setting) {
+                const select = SpreadJsObj.getSelectObject(info.sheet);
+                const col = info.sheet.zh_setting.cols[info.col];
+                if (col.field === 'del_list') {
+                    return;
+                }
+                // 未改变值则不提交
+                let validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
+                const orgValue = select[col.field];
+                if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    return;
+                }
+                // 判断部分值是否输入的是数字判断和数据计算
+                if (col.type === 'Number') {
+                    if (isNaN(validText)) {
+                        toastr.error('不能输入其它非数字类型字符');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    if (col.field === 'unit_price') {
+                        validText = ZhCalc.round(validText, unitPriceUnit);
+                    } else {
+                        validText = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
+                    }
+                }
+                if (col.field === 'unit') {
+                    select.camount = ZhCalc.round(select.camount, findDecimal(validText)) || 0;
+                    select.oamount = ZhCalc.round(select.oamount, findDecimal(validText)) || 0;
+                }
+                select[col.field] = validText;
+                if(col.field === 'camount') {
+                    select.spamount = ZhCalc.round(select.camount, findDecimal(validText)) || 0;
+                }
+                console.log(select);
+
+                // 更新至服务器
+                postData(window.location.pathname + '/save', { type:'update', updateData: select }, function (result) {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    changeSpreadObj.countSum();
+                }, function () {
+                    select[col.field] = orgValue;
+                    if(col.field === 'camount') {
+                        select.spamount = orgValue;
+                    }
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                });
+            }
+        },
+        clipboardPasted(e, info) {
+            const hint = {
+                cellError: {type: 'error', msg: '粘贴内容超出了表格范围'},
+                numberExpr: {type: 'error', msg: '不能粘贴其它非数字类型字符'},
+            };
+            const range = info.cellRange;
+            const sortData = info.sheet.zh_data || [];
+            if (info.cellRange.row + info.cellRange.rowCount > sortData.length) {
+                toastMessageUniq(hint.cellError);
+                // SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
+                SpreadJsObj.reLoadSheetHeader(changeSpreadSheet);
+                SpreadJsObj.reLoadSheetData(changeSpreadSheet);
+                return;
+            }
+            if (sortData.length > 0 && range.col + range.colCount > 10) {
+                toastMessageUniq(hint.cellError);
+                SpreadJsObj.reLoadSheetHeader(changeSpreadSheet);
+                SpreadJsObj.reLoadSheetData(changeSpreadSheet);
+                return;
+            }
+            const data = [];
+            // const rowData = [];
+            for (let iRow = 0; iRow < range.rowCount; iRow++) {
+                let bPaste = true;
+                const curRow = range.row + iRow;
+                // const materialData = JSON.parse(JSON.stringify(sortData[curRow]));
+                const cLData = { id: sortData[curRow].id };
+                const hintRow = range.rowCount > 1 ? curRow : '';
+                let sameCol = 0;
+                for (let iCol = 0; iCol < range.colCount; iCol++) {
+                    const curCol = range.col + iCol;
+                    const colSetting = info.sheet.zh_setting.cols[curCol];
+                    if (!colSetting) continue;
+
+                    let validText = info.sheet.getText(curRow, curCol);
+                    validText = is_numeric(validText) ? parseFloat(validText) : (validText ? trimInvalidChar(validText) : null);
+                    const orgValue = sortData[curRow][colSetting.field];
+                    if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
+                        sameCol++;
+                        if (range.colCount === sameCol)  {
+                            bPaste = false;
+                        }
+                        continue;
+                    }
+                    if (colSetting.type === 'Number') {
+                        if (isNaN(validText)) {
+                            toastMessageUniq(getPasteHint(hint.numberExpr, hintRow));
+                            bPaste = false;
+                            continue;
+                        }
+                        if (colSetting.field === 'unit_price') {
+                            validText = ZhCalc.round(validText, unitPriceUnit);
+                        } else {
+                            validText = ZhCalc.round(validText, findDecimal(sortData[curRow].unit)) || 0;
+                        }
+                    }
+                    if (colSetting.field === 'unit') {
+                        cLData.camount = ZhCalc.round(sortData[curRow].camount, findDecimal(validText)) || 0;
+                        cLData.oamount = ZhCalc.round(sortData[curRow].oamount, findDecimal(validText)) || 0;
+                    }
+                    cLData[colSetting.field] = validText;
+                    sortData[curRow][colSetting.field] = validText;
+                    cLData.spamount = ZhCalc.round(sortData[curRow].camount, findDecimal(validText)) || 0;
+                }
+                if (bPaste) {
+                    data.push(cLData);
+                    // rowData.push(curRow);
+                } else {
+                    SpreadJsObj.reLoadRowData(info.sheet, curRow);
+                }
+            }
+            if (data.length === 0) {
+                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                return;
+            }
+            console.log(data);
+            // 更新至服务器
+            postData(window.location.pathname + '/save', { type:'paste', updateData: data }, function (result) {
+                changeList = result;
+                SpreadJsObj.loadSheetData(changeSpreadSheet, SpreadJsObj.DataType.Data, changeList);
+                changeSpreadObj.makeSjsFooter();
+            }, function () {
+                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                return;
+            });
+        },
+    };
+
+    const preUrl = window.location.pathname.split('/').slice(0, 4).join('/');
+    let changeListData;
+    let gclGatherData;
+    postData(preUrl + '/defaultBills', {}, function (result) {
+        gclGatherModel.loadLedgerData(result.bills);
+        gclGatherModel.loadPosData(result.pos);
+
+        gclGatherData = gclGatherModel.gatherGclData();
+        gclGatherData = _.filter(gclGatherData, function (item) {
+            return item.leafXmjs && item.leafXmjs.length !== 0;
+        });
+        for (const ggd in gclGatherData) {
+            if (gclGatherData[ggd].leafXmjs && gclGatherData[ggd].leafXmjs.length === 0) {
+                gclGatherData.splice(ggd, 1);
+            }
+            gclGatherData[ggd].code = gclGatherData[ggd].b_code;
+        }
+        // 数组去重
+        const dealBillList = result.dealBills;
+        for (const db of gclGatherData) {
+            const exist_index = dealBillList.findIndex(function (item) {
+                return item.code === db.code && item.name === db.name && item.unit === db.unit && item.unit_price === db.unit_price;
+            });
+            if (exist_index !== -1) {
+                dealBillList.splice(exist_index, 1);
+            }
+        }
+        changeListData = gclGatherData.concat(dealBillList).sort(sortByCode);
+        // 先加载台账数据
+        let listHtml = '';
+        let list_index = 1;
+        let gcl_index = 0;
+        for (const gcl of changeListData) {
+            const unit = gcl.unit !== undefined && gcl.unit !== null ? gcl.unit : '';
+            const quantity = gcl.quantity !== null && gcl.quantity !== undefined ? (unit !== '' ? ZhCalc.round(gcl.quantity, findDecimal(gcl.unit)) : gcl.quantity) : 0;
+            const unit_price = gcl.unit_price !== null && gcl.unit_price !== undefined ? gcl.unit_price : 0;
+            let gclhtml = gcl.leafXmjs !== undefined && gcl.leafXmjs !== null ? ' data-gcl="' + gcl_index + '"' : '';
+            gcl_index = gclhtml !== '' ? ++gcl_index : gcl_index;
+            const lid = gcl.leafXmjs !== undefined && gcl.leafXmjs !== null ? (gcl.leafXmjs.length !== 0 ? gcl.leafXmjs[0].gcl_id : false) : gcl.id;
+            if (lid) {
+                listHtml += '<tr data-lid="' + lid + '"' + gclhtml + ' data-index="' + list_index + '" data-bwmx="">' +
+                    '<td class="text-center">' + list_index + '</td>' +
+                    '<td>' + gcl.code + '</td>' +
+                    '<td class="text-left">' + gcl.name + '</td>' +
+                    '<td class="text-center">' + unit + '</td>' +
+                    '<td class="text-right">' + ZhCalc.round(unit_price, unitPriceUnit) + '</td>' +
+                    '<td class="text-right">' + quantity + '</td>' +
+                    '</tr>';
+                list_index++;
+            }
+        }
+        $('#table-list-select').html(listHtml);
+        tableDataRemake(changeListData);
+
+        SpreadJsObj.initSpreadSettingEvents(changeSpreadSetting, changeCol);
+        SpreadJsObj.initSheet(changeSpreadSheet, changeSpreadSetting);
+        SpreadJsObj.loadSheetData(changeSpreadSheet, SpreadJsObj.DataType.Data, changeList);
+        changeSpreadObj.makeSjsFooter();
+    });
+
+    if (!readOnly) {
+        $('#add-white-btn').click(changeSpreadObj.add);
+        changeSpread.bind(spreadNS.Events.EditEnded, changeSpreadObj.editEnded);
+        changeSpread.bind(spreadNS.Events.SelectionChanged, changeSpreadObj.selectionChanged);
+        changeSpread.bind(spreadNS.Events.ClipboardPasted, changeSpreadObj.clipboardPasted);
+        changeSpreadSheet.getCell(-1, 10).foreColor('#dc3545');
+
+        // 右键菜单
+        $.contextMenu({
+            selector: '#change-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, changeSpread);
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                'createList': {
+                    name: '添加台账清单',
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        $('#addlist').modal('show');
+                    },
+                },
+                'createAdd': {
+                    name: '添加空白清单',
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        changeSpreadObj.add(changeSpreadSheet);
+                    },
+                },
+                'delete': {
+                    name: '删除',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        changeSpreadObj.del(changeSpreadSheet);
+                    },
+                    disabled: function (key, opt) {
+                        const select = SpreadJsObj.getSelectObject(changeSpreadSheet);
+                        const sel = changeSpreadSheet.getSelections()[0];
+                        console.log(select, sel);
+                        if (!readOnly && select && sel.row !== changeSpreadSheet.getRowCount() - 1) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                },
+            }
+        });
+    }
+
+    // 清单选中和移除
+    $('body').on('click', '#table-list-select tr', function () {
+        $('#table-list-select tr').removeClass('table-warning');
+        $(this).addClass('table-warning');
+        const isCheck = $(this).hasClass('table-success') ? true : false;
+        const data_bwmx = $(this).attr('data-bwmx').split('$#$');
+        const isDeal = $(this).data('gcl') !== undefined ? true : false;
+        let codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox"></td></tr>';
+        if (isDeal) {
+            const lid = $(this).data('lid');
+            let gcl = _.find(gclGatherData, function (item) {
+                return item.leafXmjs && item.leafXmjs[0].gcl_id === lid;
+            });
+            if (!gcl) {
+                gcl = gclGatherData[$(this).data('gcl')];
+            }
+            codeHtml = '';
+            for (const leaf of gcl.leafXmjs) {
+                const quantity = leaf.quantity !== undefined && leaf.quantity !== null ? leaf.quantity : 0;
+                const bwmx = leaf.bwmx !== undefined ? leaf.bwmx : '';
+                const isChecked = data_bwmx.indexOf(leaf.code + '!_!' + (leaf.jldy ? leaf.jldy : '') + '!_!' + (bwmx !== '' ? bwmx : leaf.jldy ? leaf.jldy : '') + '*;*' + quantity) !== -1 && isCheck ? 'checked' : '';
+                codeHtml += '<tr quantity="' + quantity + '"><td>' + leaf.code + '</td>' +
+                    '<td>' + (leaf.jldy ? leaf.jldy: '') + '</td>' +
+                    '<td>' + (leaf.dwgc ? leaf.dwgc : '') + '</td>' +
+                    '<td>' + (leaf.fbgc ? leaf.fbgc : '') + '</td>' +
+                    '<td>' + (leaf.fxgc ? leaf.fxgc : '') + '</td>' +
+                    '<td>' + bwmx + '</td>' +
+                    '<td class="text-right">' + ZhCalc.round(quantity, findDecimal(gcl.unit)) + '</td>' +
+                    '<td class="text-center"><input type="checkbox"' + isChecked +
+                    '></td></tr>';
+            }
+        } else if (!isDeal && isCheck) {
+            codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox" checked></td></tr>';
+        }
+        $('#code-list').attr('data-index', $(this).children('td').eq(0).text());
+        $('#code-input').val('');
+        $('#code-input').siblings('a').hide();
+        $('#code-list').html(codeHtml);
+    });
+
+    // 右边项目节选择
+    $('body').on('click', '#code-list input', function () {
+        let index = $('#code-list').attr('data-index');
+        if ($(this).is(':checked')) {
+            // 去除其它可能已选的checked
+            // $('#code-list input').prop('checked', false);
+            $(this).prop('checked', true);
+            // 左边表单传值并添加class
+            $('#table-list-select tr[data-index="' + index + '"]').addClass('table-success');
+            // 去除部分data-detail值
+            let data_bwmx = [];
+            $('#code-list input:checked').each(function () {
+                const tr = $(this).parents('tr');
+                const length = tr.children('td').length;
+                const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!' + tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                const quantity = tr.attr('quantity');
+                const de_qu = bwmx + '*;*' + quantity;
+                data_bwmx.push(de_qu);
+            });
+            data_bwmx = data_bwmx.join('$#$');
+            $('#table-list-select tr[data-index="' + index + '"]').attr('data-bwmx', data_bwmx);
+        } else {
+            // 判断还有无选中项目节编号
+            if ($('#code-list input').is(':checked')) {
+                // 去除部分data-detail值
+                let data_bwmx = [];
+                $('#code-list input:checked').each(function () {
+                    const tr = $(this).parents('tr');
+                    const length = tr.children('td').length;
+                    const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!'+ tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                    const quantity = tr.attr('quantity');
+                    const de_qu = bwmx + '*;*' + quantity;
+                    data_bwmx.push(de_qu);
+                });
+                data_bwmx = data_bwmx.join('$#$');
+                $('#table-list-select tr[data-index="' + index + '"]').attr('data-bwmx', data_bwmx);
+            } else {
+                $('#table-list-select tr[data-index="' + index + '"]').removeClass('table-success');
+                $('#table-list-select tr[data-index="' + index + '"]').attr('data-bwmx', '');
+            }
+        }
+    });
+
+    // 添加空白清单or签约清单
+    $('.add-list-btn').on('click', function () {
+        remakeChangeSpread();
+        SpreadJsObj.loadSheetData(changeSpreadSheet, SpreadJsObj.DataType.Data, changeList);
+        changeSpreadObj.makeSjsFooter();
+        $('#addlist').modal('hide');
+    });
+
+    // 选中input所有值
+    $('body').on('focus', ".clist input", function() {
+        $(this).select();
+    });
+
+    // 取消选中清单
+    $('#cancel-list-btn').click(function () {
+        // $('#table-list-select tr').removeClass('table-success');
+        // $('#table-list-select tr').attr('data-bwmx', '');
+        // $('#code-list').html('');
+        tableDataRemake(changeListData);
+    });
+
+    // 自动编号
+    $('.reduction-code').click(function () {
+        const code = $(this).attr('data-code');
+        $('input[name="code"]').val(code);
+    });
+
+    $('#list-input').on('valuechange', function (e, previous) {
+        const value = $(this).val();
+        let showListData = changeListData;
+        if (value !== '') {
+            $(this).siblings('a').show();
+            showListData = _.filter(changeListData, function (c) {
+                return (c.code && c.code.indexOf(value) !== -1) || (c.name && c.name.indexOf(value) !== -1);
+            });
+        } else {
+            $(this).siblings('a').hide();
+        }
+        makeListTable(changeListData, showListData);
+        $('#table-list-select tr').removeClass('table-warning');
+        $('#code-input').val('');
+        $('#code-input').siblings('a').hide();
+        $('#code-list').html('');
+    });
+
+    $('#code-input').on('valuechange', function (e, previous) {
+        const value = $(this).val();
+        if (value !== '') {
+            $(this).siblings('a').show();
+        } else {
+            $(this).siblings('a').hide();
+        }
+        makeCodeTable($(this).val());
+    });
+
+    $('.remove-btn').on('click', function () {
+        $(this).hide();
+        $(this).siblings('input').val('');
+        if ($(this).data('btn') === 'list') {
+            makeListTable(changeListData);
+            $('#table-list-select tr').removeClass('table-warning');
+            $('#code-list').html('');
+        } else {
+            makeCodeTable();
+        }
+    })
+});
+function findDecimal(unit) {
+    let value = precision.other.value;
+    const changeUnits = precision;
+    for (const d in changeUnits) {
+        if (changeUnits[d].unit !== undefined && changeUnits[d].unit === unit) {
+            value = changeUnits[d].value;
+            break;
+        }
+    }
+    return value;
+}
+
+function tableDataRemake(changeListData) {
+    $('#table-list-select tr').removeClass('table-warning');
+    $('#table-list-select tr').removeClass('table-success');
+    $('#table-list-select tr').attr('data-bwmx', '');
+    $('#code-list').html('');
+    // 根据已添加的清单显示
+    if (changeList.length > 0 && changeList[0]) {
+        for (const [index,clinfo] of changeList.entries()) {
+            if (clinfo.lid != 0) {
+                let listinfo = changeListData.find(function (item) {
+                    return (item.id !== undefined && item.id == clinfo.lid) || (item.id === undefined && item.leafXmjs !== undefined && item.leafXmjs.length !== 0 && item.leafXmjs[0].gcl_id == clinfo.lid);
+                });
+                if (listinfo === undefined) {
+                    // 针对旧数据获取清单信息
+                    listinfo = changeListData[clinfo.lid - 1];
+                    if (listinfo === undefined) {
+                        toastr.warning('台账清单列表已不存在'+ clinfo.code +',已更新变更清单列表');
+                        changeList.splice(index, 1);
+                        continue;
+                    }
+                    $('#table-list-select tr[data-index="'+ clinfo.lid +'"]').addClass('table-success');
+                    let pushbwmx = '0*;*0';
+                    if (listinfo.leafXmjs !== undefined) {
+                        const leafInfo = listinfo.leafXmjs.find(function (item) {
+                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                        });
+                        console.log(leafInfo);
+                        if (leafInfo) {
+                            pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        } else {
+                            toastr.warning('台账清单列表已不存在'+ clinfo.code +',已更新变更清单列表');
+                            changeList.splice(index, 1);
+                            continue;
+                        }
+                    } else {
+                        pushbwmx = '0*;*' + (listinfo.quantity !== null ? listinfo.quantity : 0);
+                    }
+                    const bwmx = $('#table-list-select tr[data-index="'+ clinfo.lid +'"]').attr('data-bwmx');
+                    if (bwmx) {
+                        const bwmxArray = bwmx.split('$#$');
+                        bwmxArray.push(pushbwmx);
+                        $('#table-list-select tr[data-index="'+ clinfo.lid +'"]').attr('data-bwmx', bwmxArray.join('$#$'));
+                    } else {
+                        $('#table-list-select tr[data-index="'+ clinfo.lid +'"]').attr('data-bwmx', pushbwmx);
+                    }
+                } else {
+                    $('#table-list-select tr[data-lid="'+ clinfo.lid +'"]').addClass('table-success');
+                    let pushbwmx = '0*;*0';
+                    if (listinfo.leafXmjs !== undefined) {
+                        const leafInfo = listinfo.leafXmjs.find(function (item) {
+                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                        });
+                        if (leafInfo) {
+                            pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        } else {
+                            toastr.warning('台账清单列表已不存在'+ clinfo.code +',已更新变更清单列表');
+                            changeList.splice(index, 1);
+                            continue;
+                        }
+                    } else {
+                        pushbwmx = '0*;*' + (listinfo.quantity !== null ? listinfo.quantity : 0);
+                    }
+                    const bwmx = $('#table-list-select tr[data-lid="'+ clinfo.lid +'"]').attr('data-bwmx');
+                    if (bwmx) {
+                        const bwmxArray = bwmx.split('$#$');
+                        bwmxArray.push(pushbwmx);
+                        $('#table-list-select tr[data-lid="'+ clinfo.lid +'"]').attr('data-bwmx', bwmxArray.join('$#$'));
+                    } else {
+                        $('#table-list-select tr[data-lid="'+ clinfo.lid +'"]').attr('data-bwmx', pushbwmx);
+                    }
+                }
+            }
+        }
+    }
+}
+
+// 清单搜索隐藏清单table部分值
+function makeListTable(changeListData, showListData = changeListData) {
+    // 先加载台账数据
+    let listHtml = '';
+    let list_index = 1;
+    let gcl_index = 0;
+    for (const [index,gcl] of changeListData.entries()) {
+        const isShow = _.find(showListData, gcl);
+        $('#table-list-select tr').eq(index).css('display', (isShow ? 'table-row' : 'none'));
+    }
+}
+// 项目节搜索隐藏code-table部分值
+function makeCodeTable(search = '') {
+    if (search === '') {
+        $('#code-list tr').css('display', 'table-row');
+        return;
+    }
+    for(let i = 0; i < $('#code-list tr').length; i++) {
+        const length = $('#code-list tr').eq(i).children('td').length;
+        if (length === 8) {
+            const code = $('#code-list tr').eq(i).children('td').eq(0).text();
+            const name = $('#code-list tr').eq(i).children('td').eq(1).text();
+            const jldy = $('#code-list tr').eq(i).children('td').eq(5).text();
+            console.log(code, name, jldy, search, code.indexOf(search) !== -1 || name.indexOf(search) !== -1 || jldy.indexOf(search) !== -1);
+            const isShow = code.indexOf(search) !== -1 || name.indexOf(search) !== -1 || jldy.indexOf(search) !== -1;
+            $('#code-list tr').eq(i).css('display', (isShow ? 'table-row' : 'none'));
+        } else {
+            return;
+        }
+    }
+}
+
+function remakeChangeSpread() {
+    const newTableList = [];
+    // 获取选中的签约清单判断并插入到原有清单中
+    $('#table-list-select .table-success').each(function(){
+        let code = $(this).children('td').eq(1).text();
+        let name = $(this).children('td').eq(2).text();
+        let unit = $(this).children('td').eq(3).text();
+        let price = $(this).children('td').eq(4).text();
+        // let oamount = $(this).children('td').eq(5).text();
+
+        // 根据单位获取数量的位数,并得出
+        // let numdecimal = findDecimal(unit);
+
+        // let scnum = makedecimalzero(numdecimal);
+        let scnum = 0;
+        // let detail = $(this).attr('data-detail') != 0 ? $(this).attr('data-detail').split('_')[1] : '';
+        let lid = $(this).data('lid');
+        let lindex = $(this).data('index');
+        // 原清单和数量改变
+        let data_bwmx = $(this).attr('data-bwmx').split('$#$');
+
+        for (const b of data_bwmx) {
+            const oamount = b.split('*;*')[1] != '' ? b.split('*;*')[1] : 0;
+            let bwmx = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[2] : '';
+            let xmj_code = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[0] : '';
+            let xmj_jldy = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[1] : '';
+            let trlist = {
+                code,
+                name,
+                bwmx,
+                unit,
+                unit_price: price,
+                oamount,
+                camount: scnum,
+                detail: '',
+                lid,
+                xmj_code,
+                xmj_jldy,
+            };
+            const radionInfo = changeList.find(function (info) {
+                return info.code === code && (info.lid == lid || parseInt(info.lid) === parseInt(lindex)) && info.bwmx === bwmx;
+            });
+            if (radionInfo) {
+                trlist.camount = radionInfo.camount;
+                trlist.detail = radionInfo.detail;
+            }
+            newTableList.push(trlist);
+        }
+    });
+    const changeWhiteList = _.filter(changeList, function (item) {
+        return item.lid == 0;
+    });
+    console.log(newTableList);
+    changeList = newTableList.concat(changeWhiteList);
+}

+ 19 - 12
app/public/js/change_set.js

@@ -404,7 +404,7 @@ $(document).ready(() => {
         const isCheck = $(this).hasClass('table-success') ? true : false;
         const data_bwmx = $(this).attr('data-bwmx').split('$#$');
         const isDeal = $(this).data('gcl') !== undefined ? true : false;
-        let codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox"></td></tr>';
+        let codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'" gcl_id="0"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox"></td></tr>';
         if (isDeal) {
             const lid = $(this).data('lid');
             let gcl = _.find(gclGatherData, function (item) {
@@ -416,9 +416,10 @@ $(document).ready(() => {
             codeHtml = '';
             for (const leaf of gcl.leafXmjs) {
                 const quantity = leaf.quantity !== undefined && leaf.quantity !== null ? leaf.quantity : 0;
+                const gcl_id = leaf.gcl_id ? leaf.gcl_id : '0';
                 const bwmx = leaf.bwmx !== undefined ? leaf.bwmx : '';
-                const isChecked = data_bwmx.indexOf(leaf.code + '!_!' + (leaf.jldy ? leaf.jldy : '') + '!_!' + (bwmx !== '' ? bwmx : leaf.jldy ? leaf.jldy : '') + '*;*' + quantity) !== -1 && isCheck ? 'checked' : '';
-                codeHtml += '<tr quantity="' + quantity + '"><td>' + leaf.code + '</td>' +
+                const isChecked = data_bwmx.indexOf(leaf.code + '!_!' + (leaf.jldy ? leaf.jldy : '') + '!_!' + (leaf.gcl_id ? leaf.gcl_id : '0') + '!_!' + (bwmx !== '' ? bwmx : leaf.jldy ? leaf.jldy : '') + '*;*' + quantity) !== -1 && isCheck ? 'checked' : '';
+                codeHtml += '<tr quantity="' + quantity + '" gcl_id="' + gcl_id + '"><td>' + leaf.code + '</td>' +
                     '<td>' + (leaf.jldy ? leaf.jldy: '') + '</td>' +
                     '<td>' + (leaf.dwgc ? leaf.dwgc : '') + '</td>' +
                     '<td>' + (leaf.fbgc ? leaf.fbgc : '') + '</td>' +
@@ -429,7 +430,7 @@ $(document).ready(() => {
                     '></td></tr>';
             }
         } else if (!isDeal && isCheck) {
-            codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox" checked></td></tr>';
+            codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'" gcl_id="0"><td colspan="7" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox" checked></td></tr>';
         }
         $('#code-list').attr('data-index', $(this).children('td').eq(0).text());
         $('#code-input').val('');
@@ -451,7 +452,8 @@ $(document).ready(() => {
             $('#code-list input:checked').each(function () {
                 const tr = $(this).parents('tr');
                 const length = tr.children('td').length;
-                const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!' + tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                const gcl_id = tr.attr('gcl_id');
+                const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!' + tr.children('td').eq(1).text() + '!_!' + gcl_id + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
                 const quantity = tr.attr('quantity');
                 const de_qu = bwmx + '*;*' + quantity;
                 data_bwmx.push(de_qu);
@@ -466,7 +468,8 @@ $(document).ready(() => {
                 $('#code-list input:checked').each(function () {
                     const tr = $(this).parents('tr');
                     const length = tr.children('td').length;
-                    const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!'+ tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                    const gcl_id = tr.attr('gcl_id');
+                    const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!'+ tr.children('td').eq(1).text() + '!_!'+ gcl_id + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
                     const quantity = tr.attr('quantity');
                     const de_qu = bwmx + '*;*' + quantity;
                     data_bwmx.push(de_qu);
@@ -536,6 +539,7 @@ $(document).ready(() => {
         const lid = $(this).parents('tr').data('lid');
         const xmj_code = $(this).parents('tr').data('xmjcode') || '';
         const xmj_jldy = $(this).parents('tr').data('xmjjldy') || '';
+        const gcl_id = $(this).parents('tr').data('gclid') || '0';
         const isWhite = !isNaN(lid) ? true : false;
         const tr = $('#list tr[data-lid="' + lid + '"]').eq(0);
         const site = parseInt($(this).parents('td').data('site'));
@@ -566,6 +570,7 @@ $(document).ready(() => {
             trlist.push(0);
             trlist.push(xmj_code);
             trlist.push(xmj_jldy);
+            trlist.push(gcl_id);
             changelist.splice(index, 1, trlist.join('*;*'));
             $('#change-whitelist').val(changelist.join('^_^'));
         } else {
@@ -573,6 +578,7 @@ $(document).ready(() => {
             trlist.push(lid.split('_')[0]);
             trlist.push(xmj_code);
             trlist.push(xmj_jldy);
+            trlist.push(gcl_id);
             changelist.splice(index, 1, trlist.join('*;*'));
             $('#change-list').val(changelist.join('^_^'));
         }
@@ -720,7 +726,7 @@ function tableDataRemake(changeListData) {
                     });
                     console.log(leafInfo);
                     if (leafInfo) {
-                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.gcl_id ? leafInfo.gcl_id : '0') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                     } else {
                         toastr.warning('台账清单列表已不存在'+ clinfo[0] +',已更新变更清单列表');
                         changeList.splice(index, 1);
@@ -745,7 +751,7 @@ function tableDataRemake(changeListData) {
                         return (item.bwmx === undefined || item.bwmx === clinfo[2] || item.jldy === clinfo[2]) && (item.quantity !== null ? item.quantity === parseFloat(clinfo[5]) : 0 === parseFloat(clinfo[5]));
                     });
                     if (leafInfo) {
-                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.gcl_id ? leafInfo.gcl_id : '0') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                     } else {
                         toastr.warning('台账清单列表已不存在'+ clinfo[0] +',已更新变更清单列表');
                         changeList.splice(index, 1);
@@ -840,7 +846,6 @@ function makeCodeTable(search = '') {
             const code = $('#code-list tr').eq(i).children('td').eq(0).text();
             const name = $('#code-list tr').eq(i).children('td').eq(1).text();
             const jldy = $('#code-list tr').eq(i).children('td').eq(5).text();
-            console.log(code, name, jldy, search, code.indexOf(search) !== -1 || name.indexOf(search) !== -1 || jldy.indexOf(search) !== -1);
             const isShow = code.indexOf(search) !== -1 || name.indexOf(search) !== -1 || jldy.indexOf(search) !== -1;
             $('#code-list tr').eq(i).css('display', (isShow ? 'table-row' : 'none'));
         } else {
@@ -895,10 +900,11 @@ function maketablelist(status){
         let data_bwmx = $(this).attr('data-bwmx').split('$#$');
         for (const b of data_bwmx) {
             const oamount = b.split('*;*')[1] != '' ? b.split('*;*')[1] : 0;
-            let bwmx = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[2] : '';
+            let bwmx = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[3] : '';
             let xmj_code = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[0] : '';
             let xmj_jldy = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[1] : '';
-            let trlist = [code, name, bwmx, unit, price, oamount, scnum, '', lid, xmj_code, xmj_jldy];
+            let gcl_id = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[2] : '0';
+            let trlist = [code, name, bwmx, unit, price, oamount, scnum, '', lid, xmj_code, xmj_jldy, gcl_id];
             const radionInfo = radionList.find(function (item) {
                 const info = item.split('*;*');
                 return info[0] === code && (info[8] == lid || parseInt(info[8]) === parseInt(lindex)) && info[2] === bwmx;
@@ -928,11 +934,12 @@ function maketablelist(status){
         let lid = radionArray[8];
         let xmj_code = radionArray[9];
         let xmj_jldy = radionArray[10];
+        let gcl_id = radionArray[11];
         let sctotal = scnum !== '' && scnum !== '-' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),decimal) : '';
 
         // 根据单位获取数量的位数,并得出
         let numdecimal = findDecimal(unit);
-        html += '<tr class="clist clid" data-lid="' + lid + '_' + index + '" data-index="' + index + '" data-xmjcode="'+ xmj_code +'" data-xmjjldy="'+ xmj_jldy +'">' +
+        html += '<tr class="clist clid" data-lid="' + lid + '_' + index + '" data-index="' + index + '" data-xmjcode="'+ xmj_code +'" data-xmjjldy="'+ xmj_jldy +'" data-gclid="'+ gcl_id +'">' +
             '<td data-site="0">'+ code +'</td>' +
             '<td data-site="1">'+ name +'</td>' +
             '<td data-site="2">'+ bwmx +'</td>' +

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

@@ -637,7 +637,7 @@ const SpreadJsObj = {
         }
         if (colSetting.cellType === 'unit') {
             if (!sheet.extendCellType.unit) {
-                sheet.extendCellType.unit = this.CellType.getUnitCellType();
+                sheet.extendCellType.unit = colSetting.comboItems ? this.CellType.getUnitCellType(colSetting.comboItems) : this.CellType.getUnitCellType();
                 SpreadJsObj._addActivePaintEvents(sheet, sheet.extendCellType.unit);
             }
             sheet.getRange(-1, col, -1, 1).cellType(sheet.extendCellType.unit);
@@ -657,6 +657,13 @@ const SpreadJsObj = {
             }
             sheet.getRange(-1, col, -1, 1).cellType(sheet.extendCellType.datepicker);
         }
+        if (colSetting.cellType === 'mouseTouch') {
+            if (!sheet.extendCellType.mouseTouch) {
+                sheet.extendCellType.mouseTouch = this.CellType.getMouseTouchCellType();
+                SpreadJsObj._addActivePaintEvents(sheet, sheet.extendCellType.mouseTouch);
+            }
+            sheet.getRange(-1, col, -1, 1).cellType(sheet.extendCellType.mouseTouch);
+        }
         if (colSetting.formatter) {
             sheet.getRange(-1, col, -1, 1).formatter(colSetting.formatter);
             if(colSetting.type === 'Number') {
@@ -2079,12 +2086,12 @@ const SpreadJsObj = {
          * 获取 单位的CellType
          * @returns {GC.Spread.Sheets.CellTypes.ComboBox}
          */
-        getUnitCellType: function () {
+        getUnitCellType: function (items = ['m', 'km', 'm2', 'm3', 'dm3', 'kg', 't', 'm3·km',
+            '总额', '月' ,'项', '处' ,'个', '根', '棵', '块', '台', '系统', '延米', '每一试桩',
+            '桥长米', '公路公里', '株', '组', '座', '元', '工日', '套', '台班', '艘班', '亩', '片',
+            'm/处', 'm/道', 'm/座', 'm2/m', 'm3/m', 'm3/处', '根/米', 'm3/m2']) {
             let combo = this.getActiveComboCellType();
-            combo.itemHeight(10).items(['m', 'km', 'm2', 'm3', 'dm3', 'kg', 't', 'm3·km',
-                '总额', '月' ,'项', '处' ,'个', '根', '棵', '块', '台', '系统', '延米', '每一试桩',
-                '桥长米', '公路公里', '株', '组', '座', '元', '工日', '套', '台班', '艘班', '亩', '片',
-                'm/处', 'm/道', 'm/座', 'm2/m', 'm3/m', 'm3/处', '根/米', 'm3/m2']);
+            combo.itemHeight(10).items(items);
             return combo;
         },
         /**
@@ -2143,6 +2150,38 @@ const SpreadJsObj = {
                 }
             };
             return new DatePickerCellType();
+        },
+        /**
+         * 获取 鼠标移入变手势 CellType
+         * @returns {DatePickerCellType}
+         */
+        getMouseTouchCellType: function () {
+            const mouseTouchCellType = function () {};
+            mouseTouchCellType.prototype = new spreadNS.CellTypes.Base();
+            mouseTouchCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+                var xm = cellRect.x + cellRect.width / 2,
+                    ym = cellRect.y + cellRect.height / 2,
+                    size = 10;
+                var info = { x: x, y: y, row: context.row, col: context.col, cellRect: cellRect, sheetArea: context.sheetArea };
+                if (xm - size <= x && x <= xm + size && ym - size <= y && y <= ym + size) {
+                    info.isReservedLocation = true;
+                }
+                return info;
+            };
+            mouseTouchCellType.prototype.processMouseMove = function (hitInfo) {
+                var sheet = hitInfo.sheet;
+                var div = sheet.getParent().getHost();
+                var canvasId = div.id + "vp_vp";
+                var canvas = $("#"+canvasId)[0];
+                if (sheet && hitInfo.isReservedLocation) {
+                    canvas.style.cursor='pointer';
+                    return true;
+                }else{
+                    canvas.style.cursor='default';
+                }
+                return false;
+            };
+            return new mouseTouchCellType();
         }
     },
 

+ 2 - 1
app/public/js/zh_calc.js

@@ -118,8 +118,9 @@ const ZhCalc = (function () {
      * @returns {*}
      */
     function round(value, decimal) {
+        decimal = decimal ? parseInt(decimal) : 0;
         return value ? new Decimal(value).toDecimalPlaces(decimal).toNumber() : null;
     }
 
     return {add, sub, mul, div, round, isNonZero: zhBaseCalc.isNonZero}
-})();
+})();

+ 6 - 0
app/router.js

@@ -23,6 +23,8 @@ module.exports = app => {
     const wechatAuth = app.middlewares.wechatAuth();
     // 预付款中间件
     const advanceCheck = app.middlewares.advanceCheck();
+    // 变更令中间件
+    const changeCheck = app.middlewares.changeCheck();
     // 登入登出相关
     app.get('/login', 'loginController.index');
     app.get('/login/port', api2otherCheck, 'loginController.port');
@@ -330,6 +332,10 @@ module.exports = app => {
     // 变更单位管理
     app.post('/change/update/company', sessionAuth, 'changeController.updateCompany');
 
+    // 变更令 - 新版本
+    app.get('/tender/:id/change/:cid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'changeController.information');
+    app.post('/tender/:id/change/:cid/information/save', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, 'changeController.saveListsData');
+
     // 材料调差
     app.get('/tender/:id/measure/material', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.index');
     app.post('/tender/:id/measure/material/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.add');

+ 1 - 0
app/service/change.js

@@ -459,6 +459,7 @@ module.exports = app => {
                             spamount: clInfo[6],
                             xmj_code: clInfo[9] !== '' ? clInfo[9] : null,
                             xmj_jldy: clInfo[10] !== '' ? clInfo[10] : null,
+                            gcl_id: clInfo[11] !== '' ? clInfo[11] : '0',
                         };
                         if (clInfo[4] === '') {
                             delete clArray.unit_price;

+ 13 - 0
app/service/change_audit.js

@@ -455,6 +455,19 @@ module.exports = app => {
             return data;
         }
 
+        /**
+         * 获取 当前审核人
+         *
+         * @param {Number} cid - 期id
+         * @param {Number} times - 第几次审批
+         * @return {Promise<*>}
+         */
+        async getCurAuditor(cid, times = 1) {
+            const sql = 'SELECT * FROM ?? WHERE `cid` = ? and `status` = ? and `times` = ? and usite != 0';
+            const sqlParam = [this.tableName, cid, audit.flow.status.checking, times];
+            return await this.db.queryOne(sql, sqlParam);
+        }
+
     }
 
     return ChangeAudit;

+ 134 - 0
app/service/change_audit_list.js

@@ -23,6 +23,140 @@ module.exports = app => {
             this.tableName = 'change_audit_list';
         }
 
+        /**
+         * 添加空白变更清单
+         * @return {void}
+         */
+        async add(data) {
+            if (!this.ctx.tender || !this.ctx.change) {
+                throw '数据错误';
+            }
+            const insertData = {
+                tid: this.ctx.tender.id,
+                cid: this.ctx.change.cid,
+                lid: '0',
+                code: '',
+                name: '',
+                bwmx: '',
+                unit: '',
+                unit_price: null,
+                oamount: 0,
+                camount: 0,
+                samount: '',
+                detail: '',
+                spamount: 0,
+                xmj_code: null,
+                xmj_jldy: null,
+            };
+            // 新增工料
+            const result = await this.db.insert(this.tableName, insertData);
+            if (result.affectedRows === 0) {
+                throw '新增空白清单数据失败';
+            }
+            return await this.getDataById(result.insertId);
+        }
+
+        /**
+         * 删除变更清单
+         * @param {int} id 清单id
+         * @return {void}
+         */
+        async del(id) {
+            if (!this.ctx.tender || !this.ctx.change) {
+                throw '数据错误';
+            }
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 判断是否可删
+                await transaction.delete(this.tableName, { id });
+                // 重新算变更令总额
+                // await this.calcQuantityByML(transaction, mb_id);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 修改变更清单
+         * @param {Object} data 工料内容
+         * @param {int} order 期数
+         * @return {void}
+         */
+        async save(data, order) {
+            if (!this.ctx.tender || !this.ctx.change) {
+                throw '数据错误';
+            }
+
+            const transaction = await this.db.beginTransaction();
+            try {
+                // const mb_id = data.mb_id;
+                // delete data.mb_id;
+                await transaction.update(this.tableName, data);
+                // await this.calcQuantityByML(transaction, mb_id);
+                await this.calcCamountSum(transaction);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 修改变更清单 复制粘贴
+         * @param {Object} datas 修改内容
+         * @return {void}
+         */
+        async saveDatas(datas) {
+            if (!this.ctx.tender || !this.ctx.change) {
+                throw '数据错误';
+            }
+            // 判断是否可修改
+            // 判断t_type是否为费用
+            const transaction = await this.db.beginTransaction();
+            try {
+                // for (const data of datas) {
+                //     const mb_id = data.mb_id;
+                //     delete data.mb_id;
+                //     await transaction.update(this.tableName, data);
+                //     await this.calcQuantityByML(transaction, mb_id);
+                // }
+                await transaction.updateRows(this.tableName, datas);
+                await this.calcCamountSum(transaction);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async calcCamountSum(transaction) {
+            // const sql = 'SELECT SUM(ROUND(`camount`*`unit_price`, )) as total_price FROM ?? WHERE cid = ?';
+            // const sqlParam = [this.tableName, this.change.cid];
+            // const tp = await transaction.queryOne(sql, sqlParam);
+            // 防止小数位不精确,采用取值计算
+            const sql = 'SELECT unit_price, spamount FROM ?? WHERE cid = ?';
+            const sqlParam = [this.tableName, this.ctx.change.cid];
+            const changeList = await transaction.query(sql, sqlParam);
+            let total_price = 0;
+            for (const cl of changeList) {
+                total_price = this.ctx.helper.accAdd(total_price, this.ctx.helper.mul(cl.unit_price, cl.spamount, this.ctx.tender.info.decimal.tp));
+            }
+            const updateData = {
+                total_price,
+            };
+            const options = {
+                where: {
+                    cid: this.ctx.change.cid,
+                },
+            };
+            await transaction.update(this.ctx.service.change.tableName, updateData, options);
+        }
+
         async gatherBgBills(tid) {
             const sql = 'SELECT cb.code, cb.name, cb.unit, cb.unit_price, Round(Sum(cb.samount + 0), 6) as quantity' +
                 '  FROM ' + this.tableName + ' cb' +

+ 432 - 0
app/view/change/information.ejs

@@ -0,0 +1,432 @@
+<% include ../tender/tender_sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title"><!--收起详解目录添加类名 fluid -->
+        <div class="title-main d-flex"><!--工具-->
+            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <div>
+                <% if(auditStatus === auditConst.status.uncheck || auditStatus === auditConst.status.back) { %>
+                    <div class="d-inline-block">
+                        <a class="btn btn-sm btn-primary" href="#add-bj" data-toggle="modal" data-target="#add-bj">拷贝其他变更令数据</a>
+                    </div>
+                <% } %>
+                <% if (auditStatus === 1 || auditStatus === 2) { %>
+                    <div class="d-inline-block">
+                        <a href="#addlist" data-toggle="modal" class="btn btn-sm btn-light text-primary" id="open-list-modal" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-plus" aria-hidden="true"></i> 添加台账清单</a>
+                    </div>
+                    <div class="d-inline-block mr-3">
+                        <a href="javascript:void(0);" class="btn btn-sm btn-light text-primary" id="add-white-btn" data-original-title="添加清单"><i class="fa fa-plus" aria-hidden="true"></i> 添加空白清单</a>
+                    </div>
+                <% } %>
+                <div class="d-inline-block">
+                    <div class="custom-control custom-checkbox" style="line-height: normal;">
+                        <input type="checkbox" class="custom-control-input change-detail-checkbox" id="customCheck1">
+                        <label class="custom-control-label" for="customCheck1">变更详情</label>
+                    </div>
+                </div>
+                <% if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) { %>
+                    <div class="d-inline-block ml-3">
+                        <div class="custom-control custom-checkbox" style="line-height: normal;">
+                            <input type="checkbox" class="custom-control-input" id="show-table-detail">
+                            <label class="custom-control-label" for="show-table-detail">审批过程</label>
+                        </div>
+                    </div>
+                <% } %>
+            </div>
+            <div class="ml-auto">
+                <!--info状态区分-->
+                <% if (auditStatus === 1) { %>
+                    <a href="#sub-ap" data-category="up_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-primary btn-sm">上报审批</a>
+                <% } else if (auditStatus === 2) { %>
+                    <a href="#sub-sp2" data-category="up_change" data-toggle="modal" data-target="#sub-sp2" class="btn btn-primary btn-sm">重新上报</a>
+                <% } else if (auditStatus === 3) { %>
+                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted">审批退回</a>
+                <% } else if (auditStatus === 4) { %>
+                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-success btn-sm">审批完成</a>
+                <% } else if (auditStatus === 5) { %>
+                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-danger btn-sm">审批终止</a>
+                <% } else if (auditStatus === 6) { %>
+                    <a href="#sp-done" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
+                    <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
+                <% } else if (auditStatus === 7) { %>
+                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">审批中</a>
+                <% } %>
+                <% if (auditStatus === 4 && ctx.session.sessionUser.accountId === auditList[auditList.length-1].uid) { %>
+                    <% if (stageChangeNum === 0) { %>
+                        <!--重新审批-->
+                        <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-back" class="btn btn-warning btn-sm">重新审批</a>
+                    <% } else { %>
+                        <button class="btn btn-outline-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="已被调用">重新审批</button>
+                    <% } %>
+                <% } %>
+            </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-4">
+                <div class="sjs-bar-1">
+                    <ul class="nav nav-tabs">
+                        <li class="nav-item">
+                            <a class="nav-link active" data-toggle="tab" href="#bgxinxi" role="tab">变更信息</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="tab" href="#bgfujian" role="tab">附件</a>
+                        </li>
+                        <li class="nav-item ml-auto pt-1">
+                            <!--所有附件 翻页-->
+                            <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a>
+                            <a href="#" class=" ml-3"><i class="fa fa-chevron-left"></i></a> 1/10 <a href="#" class="mr-3"><i class="fa fa-chevron-right"></i></a>
+                            <a href="#addfujian" data-toggle="modal" class="btn btn-sm btn-light text-primary" data-placement="bottom" title="" data-original-title="上传附件"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="tab-content">
+                    <div class="tab-pane active" id="bgxinxi">
+                        <div class="sjs-sh-1" style="overflow-y: auto;">
+                            <% if (auditStatus === 1 || auditStatus === 2) { %>
+                            <form class="p-2" action="/tender/<%- change.tid %>/change/save?_csrf=<%= ctx.csrf %>" method="post" id="change_form">
+                                <div class="form-group">
+                                    <label><b class="text-danger">*&nbsp;</b>申请编号</label>
+                                    <a href="javascript:void(0);" class="pull-right reduction-code" data-toggle="tooltip" data-placement="bottom" title="" data-code="<%- change.code %>" data-original-title="重置"><i class="fa fa-repeat"></i></a>
+                                    <input class="form-control form-control-sm" name="code" value="<%- change.code %>" type="text">
+                                </div>
+                                <div class="form-group">
+                                    <label><b class="text-danger">*&nbsp;</b>工程名称</label>
+                                    <input class="form-control form-control-sm" name="name" value="<%- change.name %>" type="text">
+                                </div>
+                                <div class="form-group">
+                                    <label>桩号</label>
+                                    <input class="form-control form-control-sm" name="peg" value="<%- change.peg %>" type="text">
+                                </div>
+                                <div class="form-group">
+                                    <label>原设计图名称</label>
+                                    <input class="form-control form-control-sm" name="org_name" placeholder="" type="text" value="<%- change.org_name %>">
+                                </div>
+                                <div class="form-group">
+                                    <label>原图号</label>
+                                    <input class="form-control form-control-sm" name="org_code" placeholder="" type="text" value="<%- change.org_code %>">
+                                </div>
+                                <div class="form-group">
+                                    <label>变更设计图名称</label>
+                                    <input class="form-control form-control-sm" name="new_name" placeholder="" type="text" value="<%- change.new_name %>">
+                                </div>
+                                <div class="form-group">
+                                    <label>变更图号</label>
+                                    <input class="form-control form-control-sm" name="new_code" placeholder="" type="text" value="<%- change.new_code %>">
+                                </div>
+                                <div class="form-group">
+                                    <label><b class="text-danger">*&nbsp;</b>工程变更理由及内容</label>
+                                    <textarea class="form-control form-control-sm" name="content" rows="6"><%- change.content %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>工程变更合同依据</label>
+                                    <textarea class="form-control form-control-sm" name="basis" rows="6"><%- change.basis %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更工程量数量计算式</label>
+                                    <textarea class="form-control form-control-sm" name="expr" rows="2"><%- change.expr %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>备注</label>
+                                    <textarea class="form-control form-control-sm" name="memo" rows="3"><%- change.memo %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更类型</label>
+                                    <div class="checkbox">
+                                        <% const changeType = change.type !== null && change.type !== '' ? change.type.split(',') : '' %>
+                                        <% for (const t in changeConst.type) { %>
+                                            <% const cType = changeConst.type[t] %>
+                                            <label class="checkbox-inline">
+                                                <input value="<%- cType.value %>" name="type[]"
+                                                       type="checkbox"<% if (changeType.indexOf(cType.value.toString()) !== -1) { %> checked<% } %>><%- cType.name %>
+                                            </label>
+                                        <% } %>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更类别 </label>
+                                    <select class="form-control form-control-sm" name="class">
+                                        <% for (const c in changeConst.class) { %>
+                                            <% const cClass = changeConst.class[c] %>
+                                            <option value="<%- cClass.value %>"<% if (cClass.value === change.class) { %> selected<% } %>><%- cClass.name %></option>
+                                        <% } %>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更性质 </label>
+                                    <select class="form-control form-control-sm" name="quality">
+                                        <% for (const q in changeConst.quality) { %>
+                                            <% const cQuality = changeConst.quality[q] %>
+                                            <option value="<%- cQuality.value %>"<% if (cQuality.value === change.quality) { %> selected<% } %>><%- cQuality.name %></option>
+                                        <% } %>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更提出单位</label>
+                                    <a href="#editcompany" style="float:right;" class="" data-toggle="modal">编辑</a>
+                                    <select class="form-control form-control-sm" id="company" name="company">
+                                        <% for (const company of companyList) { %>
+                                            <option <% if (company.name === change.company) { %>selected<% } %>><%- company.name %></option>
+                                        <% } %>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>费用承担方</label>
+                                    <div class="radio">
+                                        <% for (const c in changeConst.charge) { %>
+                                            <% const cCharge = changeConst.charge[c] %>
+                                            <label class="radio-inline">
+                                                <input value="<%- cCharge.value %>" name="charge" type="radio"<% if (cCharge.value === change.charge) { %> checked<% } %>> <%- cCharge.name %>
+                                            </label>
+                                        <% } %>
+                                    </div>
+                                </div>
+                            </form>
+                            <% } else { %>
+                            <form class="p-2">
+                                <div class="form-group">
+                                    <label>申请编号</label>
+                                    <input class="form-control form-control-sm" value="<%- change.code %>" type="text" readonly>
+                                </div>
+                                <% if (auditStatus === 4) { %>
+                                    <div class="form-group">
+                                        <label>变更令号(批复编号)</label>
+                                        <input class="form-control form-control-sm" value="<%- change.p_code %>" type="text" readonly>
+                                    </div>
+                                <% } %>
+                                <div class="form-group">
+                                    <label>工程名称</label>
+                                    <input class="form-control form-control-sm" value="<%- change.name %>" type="text" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>桩号</label>
+                                    <input class="form-control form-control-sm" value="<%- change.peg %>" type="text" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>原设计图名称</label>
+                                    <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.org_name %>" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>原图号</label>
+                                    <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.org_code %>" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更设计图名称</label>
+                                    <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.new_name %>" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更图号</label>
+                                    <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.new_code %>" readonly>
+                                </div>
+                                <div class="form-group">
+                                    <label>工程变更理由及内容</label>
+                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- change.content %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>工程变更合同依据</label>
+                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- change.basis %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更工程量数量计算式</label>
+                                    <textarea class="form-control form-control-sm" rows="2" readonly><%- change.expr %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>备注</label>
+                                    <textarea class="form-control form-control-sm" rows="3" readonly><%- change.memo %></textarea>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更类型</label>
+                                    <div class="checkbox">
+                                        <% const changeType = change.type !== null && change.type !== '' ? change.type.split(',') : '' %>
+                                        <% for (const t in changeConst.type) { %>
+                                            <% const cType = changeConst.type[t] %>
+                                            <label class="checkbox-inline">
+                                                <% if (changeType.indexOf(cType.value.toString()) !== -1) { %>
+                                                    <input value="<%- cType.value %>" type="checkbox" disabled checked><%- cType.name %>
+                                                <% } %>
+                                            </label>
+                                        <% } %>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更类别 </label>
+                                    <select class="form-control form-control-sm" disabled>
+                                        <% for (const c in changeConst.class) { %>
+                                            <% const cClass = changeConst.class[c] %>
+                                            <% if (cClass.value === change.class) { %>
+                                                <option value="<%- cClass.value %>"><%- cClass.name %></option>
+                                            <% } %>
+                                        <% } %>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更性质 </label>
+                                    <select class="form-control form-control-sm" disabled>
+                                        <% for (const q in changeConst.quality) { %>
+                                            <% const cQuality = changeConst.quality[q] %>
+                                            <% if (cQuality.value === change.quality) { %>
+                                                <option value="<%- cQuality.value %>"><%- cQuality.name %></option>
+                                            <% } %>
+                                        <% } %>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>变更提出单位</label>
+                                    <select class="form-control form-control-sm" disabled>
+                                        <option><%- change.company %></option>
+                                    </select>
+                                </div>
+                                <div class="form-group">
+                                    <label>费用承担方</label>
+                                    <div class="radio">
+                                        <% for (const c in changeConst.charge) { %>
+                                            <% const cCharge = changeConst.charge[c] %>
+                                            <label class="radio-inline">
+                                                <% if (cCharge.value === change.charge) { %>
+                                                    <input value="<%- cCharge.value %>" type="radio" disabled checked> <%- cCharge.name %>
+                                                <% } %>
+                                            </label>
+                                        <% } %>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label>批复文号</label>
+                                    <input class="form-control form-control-sm" id="w_code" placeholder="" type="text" value="<%- change.w_code %>" <% if (auditStatus !== 6) { %>readonly<% } %>>
+                                </div>
+                            </form>
+                            <% } %>
+                        </div>
+                    </div>
+                    <div class="tab-pane" id="bgfujian">
+                        <div class="sjs-sh-1">
+                            <div class="p-2">
+                                <table class="table table-bordered">
+                                    <thead>
+                                    <tr>
+                                        <td width="25" style="background-color: #e9ecef;"><input type="checkbox" id="check-all-file" ></td>
+                                        <th width="50">序号</th>
+                                        <th>名称</th>
+                                        <th width="90">大小</th>
+                                        <th width="100">上传时间</th>
+                                        <th width="100">操作</th>
+                                    </tr>
+                                    </thead>
+                                    <tbody id="attList">
+                                    <% if (attList !== undefined && attList !== '') { %>
+                                        <% for (const [index,att] of attList.entries()) { %>
+                                            <tr>
+                                                <td width="25"><input type="checkbox" class="check-file" file-id=<%- att.id %>></td>
+                                                <td><%- index+1 %></td>
+                                                <td><a href="javascript: void(0);" class="file-atn" f-id="<%- att.id %>"><%- att.filename %><%- att.fileext %></a></td>
+                                                <td><%- ctx.helper.bytesToSize(att.filesize) %></td>
+                                                <td><%- moment(att.in_time * 1000).format('YYYY-MM-DD') %></td>
+                                                <td>
+                                                    <a href="/change/download/file/<%- att.id %>" class="btn btn-light btn-sm" title="下载"><span class="fa fa-download text-primary"></span></a>
+                                                    <% if (att.uid === uid && (auditStatus === 4 ? Boolean(att.extra_upload) : true )) { %>
+                                                        <a class="btn btn-light btn-sm delete-file" data-attid="<%- att.id %>" title="删除附件"><span class="fa fa-trash text-danger"></span></a>
+                                                    <% } %>
+                                                </td>
+                                            </tr>
+                                        <% } %>
+                                    <% } %>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="c-body col-8">
+                <div class="sjs-height-0" id="change-spread">
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    let table = '';
+    const totalPriceUnit = '<%- tpUnit %>';
+    const unitPriceUnit = '<%- upUnit %>';
+    const accountId = '<%- ctx.session.sessionUser.accountId %>';
+    const ledgeStatus = '<%- tender.ledger_status %>';
+    const ledgerConsts = JSON.parse('<%- JSON.stringify(ledgerConsts) %>');
+    const auditStatus = '<%- auditStatus %>'
+    const auditList = JSON.parse('<%- JSON.stringify(auditList) %>');
+    autoFlashHeight();
+    $('a[href="#sub-ap"').click(function() {
+        if (parseInt(ledgeStatus) === ledgerConsts.uncheck) {
+            $('#warning-ledger').modal('show');
+            return false
+        }
+    });
+    const readOnly = <%- change.readOnly %>;
+    const changeSpread = SpreadJsObj.createNewSpread($('#change-spread')[0]);
+    const changeSpreadSheet = changeSpread.getActiveSheet();
+</script>
+<script>
+    const whiteList = JSON.parse('<%- JSON.stringify(whiteList) %>');
+</script>
+<% if (auditStatus === 1 || auditStatus === 2) { %>
+<script>
+    let changeUnits = JSON.parse('<%- JSON.stringify(changeUnits) %>');
+    const precision = JSON.parse('<%- JSON.stringify(precision) %>');
+    changeUnits = _.map(changeUnits, 'unit');
+    changeUnits.push('');
+    const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
+    const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
+    const shenpi_status = <%- ctx.tender.info.shenpi.change %>;
+    const shenpiConst = JSON.parse('<%- JSON.stringify(shenpiConst) %>');
+    const changesUid = <%- change.uid %>;
+
+    let back_changeInfo = {
+        code: '<%- change.code %>',
+        name: '<%- change.name %>',
+        peg: '<%- change.peg %>',
+        org_name: '<%- change.org_name %>',
+        org_code: '<%- change.org_code %>',
+        new_name: '<%- change.new_name %>',
+        new_code: '<%- change.new_code %>',
+        content: '<%- ctx.helper.replaceRntoBr(change.content) %>',
+        basis: '<%- ctx.helper.replaceRntoBr(change.basis) %>',
+        expr: '<%- ctx.helper.replaceRntoBr(change.expr) %>',
+        memo: '<%- ctx.helper.replaceRntoBr(change.memo) %>',
+        type: '<%- change.type %>',
+        class: '<%- change.class %>',
+        quality: '<%- change.quality %>',
+        company: '<%- change.company %>',
+        charge: '<%- change.charge %>',
+    };
+    let changeInfo = Object.assign({}, back_changeInfo);
+    let changeList = JSON.parse('<%- JSON.stringify(changeList) %>');
+
+    const changeSpreadSetting = {
+        cols: [
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit'},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 120, formatter: '@', readOnly: 'readOnly.isEdit'},
+            {title: '变更部位', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 120, formatter: '@', readOnly: 'readOnly.isEdit'},
+            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: false},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: 'readOnly.isEdit', cellType: 'unit', comboItems: changeUnits},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isEdit', getValue: 'getValue.unit_price'},
+            {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'oamount', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isEdit', getValue: 'getValue.oamount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'oa_tp', hAlign: 2, width: 80, formatter: '@', type: 'Number', readOnly: true, getValue: 'getValue.oa_tp'},
+            {title: '申请变更增(+)减(-)|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', readOnly: false, getValue: 'getValue.camount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'ca_tp', hAlign: 2, width: 80, formatter: '@', type: 'Number', readOnly: true, getValue: 'getValue.ca_tp'},
+            {title: '操作', colSpan: '1', rowSpan: '2', field: 'del_list', hAlign: 1, width: 40, readOnly: true, cellType: 'mouseTouch', getValue: 'getValue.del_list'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: readOnly,
+    };
+</script>
+<script src="/public/js/change_information_set.js"></script>
+<% } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) { %>
+<!--<script src="/public/js/change_show.js"></script>-->
+<% } else if (auditStatus === 6) { %>
+<!--<script src="/public/js/change_approval.js"></script>-->
+<% } %>
+<!--<script src="/public/js/change_detail.js"></script>-->

文件差異過大導致無法顯示
+ 1104 - 0
app/view/change/information_modal.ejs


+ 20 - 0
config/web.js

@@ -676,6 +676,26 @@ const JsFiles = {
                 mergeFile: 'ledger',
             },
         },
+        change: {
+            information: {
+                files: [
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gcl_gather.js',
+                    '/public/js/jquery/jquery.form.min.js',
+                    // '/public/js/change_calculation.js',
+                    '/public/js/change_information.js',
+                ],
+                mergeFile: 'information',
+            },
+        },
     },
 };
 

+ 4 - 0
sql/update.sql

@@ -1,2 +1,6 @@
 ALTER TABLE `zh_tender`
 ADD COLUMN `copy_id` INT(10) NULL COMMENT '被拷贝标段id' AFTER `uuid`;
+
+
+ALTER TABLE `zh_change_audit_list` ADD `gcl_id` VARCHAR(255) NOT NULL DEFAULT '0' COMMENT '台账对应id(非准确)' AFTER `xmj_jldy`;
+UPDATE `zh_change_audit_list` SET `gcl_id`=`lid`;