Selaa lähdekoodia

调差及参建单位功能

laiguoran 3 vuotta sitten
vanhempi
commit
204b7b09d7

+ 2 - 2
app/base/base_service.js

@@ -139,7 +139,7 @@ class BaseService extends Service {
      * @param {Object} condition - 更新的条件筛选
      * @return {Boolean} - 返回更新结果
      */
-    async update(data, condition) {
+    async update(data, condition, transaction = false) {
         if (Object.keys(data).length <= 0 || Object.keys(condition).length <= 0) {
             return false;
         }
@@ -159,7 +159,7 @@ class BaseService extends Service {
         const whereString = where.join(' AND ');
 
         const sql = 'UPDATE ' + this.tableName + ' SET ' + paramString + ' WHERE ' + whereString;
-        const result = await this.db.query(sql, sqlParam);
+        const result = transaction ? await transaction.query(sql, sqlParam) : await this.db.query(sql, sqlParam);
         return result.affectedRows > 0;
     }
 

+ 93 - 3
app/controller/material_controller.js

@@ -81,6 +81,11 @@ module.exports = app => {
                     }
                     s.decimal = s.decimal ? JSON.parse(s.decimal) : materialConst.decimal;
                 }
+                if (lastMaterial && lastMaterial.status === auditConst.status.checked && ctx.session.sessionUser.accountId === ctx.tender.data.user_id && stages.length > 0) {
+                    renderData.lastMaterialList = lastMaterial.is_new ? await ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: ctx.tender.id } }) : await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
+                } else {
+                    renderData.lastMaterialList = null;
+                }
                 renderData.stages = stages;
                 renderData.openMaterialTax = openMaterialTax;
                 renderData.allMaterialTax = allMaterialTax;
@@ -166,7 +171,7 @@ module.exports = app => {
                 if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id) {
                     throw '您无权创建材料调差期';
                 }
-                const data = ctx.request.body;
+                const data = JSON.parse(ctx.request.body.data);
                 if (data.s_order === '') {
                     throw '没有选中计量期';
                 }
@@ -179,10 +184,12 @@ module.exports = app => {
                 if (!newMaterial) {
                     throw '新增材料调差期失败,请重试';
                 }
-                ctx.redirect('/tender/' + ctx.tender.id + '/measure/material/' + newMaterial.order);
+                // ctx.redirect('/tender/' + ctx.tender.id + '/measure/material/' + newMaterial.order);
+                ctx.body = { err: 0, msg: '', data: newMaterial };
             } catch (err) {
                 this.log(err);
-                ctx.redirect(ctx.request.header.referer);
+                // ctx.redirect(ctx.request.header.referer);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
 
@@ -479,6 +486,89 @@ module.exports = app => {
                 responseData.data.materialChecklistData = materialChecklistData.sort(function(a, b) {
                     return ctx.helper.compareCode(a.b_code, b.b_code);
                 });
+                const lastMaterial = await ctx.service.material.getLastestMaterial(ctx.tender.id, true);
+                if (!lastMaterial.is_new) {
+                    const materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
+                    const hadBillsList = [];
+                    for (const ml of materialListData) {
+                        const hb = _.find(hadBillsList, { gcl_id: ml.gcl_id, mb_id: ml.mb_id });
+                        if (!hb) {
+                            hadBillsList.push({
+                                gcl_id: ml.gcl_id,
+                                mb_id: ml.mb_id,
+                                order: ml.order,
+                                quantity: ml.quantity,
+                                expr: ml.expr,
+                            });
+                        }
+                    }
+                    // 批量插入并修改is_new值
+                    await ctx.service.materialListGcl.setData(lastMaterial.id, hadBillsList);
+                    // responseData.data.gclList = hadBillsList;
+                } else {
+                    const hadBillsList = await ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                    // responseData.data.gclList = hadBillsList;
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
+        /**
+         * 调差清单新建台账数据获取 (Post)
+         * @param {Object} ctx - egg全局变量
+         * @return {Promise<void>}
+         */
+        async loadGclData(ctx) {
+            try {
+                // const data = JSON.parse(ctx.request.body.data);
+                // const filter = data.filter.split(';');
+                const responseData = { err: 0, msg: '', data: {} };
+                const data = JSON.parse(ctx.request.body.data);
+                if (data.stage_id === '') {
+                    throw '没有选中计量期';
+                }
+                // 取所有已被调用的工料清单表
+                // responseData.data.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, ctx.material.id);
+                // responseData.data.materialNotJoinListData = await ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: ctx.material.id } });
+                // 获取清单数据
+                responseData.data.ledger = await ctx.service.ledger.getData(ctx.tender.id);
+                responseData.data.pos = await ctx.service.pos.getPosData({ tid: ctx.tender.id });
+                // 获取所选期数据并合并相加同类清单项
+                responseData.data.curLedgerData = await ctx.service.stageBills.getStagesData(ctx.tender.id, data.stage_id.join(','));
+                responseData.data.curPosData = await ctx.service.stagePos.getStagesData(ctx.tender.id, data.stage_id.join(','), 'list');
+
+                // 获取gclidlist值
+                const lastMaterial = await ctx.service.material.getLastestCompleteMaterial(ctx.tender.id);
+                // responseData.data.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
+                if (!lastMaterial.is_new) {
+                    const materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
+                    const hadBillsList = [];
+                    for (const ml of materialListData) {
+                        const hb = _.find(hadBillsList, { gcl_id: ml.gcl_id, mb_id: ml.mb_id });
+                        if (!hb) {
+                            hadBillsList.push({
+                                gcl_id: ml.gcl_id,
+                                mb_id: ml.mb_id,
+                                order: ml.order,
+                                quantity: ml.quantity,
+                                expr: ml.expr,
+                            });
+                        }
+                    }
+                    // 批量插入并修改is_new值
+                    await ctx.service.materialListGcl.setData(lastMaterial.id, hadBillsList);
+                    // responseData.data.gclList = hadBillsList;
+                }
+                const hadBillsList = await ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                responseData.data.gclList = hadBillsList;
+                // 获取清单设置已选清单
+                // const materialChecklistData = await ctx.service.materialChecklist.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                // responseData.data.materialChecklistData = materialChecklistData.sort(function(a, b) {
+                //     return ctx.helper.compareCode(a.b_code, b.b_code);
+                // });
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);

+ 172 - 0
app/controller/setting_controller.js

@@ -17,6 +17,8 @@ const projectLog = require('../const/project_log');
 const imType = require('../const/tender').imType;
 const S2b = require('../lib/s2b');
 const measureType = require('../const/tender').measureType;
+const sendToWormhole = require('stream-wormhole');
+const path = require('path');
 
 module.exports = app => {
 
@@ -107,6 +109,10 @@ module.exports = app => {
                 if (ctx.query.keyword) {
                     keyword = ctx.query.keyword;
                 }
+                let company = '';
+                if (ctx.query.company) {
+                    company = ctx.query.company;
+                }
 
                 const page = ctx.page;
                 const pageSize = ctx.pageSize;
@@ -146,6 +152,8 @@ module.exports = app => {
                     queryData: JSON.stringify(ctx.urlInfo.query),
                 };
 
+                const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: projectId } });
+
                 const renderData = {
                     projectData,
                     accountData,
@@ -154,6 +162,8 @@ module.exports = app => {
                     pageInfo,
                     keyword,
                     user_total,
+                    unitList,
+                    company,
                     // rule: JSON.stringify(frontRule),
                 };
                 await this.layout('setting/user.ejs', renderData, 'setting/user_modal.ejs');
@@ -214,6 +224,11 @@ module.exports = app => {
                     keyword = ctx.query.keyword;
                 }
 
+                let company = '';
+                if (ctx.query.company) {
+                    company = ctx.query.company;
+                }
+
                 // 获取数据规则
                 const page = ctx.page;
                 const pageSize = ctx.pageSize;
@@ -238,6 +253,8 @@ module.exports = app => {
                     queryData: JSON.stringify(ctx.urlInfo.query),
                 };
 
+                const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: projectId } });
+
                 const renderData = {
                     projectData,
                     accountData,
@@ -247,6 +264,8 @@ module.exports = app => {
                     permissionStr: JSON.stringify(permission),
                     pageInfo,
                     user_total,
+                    unitList,
+                    company,
                     // rule: JSON.stringify(frontRule),
                 };
                 await this.layout('setting/user_permission.ejs', renderData, 'setting/user_permission_modal.ejs');
@@ -257,6 +276,159 @@ module.exports = app => {
         }
 
         /**
+         * 项目权限 -- 参建单位(Get)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async userUnit(ctx) {
+            try {
+                // 获取项目数据
+                const projectId = ctx.session.sessionProject.id;
+                const projectData = await ctx.service.project.getDataById(projectId);
+                if (projectData === null) {
+                    throw '没有对应的项目数据';
+                }
+                if (ctx.session.sessionUser.is_admin === 0) {
+                    throw '没有访问权限';
+                }
+
+                const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: projectId } });
+                for (const u of unitList) {
+                    const accountList = await ctx.service.projectAccount.getAllDataByCondition({ where: { project_id: projectId, company: u.name } });
+                    u.account_num = accountList.length;
+                }
+
+                // 获取账号个数
+                const user_total = await ctx.service.projectAccount.count({ project_id: projectId });
+
+                const renderData = {
+                    projectData,
+                    accountGroup,
+                    unitList,
+                    user_total,
+                    fujianOssPath: ctx.app.config.fujianOssPath,
+                };
+                await this.layout('setting/user_unit.ejs', renderData, 'setting/user_unit_modal.ejs');
+            } catch (error) {
+                console.log(error);
+                ctx.redirect('/dashboard');
+            }
+        }
+
+        /**
+         * 项目设置 -- 单位新增设置(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async userUnitAdd(ctx) {
+            const projectData = ctx.session.sessionProject;
+            try {
+                // 验证数据
+                if (projectData.id === undefined) {
+                    throw '不存在对应的项目数据';
+                }
+
+                // 获取验证规则
+                const rule = ctx.service.constructionUnit.rule('add');
+                ctx.validate(rule);
+                ctx.request.body.pid = projectData.id;
+                const result = await ctx.service.constructionUnit.save(ctx.request.body);
+                if (!result) {
+                    throw '保存单位失败';
+                }
+
+                this.setMessage('保存单位成功', this.messageType.SUCCESS);
+                ctx.redirect('/' + ctx.controllerName + '/user/unit');
+            } catch (error) {
+                console.log(error);
+                this.setMessage(error.toString(), this.messageType.ERROR);
+                ctx.redirect(ctx.request.header.referer);
+            }
+        }
+
+        /**
+         * 项目设置 -- 单位编辑(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async userUnitSave(ctx) {
+            const projectData = ctx.session.sessionProject;
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            try {
+                // 验证数据
+                if (projectData.id === undefined) {
+                    throw '不存在对应的项目数据';
+                }
+                const data = JSON.parse(ctx.request.body.data);
+                switch (data.type) {
+                    case 'update':
+                        const post_data = {
+                            pid: projectData.id,
+                            id: data.id,
+                        };
+                        post_data[data.val_name] = data.val;
+                        if (data.name) post_data.name = data.name;
+                        const result = await ctx.service.constructionUnit.save(post_data);
+                        if (!result) {
+                            throw '保存单位失败';
+                        }
+                        if (post_data.name) {
+                            const accountList = await ctx.service.projectAccount.getAllDataByCondition({ where: { project_id: projectData.id, company: post_data.name } });
+                            responseData.data = { account_num: accountList.length };
+                        }
+                        break;
+                    case 'delete':
+                        const accountList = await ctx.service.projectAccount.getAllDataByCondition({ where: { project_id: projectData.id, company: data.name } });
+                        if (accountList.length > 0) {
+                            throw '该单位下还存在账号,无法删除';
+                        }
+                        await ctx.service.constructionUnit.del(data.id);
+                        break;
+                    case 'del-sign':
+                        const info = await ctx.service.constructionUnit.getDataById(data.id);
+                        if (info.sign_path) {
+                            await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + info.sign_path);
+                        }
+                        await ctx.service.constructionUnit.update({ sign_path: null }, { id: info.id });
+                        break;
+                    default:
+                        break;
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
+        async userUnitUpload(ctx) {
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            try {
+                const stream = await ctx.getFileStream();
+                const create_time = Date.parse(new Date()) / 1000;
+                const fileInfo = path.parse(stream.filename);
+                const filepath = `app/public/upload/sign/unit/qianzhang_${create_time + fileInfo.ext}`;
+                await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
+                await sendToWormhole(stream);
+                const result = await ctx.service.constructionUnit.update({ sign_path: filepath }, { id: stream.fields.id });
+                if (result) {
+                    responseData.data = { sign_path: filepath };
+                } else {
+                    throw '添加数据库失败';
+                }
+            } catch (err) {
+                this.log(err);
+                responseData.err = 1;
+                responseData.msg = err;
+            }
+            ctx.body = responseData;
+        }
+
+        /**
          * 项目设置 -- 账号启用和停用设置(Post)
          * @param ctx
          * @return {Promise<void>}

+ 16 - 5
app/public/js/material_checklist.js

@@ -162,14 +162,25 @@ $(document).ready(() => {
             // 判断是否已不存在工料清单,台账修改过后删除之
             if (!gcl) {
                 removeData.push(mc.id);
-            }
-            // 更新had_bills值
-            if (mc.had_bills === 1) {
-                if (_.indexOf(hadBillsidList, gcl.leafXmjs ? gcl.leafXmjs[0].gcl_id : null) === -1) {
-                    updateData.push({ id: mc.id, mid: materialID, had_bills: 0 });
+            } else {
+                // 更新had_bills值
+                const updateObj = { id: mc.id };
+                if (mc.had_bills === 1) {
+                    if (_.indexOf(hadBillsidList, gcl.leafXmjs ? gcl.leafXmjs[0].gcl_id : null) === -1) {
+                        updateObj.mid = materialID;
+                        updateObj.had_bills = 0;
+                        // updateData.push({ id: mc.id, mid: materialID, had_bills: 0 });
+                    }
+                }
+                // 更新工程量及台账金额
+                if (mc.quantity !== (gcl.quantity ? gcl.quantity : null)) {
+                    updateObj.quantity = gcl.quantity ? gcl.quantity : null;
+                    updateObj.total_price = gcl.total_price ? gcl.total_price : null;
                 }
+                if(!_.isEqual(updateObj,{ id: mc.id })) updateData.push(updateObj);
             }
         }
+        console.log(pushData, removeData, updateData);
         setChecklistData(pushData, removeData, updateData, true);
     });
     function setChecklistData(pushData, removeData, updateData = [], sendmsg = false) {

+ 55 - 4
app/public/js/material_list.js

@@ -203,7 +203,7 @@ $(document).ready(() => {
         readOnly: true,
     };
     // 加载清单数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
-    postData(window.location.pathname + '/load', {}, function (result) {
+    postData(window.location.pathname + '/load', {}, async function (result) {
         ledger = result.ledger;
         curLedgerData = result.curLedgerData;
         pos = result.pos;
@@ -214,15 +214,66 @@ $(document).ready(() => {
         // 解析清单汇总数据
         gclGatherModel.loadLedgerData(ledger, curLedgerData);
         gclGatherModel.loadPosData(pos, curPosData);
-        gclGatherData = gclGatherModel.gatherGclData().filter(item => {
-            return item.qc_qty || item.contract_qty
-        });
+        gclGatherData = gclGatherModel.gatherGclData();
         console.log(gclGatherData);
         if (openMaterialChecklist) {
+            const hadBillsidList = _.uniq(_.map(materialListData, 'gcl_id'));
+            console.log(hadBillsidList);
+            // 判断是否有修订影响到本次数据,并有几率修改清单设置页的值
+            const pushData = [];
+            const updateData = [];
+            for (const hb of hadBillsidList) {
+                const gcl = _.find(gclGatherData, function (item) {
+                    return item.leafXmjs && item.leafXmjs.length > 0 && _.findIndex(item.leafXmjs, { gcl_id : hb }) !== -1;
+                });
+                if (gcl) {
+                    const mc = _.find(materialChecklistData, { b_code: gcl.b_code, name: gcl.name, unit: gcl.unit, unit_price: gcl.unit_price });
+                    // const newOrder = _.indexOf(gclGatherData, gcl);
+                    // console.log(newOrder);
+                    if (!mc && _.findIndex(pushData, { b_code: gcl.b_code, name: gcl.name, unit: gcl.unit, unit_price: gcl.unit_price }) === -1) {
+                        pushData.push({ b_code: gcl.b_code, name: gcl.name, unit: gcl.unit, unit_price: gcl.unit_price, quantity: (gcl.quantity ? gcl.quantity : null), total_price: (gcl.total_price ? gcl.total_price : null), had_bills: 1 });
+                    }
+                }
+            }
+            const removeData = [];
+            for (const mc of materialChecklistData) {
+                const gcl = _.find(gclGatherData, { b_code: mc.b_code, name: mc.name, unit: mc.unit, unit_price: mc.unit_price });
+                // 判断是否已不存在工料清单,台账修改过后删除之
+                if (!gcl) {
+                    removeData.push(mc.id);
+                } else {
+                    // 更新had_bills值
+                    const updateObj = { id: mc.id };
+                    if (mc.had_bills === 1) {
+                        if (_.indexOf(hadBillsidList, gcl.leafXmjs ? gcl.leafXmjs[0].gcl_id : null) === -1) {
+                            updateObj.mid = materialID;
+                            updateObj.had_bills = 0;
+                            // updateData.push({ id: mc.id, mid: materialID, had_bills: 0 });
+                        }
+                    }
+                    // 更新工程量及台账金额
+                    if (mc.quantity !== (gcl.quantity ? gcl.quantity : null)) {
+                        updateObj.quantity = gcl.quantity ? gcl.quantity : null;
+                        updateObj.total_price = gcl.total_price ? gcl.total_price : null;
+                    }
+                    if(!_.isEqual(updateObj,{ id: mc.id })) updateData.push(updateObj);
+                }
+            }
+            console.log(pushData, removeData, updateData);
+            if (pushData.length > 0 || removeData.length > 0 || updateData.length > 0) {
+                // materialChecklistData = await postDataAsync('/tender/'+ tenderID +'/measure/material/'+ stage_order +'/checklist/save', { type: 'resetChecklist', pushData, removeData, updateData })
+            }
+            gclGatherData = gclGatherData.filter(item => {
+                return item.qc_qty || item.contract_qty
+            });
             // 取交集
             gclGatherData = _.filter(gclGatherData, function (item) {
                 return _.find(materialChecklistData, { b_code: item.b_code, name: item.name, unit: item.unit, unit_price: item.unit_price });
             });
+        } else {
+            gclGatherData = gclGatherData.filter(item => {
+                return item.qc_qty || item.contract_qty
+            });
         }
         calculateJiaCha(gclGatherData);
         SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);

+ 130 - 2
app/public/js/measure_material.js

@@ -235,7 +235,8 @@ $(function () {
             $('#s_order').val(order_array.join(','));
         }
     });
-
+    let interval;
+    let stop = false;
     // 提交表单判断
     $('#addMaterial').click(function () {
         $(this).attr('disabled', true);
@@ -245,8 +246,135 @@ $(function () {
             return false;
         }
         $(this).text('正在生成新一期数据中,请勿刷新本页!...');
-        $(this).parents('form').submit();
+        const _self = $(this);
+        const stage_id = [];
+        $('#add-qi input[name="stage_id[]"]:checked').each(function () {
+            stage_id.push(parseInt($(this).val()));
+        });
+        const newMaterialData = {
+            s_order: $('#s_order').val(),
+            period: $('#add-qi input[name="period"]').val(),
+            stage_id,
+        };
+        if (lastMaterialListNum === 0) {
+            console.log(newMaterialData);
+            postData(preUrl + '/measure/material/add', newMaterialData, function (result) {
+                window.location.href = preUrl + '/measure/material/' + result.order;
+            }, function () {
+                _self.attr('disabled', false).text('确认添加');
+            });
+            return;
+        }
+        $('#add-qi').modal('hide');
+        $('#okedit').modal('show');
+        interval = setInterval(progress, 50);
+        postData(preUrl + '/measure/material/gcl/load', { stage_id }, function (result) {
+            // console.log(result);
+            const ledger = result.ledger;
+            const curLedgerData = result.curLedgerData;
+            const pos = result.pos;
+            const curPosData = result.curPosData;
+            const gclList = result.gclList;
+            gclGatherModel.loadLedgerData(ledger, curLedgerData);
+            gclGatherModel.loadPosData(pos, curPosData);
+            const gclGatherData = gclGatherModel.gatherGclData();
+            // const gclGatherData = gclGatherModel.gatherGclData().filter(item => {
+            //     return item.qc_qty || item.contract_qty
+            // });
+            // 获取需要新增的工料关联清单
+            const insertGcl = [];
+            const removeGclList = [];
+            for (const g of gclList) {
+                const gcl = _.find(gclGatherData, function (item) {
+                    return item.leafXmjs && item.leafXmjs.length > 0 && _.findIndex(item.leafXmjs, { gcl_id : g.gcl_id }) !== -1;
+                });
+                if (gcl) {
+                    const ig = _.find(insertGcl, { gcl });
+                    if (ig) {
+                        if(_.findIndex(ig.bills, { mb_id: g.mb_id }) === -1) {
+                            ig.bills.push(g);
+                        }
+                    } else {
+                        insertGcl.push({
+                            bills: [g],
+                            gcl,
+                            leafXmjs: _.filter(gcl.leafXmjs, function(item) { return item.gather_qty !== undefined && item.gather_qty !== null }),
+                        })
+                    }
+                } else {
+                    removeGclList.push(g);
+                }
+            }
+            const insertList = [];
+            const insertGclList = [];
+            for (const one of insertGcl) {
+                if (one.leafXmjs && one.leafXmjs.length > 0) {
+                    for (const xmj of one.leafXmjs) {
+                        const newgcl = _.find(gclList, { gcl_id: xmj.gcl_id });
+                        for (const bill of one.bills) {
+                            insertList.push({
+                                gcl_id: xmj.gcl_id,
+                                mx_id: xmj.mx_id ? xmj.mx_id : null,
+                                xmj_id: xmj.id ? xmj.id : null,
+                                gather_qty: xmj.gather_qty,
+                                quantity: bill.quantity,
+                                expr: bill.expr,
+                                mb_id: bill.mb_id,
+                                order: bill.order,
+                            });
+                            if (!newgcl) {
+                                insertGclList.push({
+                                    gcl_id: xmj.gcl_id,
+                                    quantity: bill.quantity,
+                                    expr: bill.expr,
+                                    mb_id: bill.mb_id,
+                                    order: bill.order,
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+            // 可能需要新增list_gcl表
+            newMaterialData.material_list = insertList;
+            newMaterialData.insertGclList = insertGclList;
+            newMaterialData.removeGclList = removeGclList;
+            console.log(newMaterialData);
+            postData(preUrl + '/measure/material/add', newMaterialData, function (result) {
+                window.location.href = preUrl + '/measure/material/' + result.order;
+            }, function () {
+                stop = true;
+                // clearInterval(interval);
+                // console.log(_self.parents('div[id="add-qi"]'));
+                // $('#add-qi').modal('show');
+                // $('#okedit').modal('hide');
+                // _self.parents('div[id="add-qi"]').modal('show');
+                _self.attr('disabled', false).text('确认添加');
+            });
+            // return;
+        });
+        // $(this).parents('form').submit();
     });
+
+    let value = 0;
+    function progress(){
+        if (stop) {
+            setTimeout(function () {
+                $('#add-qi').modal('show');
+                $('#okedit').modal('hide');
+                value = 0;
+                clearInterval(interval);
+            }, 500);
+        }
+        if (value < 100) {
+            value = parseInt(value) + 1;
+            $("#material-progress").css("width", value + "%").text(value + "%");
+        } else if (value === 100) {
+            value = parseInt(value) + 1;
+            value = 30;
+        }
+    };
+
     let editPeriod = null;
     $('.edit-material').on('click', function () {
         const order = parseInt($(this).data('order'));

+ 236 - 8
app/public/js/setting.js

@@ -25,12 +25,12 @@ $(document).ready(() => {
         const account = $(this).data('account');
         $('#edit-user input[name="account"]').val(account.account);
         $('#edit-user input[name="name"]').val(account.name);
-        $('#edit-user input[name="company"]').val(account.company);
+        $('#edit-user select[name="company"]').val(account.company);
         $('#edit-user input[name="role"]').val(account.role);
         $('#edit-user input[name="mobile"]').val(account.mobile);
         $('#edit-user input[name="telephone"]').val(account.telephone);
         $('#edit-user input[name="id"]').val(account.id);
-        $('#edit-user select[name="account_group"]').val(account.account_group);
+        $('#edit-user input[name="account_group"]').val(account.account_group);
         $('#edit-user input[class="account-check"]').val(account.account);
         $('#edit-user input[data-mobile="auth-mobile"]').val(account.auth_mobile);
         $('#edit-user input[name="mobile"]').attr('readOnly', account.bind === 1);
@@ -45,6 +45,13 @@ $(document).ready(() => {
         $('#edit-password input[name="reset_password"]').val('');
     });
 
+    // 选择单位自动配置账号组
+    $('select[name="company"]').change(function () {
+        const company = $(this).val();
+        const oneUnit = _.find(unitList, { name: company });
+        $(this).siblings('input[name="account_group"]').val(oneUnit ? oneUnit.type : 7);
+    });
+
     // 分配随机密码
     $("#rand-password").click(function() {
         const password = randPassword();
@@ -196,10 +203,214 @@ $(document).ready(() => {
     // 设置页显示数目
     $('.nav-tabs .nav-link').each(function () {
         const pageSize = getLocalCache('account-pageSize') ? getLocalCache('account-pageSize') : '';
-        if (getLocalCache('account-pageSize') && $(this).attr('href').indexOf('pageSize') === -1) {
+        if (getLocalCache('account-pageSize') && $(this).attr('href').indexOf('pageSize') === -1 && $(this).attr('href').indexOf('unit') === -1) {
             $(this).attr('href', $(this).attr('href') + '?pageSize=' + getLocalCache('account-pageSize'));
         }
     });
+    // 设置页显示数目
+    $('#user-list .list-group-item').each(function (k,v) {
+        const pageSize = getLocalCache('account-pageSize') ? getLocalCache('account-pageSize') : '';
+        if (pageSize) {
+            $(this).attr('href', $(this).attr('href') + '&pageSize=' + pageSize);
+        }
+    })
+
+    // 参建单位页切换单位右侧显示
+    $('#unit_list tr').click(function () {
+        const id = parseInt($(this).data('id'));
+        const one = _.find(unitList, { id });
+        if (one) {
+            $(this).siblings('tr').removeClass('table-warning');
+            $(this).addClass('table-warning');
+            $('#unit_name').val(one.name);
+            $('#unit_corporation').val(one.corporation);
+            $('#unit_credit_code').val(one.credit_code);
+            $('#unit_tel').val(one.tel);
+            $('#unit_website').val(one.website);
+            $('#unit_region').val(one.region);
+            $('#unit_address').val(one.address);
+            $('#unit_basic').val(one.basic);
+            $('#unit_type').val(one.type);
+            if(one.sign_path) {
+                $('#sign-show').html('<img src="' + fujianOssPath + one.sign_path + '" width="120">');
+                $('#delete-sign').show();
+                $('#upload-sign').hide();
+            } else {
+                $('#sign-show').html('');
+                $('#delete-sign').hide();
+                $('#upload-sign').show();
+            }
+            oneUnit = one;
+        }
+    });
+
+    // 参建单位编辑
+    // 回车提交
+    $('#one_unit input').on('keypress', function () {
+        if(window.event.keyCode === 13) {
+            $(this).blur();
+        }
+    });
+
+    $('#one_unit input').blur(function () {
+        console.log('hello');
+        const val_name = $(this).data('name');
+        let val = _.trim($(this).val()) !== '' ? _.trim($(this).val()) : null;
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        switch(val_name) {
+            case 'name':
+                if(val && val.length > 100) {
+                    toastr.error('单位名称超过100个字,请缩减名称');
+                    $(this).val(oneUnit[val_name]);
+                    return false;
+                }
+                const tongming = _.find(unitList, { name: val });
+                if (tongming && tongming.id !== oneUnit.id) {
+                    toastr.error('单位名称不能重复');
+                    $(this).val(oneUnit[val_name]);
+                    return false;
+                }
+                break;
+            default:
+                if(val && val.length > 255) {
+                    toastr.error('超出字段范围,请缩减');
+                    $(this).val(oneUnit[val_name]);
+                    return false;
+                }
+                break;
+        }
+        if(oneUnit[val_name] !== val) {
+            const _self = $(this);
+            postData('/setting/user/unit/save', { type: 'update', id: oneUnit.id, val_name, val}, function (result) {
+                oneUnit[val_name] = val;
+                _self.val(oneUnit[val_name]);
+                if (val_name === 'name') {
+                    oneUnit.account_num = result.account_num;
+                    $('#unit_list tr[class="table-warning"]').find('a').text(oneUnit[val_name]);
+                    $('#unit_list tr[class="table-warning"]').children('td').eq(2).text(result.account_num);
+                }
+            }, function () {
+                _self.val(oneUnit[val_name]);
+            })
+        } else {
+            $(this).val(oneUnit[val_name]);
+        }
+    });
+
+    $('#one_unit textarea').blur(function () {
+        const val_name = $(this).data('name');
+        let val = _.trim($(this).val()) !== '' ? _.trim($(this).val()) : null;
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        if(oneUnit[val_name] !== val) {
+            const _self = $(this);
+            postData('/setting/user/unit/save', { type: 'update', id: oneUnit.id, val_name, val}, function (result) {
+                oneUnit[val_name] = val;
+                _self.val(oneUnit[val_name]);
+                $('#unit_list tr[class="table-warning"]').children('td').eq(4).text(oneUnit[val_name]);
+            }, function () {
+                _self.val(oneUnit[val_name]);
+            })
+        } else {
+            $(this).val(oneUnit[val_name]);
+        }
+    });
+
+    $('#one_unit select').change(function () {
+        const val_name = $(this).attr('data-name');
+        let val = _.trim($(this).val()) !== '' ? _.trim($(this).val()) : null;
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        if(oneUnit[val_name] !== val) {
+            const _self = $(this);
+            postData('/setting/user/unit/save', { type: 'update', id: oneUnit.id, name: oneUnit.name, val_name, val}, function (result) {
+                oneUnit[val_name] = val;
+                _self.val(oneUnit[val_name]);
+                $('#unit_list tr[class="table-warning"]').children('td').eq(3).text(accountGroup[parseInt(oneUnit[val_name])]);
+            }, function () {
+                _self.val(oneUnit[val_name]);
+            })
+        } else {
+            $(this).val(oneUnit[val_name]);
+        }
+    });
+
+    // 删除单位弹窗
+    $('#del-modal-btn').click(function () {
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        if (oneUnit.account_num === 0) {
+            $('.del-btn').show();
+            $('.not-del-btn').hide();
+        } else {
+            $('.del-btn').hide();
+            $('.not-del-btn').show();
+        }
+    });
+
+    // 删除单位
+    $('#delete-unit').click(function () {
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        postData('/setting/user/unit/save', { type: 'delete', name: oneUnit.name, id: oneUnit.id }, function (result) {
+            window.location.href = '/setting/user/unit';
+        })
+    });
+
+    // 上传签章
+    $('#sign-upload').change(function () {
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        const file = this.files[0];
+        const ext = file.name.toLowerCase().split('.').splice(-1)[0];
+        const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
+        if (!imgStr.test(ext)) {
+            toastr.error('请上传正确的图片格式文件');
+            return
+        }
+        if ($(this).val()) {
+            const formData = new FormData();
+            formData.append('file', this.files[0]);
+            formData.append('id', oneUnit.id);
+            postDataWithFile('/setting/user/unit/upload', formData, function (result) {
+                const html = '<img src="'+ fujianOssPath + result.sign_path +'" width="120">';
+                $('#sign-show').html(html);
+                $('#sign-upload').val('');
+                oneUnit.sign_path = result.sign_path;
+                $('#upload-sign').hide();
+                $('#delete-sign').show();
+                toastr.success('上传成功');
+            });
+        }
+    });
+
+    // 移除签章
+    $('#delete-sign').click(function () {
+        if (!oneUnit) {
+            toastr.error('所选单位有误,请重新选择');
+            return false;
+        }
+        postData('/setting/user/unit/save', { type: 'del-sign', id: oneUnit.id }, function (result) {
+            $('#sign-show').html('');
+            toastr.warning('已移除');
+            oneUnit.sign_path = null;
+            $('#upload-sign').show();
+            $('#delete-sign').hide();
+        })
+    });
 });
 
 function checkPasswordForm() {
@@ -226,7 +437,7 @@ function checkPasswordForm() {
 function checkUserForm(status) {
     try {
         if (status === 'add') {
-            if ($('#add-user select[name="account_group"]').val() == 0) {
+            if ($('#add-user input[name="account_group"]').val() == 0) {
                 throw '请选择账号组';
             }
             if ($('#add-user input[name="account"]').val() == '' || $('#add-user input[name="account"]').hasClass('is-invalid')) {
@@ -241,8 +452,8 @@ function checkUserForm(status) {
             if ($('#add-user input[name="name"]').val() == '') {
                 throw '姓名不能为空';
             }
-            if ($('#add-user input[name="company"]').val() == '') {
-                throw '单位名称不能为空';
+            if (_.findIndex(unitList, $('#add-user select[name="company"]').val()) === -1) {
+                throw '请选择单位名称';
             }
             if ($('#add-user input[name="role"]').val() == '') {
                 throw '职位名称不能为空';
@@ -262,8 +473,8 @@ function checkUserForm(status) {
             if ($('#edit-user input[name="name"]').val() == '') {
                 throw '姓名不能为空';
             }
-            if ($('#edit-user input[name="company"]').val() == '') {
-                throw '单位名称不能为空';
+            if (_.findIndex(unitList, $('#edit-user select[name="company"]').val()) === -1) {
+                throw '请选择单位名称';
             }
             if ($('#edit-user input[name="role"]').val() == '') {
                 throw '职位名称不能为空';
@@ -281,6 +492,23 @@ function checkUserForm(status) {
 }
 
 /**
+ * 表单检测
+ */
+function checkUnitForm() {
+    try {
+        if ($('#add-company input[name="name"]').val() == '') {
+            throw '单位名称不能为空';
+        }
+        if ($('#add-company select[name="type"]').val() == 0) {
+            throw '请选择类型';
+        }
+    } catch (err) {
+        toastr.error(err);
+        return false;
+    }
+}
+
+/**
  * 随机密码
  */
 function randPassword() {

+ 6 - 1
app/router.js

@@ -80,6 +80,10 @@ module.exports = app => {
     // 账号设置
     app.get('/setting/user', sessionAuth, 'settingController.user');
     app.get('/setting/user/permission/set', sessionAuth, 'settingController.userPermissionSet');
+    app.get('/setting/user/unit', sessionAuth, 'settingController.userUnit');
+    app.post('/setting/user/unit/add', sessionAuth, 'settingController.userUnitAdd');
+    app.post('/setting/user/unit/save', sessionAuth, 'settingController.userUnitSave');
+    app.post('/setting/user/unit/upload', sessionAuth, 'settingController.userUnitUpload');
     // 账号停用和启用
     app.post('/setting/user/switch', sessionAuth, 'settingController.userSwitch');
     app.post('/setting/user/add', sessionAuth, datetimeFill, 'settingController.addUser');
@@ -539,7 +543,8 @@ module.exports = app => {
     app.post('/tender/:id/measure/material/:order/file/find', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.getCurMatericalFiles');
     app.post('/tender/:id/measure/material/:order/file/delete', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.deleteFile');
     app.post('/tender/:id/measure/material/:order/file/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.downloadZip');
-
+    // 调差新建期数据获取
+    app.post('/tender/:id/measure/material/gcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.loadGclData');
     // 个人账号相关
     app.get('/profile/info', sessionAuth, 'profileController.info');
     app.get('/profile/sms', sessionAuth, 'profileController.sms');

+ 117 - 0
app/service/construction_unit.js

@@ -0,0 +1,117 @@
+'use strict';
+
+/**
+ * Created by EllisRan on 2020/3/3.
+ */
+
+const BaseService = require('../base/base_service');
+
+module.exports = app => {
+
+    class ConstructionUnit extends BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'construction_unit';
+            this.dataId = 'id';
+        }
+
+        /**
+         * 数据验证规则
+         *
+         * @param {String} scene - 场景
+         * @return {Object} - 返回数据
+         */
+        rule(scene) {
+            let rule = {};
+            switch (scene) {
+                case 'add':
+                    rule = {
+                        name: { type: 'string', required: true },
+                        type: { type: 'string', required: true },
+                    };
+                    break;
+                default:
+                    break;
+            }
+            return rule;
+        }
+
+        /**
+         * 修改单位数据
+         *
+         * @param {Object} data - post过来的数据
+         * @return {Boolean} - 返回修改结果
+         */
+        async save(data) {
+            if (data._csrf_j !== undefined) {
+                delete data._csrf_j;
+            }
+            const id = data.id !== undefined ? parseInt(data.id) : 0;
+            const transaction = await this.db.beginTransaction();
+            try {
+                if (id > 0) {
+                    // 修改操作时
+                    delete data.create_time;
+                    data.id = id;
+                } else {
+                    // 重名检测
+                    const accountData = await this.db.select(this.tableName, {
+                        where: {
+                            name: data.name,
+                            pid: data.pid,
+                        },
+                    });
+                    if (accountData.length > 0) {
+                        throw '已存在对应的单位名';
+                    }
+                    data.create_time = new Date();
+                }
+                // 并修改用户的用户组及单位名称
+                const updateRow = {};
+                if (data.name) updateRow.company = data.name;
+                if (data.type) updateRow.account_group = data.type;
+                if (!this._.isEmpty(updateRow)) {
+                    const info = id !== 0 ? await this.getDataById(id) : null;
+                    await this.ctx.service.projectAccount.update(updateRow, {
+                        project_id: data.pid,
+                        company: info ? info.name : data.name,
+                    }, transaction);
+                    // egg 自带的update方法无法使用UPDATE zh_project_account SET company = ? WHERE project_id = ? AND company = ? ,未知原因
+                    // await transaction.update(this.ctx.service.projectAccount.tableName, updateRow,
+                    //     {
+                    //         where: {
+                    //             project_id: data.pid,
+                    //             company: info ? info.name : data.name,
+                    //         },
+                    //     }
+                    // );
+                }
+                const operate = id === 0 ? await transaction.insert(this.tableName, data) :
+                    await transaction.update(this.tableName, data);
+                transaction.commit();
+                const result = operate.affectedRows > 0;
+                return result;
+            } catch (e) {
+                transaction.rollback();
+            }
+        }
+
+        async del(id) {
+            // 先删除签章oss地址
+            const info = await this.getDataById(id);
+            if (info.sign_path) {
+                await this.ctx.app.fujianOss.delete(this.ctx.app.config.fujianOssFolder + info.sign_path);
+            }
+            // 删除单位
+            return await this.db.delete(this.tableName, { id });
+        }
+    }
+    return ConstructionUnit;
+};

+ 6 - 1
app/service/material.js

@@ -148,6 +148,7 @@ module.exports = app => {
                 s_order: data.s_order,
                 material_tax: this.ctx.session.sessionProject.page_show.openMaterialTax,
                 decimal: preMaterial && preMaterial.decimal ? preMaterial.decimal : JSON.stringify(materialConst.decimal),
+                is_new: 1,
             };
             const transaction = await this.db.beginTransaction();
             try {
@@ -174,7 +175,10 @@ module.exports = app => {
                     const preNotJoinList = await this.ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: this.ctx.tender.id, mid: preMaterial.id } });
                     await this.ctx.service.materialListNotjoin.copyNewStageNotJoinList(transaction, preNotJoinList, newMaterial.id);
                     // 复制调差清单工料关联表
-                    await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial);
+                    // await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial);
+                    await this.ctx.service.materialList.copyPreMaterialList2(transaction, data.material_list, preNotJoinList, newMaterial);
+                    // 新增或删除list_gcl表
+                    await this.ctx.service.materialListGcl.insertOrDelGcl(transaction, data.insertGclList, data.removeGclList, newMaterial.id);
                     // 修改本期应耗数量值和有效价差,需要剔除不参与调差的清单数据,并返回总金额
                     const [m_tp, m_tax_tp] = await this.ctx.service.materialBills.updateNewMaterial(transaction, this.ctx.tender.id, newMaterial.id, this.ctx, newMaterial.stage_id, JSON.parse(newMaterial.decimal));
                     // 修改现行价格指数,并返回调差基数json
@@ -225,6 +229,7 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.materialAudit.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialBills.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialList.tableName, { mid: id });
+                await transaction.delete(this.ctx.service.materialListGcl.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialListNotjoin.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialBillsHistory.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialFile.tableName, { mid: id });

+ 30 - 0
app/service/material_list.js

@@ -292,6 +292,36 @@ module.exports = app => {
             return copyMLArray.length !== 0 ? await transaction.insert(this.tableName, copyMLArray) : true;
         }
 
+        /**
+         * 复制上一期并生成新一期清单工料关联,计算新一期小计值
+         * @param transaction
+         * @param preMaterial
+         * @param newMid
+         * @return {Promise<void>}
+         */
+        async copyPreMaterialList2(transaction, materialListData, notJoinList, newMaterial) {
+            const copyMLArray = [];
+            for (const ml of materialListData) {
+                const is_join = this._.find(notJoinList, { gcl_id: ml.gcl_id, xmj_id: ml.xmj_id, mx_id: ml.mx_id });
+                const newMaterialList = {
+                    tid: newMaterial.tid,
+                    order: ml.order,
+                    mid: newMaterial.id,
+                    mb_id: ml.mb_id,
+                    gcl_id: ml.gcl_id,
+                    xmj_id: ml.xmj_id,
+                    mx_id: ml.mx_id,
+                    gather_qty: ml.gather_qty,
+                    quantity: ml.quantity,
+                    expr: ml.expr,
+                    is_join: is_join ? 1 : 0,
+                    in_time: new Date(),
+                };
+                copyMLArray.push(newMaterialList);
+            }
+            return copyMLArray.length !== 0 ? await transaction.insert(this.tableName, copyMLArray) : true;
+        }
+
 
         /**
          * 添加工料清单关联(多清单对应)

+ 68 - 0
app/service/material_list_gcl.js

@@ -0,0 +1,68 @@
+'use strict';
+/**
+ * 清单设置 数据模型
+ * @author LanJianRong
+ * @date 2020/6/30
+ * @version
+ */
+
+module.exports = app => {
+    class MaterialListGcl extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'material_list_gcl';
+        }
+
+        async setData(mid, data) {
+            if (!this.ctx.tender) {
+                throw '数据错误';
+            }
+            const transaction = await this.db.beginTransaction();
+            try {
+                const insertArray = [];
+                for (const d of data) {
+                    insertArray.push({
+                        tid: this.ctx.tender.id,
+                        mid,
+                        order: d.order,
+                        gcl_id: d.gcl_id,
+                        mb_id: d.mb_id,
+                        quantity: d.quantity,
+                        expr: d.expr,
+                    });
+                }
+                if (insertArray.length > 0) await transaction.insert(this.tableName, insertArray);
+                await transaction.update(this.ctx.service.material.tableName, { id: mid, is_new: 1 });
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                console.log(err);
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async insertOrDelGcl(transaction, insertGclList, removeGclList, mid) {
+            if (insertGclList.length > 0) {
+                for (const gcl of insertGclList) {
+                    gcl.tid = this.ctx.tender.id;
+                    gcl.mid = mid;
+                }
+                await transaction.insert(this.tableName, insertGclList);
+            }
+            if (removeGclList.length > 0) {
+                for (const gcl of removeGclList) {
+                    await transaction.delete(this.tableName, { id: gcl.id });
+                }
+            }
+        }
+    }
+    return MaterialListGcl;
+};
+

+ 8 - 0
app/service/project_account.js

@@ -767,6 +767,14 @@ module.exports = app => {
                 operate: '=',
             });
 
+            // 单位名称筛选
+            if (data.company !== undefined && data.company !== '') {
+                this.sqlBuilder.setAndWhere('company', {
+                    value: this.db.escape(data.company),
+                    operate: '=',
+                });
+            }
+
             // 名字筛选
             if (data.keyword !== undefined && data.keyword !== '') {
                 this.sqlBuilder.setNewOrWhere([{

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

@@ -450,6 +450,7 @@
     };
     let changeInfo = Object.assign({}, back_changeInfo);
     let changeUsedData = JSON.parse(unescape('<%- escape(JSON.stringify(changeUsedData)) %>'));
+    console.log(changeUsedData);
 </script>
 <script src="/public/js/change_information_set.js?202001181"></script>
 <script src="/public/js/change_audit.js"></script>
@@ -466,6 +467,7 @@
     const aidList = _.map(auditList2, 'uid');
     aidList.splice(0, 1);
     let changeUsedData = JSON.parse(unescape('<%- escape(JSON.stringify(changeUsedData)) %>'));
+    // console.log(changeUsedData);
     const changeLedgerList = JSON.parse(unescape('<%- escape(JSON.stringify(changeLedgerList)) %>'));
     const changePosList = JSON.parse(unescape('<%- escape(JSON.stringify(changePosList)) %>'));
 </script>

+ 6 - 0
app/view/material/index.ejs

@@ -92,12 +92,18 @@
     </div>
 </div>
 <script src="/public/js/sub_menu.js"></script>
+<script src="/public/js/decimal.min.js"></script>
+<script src="/public/js/zh_calc.js"></script>
+<script src="/public/js/path_tree.js"></script>
+<script src="/public/js/gcl_gather.js"></script>
 <script src="/public/js/datepicker/datepicker.min.js"></script>
 <script src="/public/js/datepicker/datepicker.zh.js"></script>
 
 <script>
     const tenderId = '<%- ctx.tender.id %>';
     const auditConst = JSON.parse('<%- auditConst2 %>');
+    const preUrl = JSON.parse(unescape('<%- escape(JSON.stringify(preUrl)) %>'));
+    const lastMaterialListNum = parseInt('<%- lastMaterialList ? lastMaterialList.length : 0 %>');
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',

+ 1 - 0
app/view/material/list.ejs

@@ -81,6 +81,7 @@
     const readOnly = <%- material.readOnly %>;
     const stage_order = <%- material.order %>;
     const materialID = <%- material.id %>;
+    const tenderID = <%- tender.id %>;
     const materialDecimal = JSON.parse(unescape('<%- escape(JSON.stringify(material.decimal)) %>'));
     const openMaterialChecklist = parseInt(<%- ctx.session.sessionProject.page_show.openMaterialChecklist %>);
     let materialListData, materialChecklistData, notJoinList, ledger, curLedgerData, pos, curPosData, gclGatherData;

+ 19 - 1
app/view/material/modal.ejs

@@ -33,12 +33,30 @@
             <div class="modal-footer">
                 <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
                 <input type="hidden" name="s_order" value="" id="s_order" />
+                <input type="hidden" name="list" value="" id="insertList" />
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
-                <button type="submit" id="addMaterial" class="btn btn-primary btn-sm">确定添加</button>
+                <button type="button" id="addMaterial" class="btn btn-primary btn-sm">确定添加</button>
             </div>
         </form>
     </div>
 </div>
+<!--正在修订提示-->
+<div class="modal fade" id="okedit" data-backdrop="static">
+    <div class="modal-dialog " role="document" >
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">提示</h5>
+            </div>
+            <div class="modal-body">
+                <h5>正在生成新一期调差清单数据中,请等待...</h5>
+                <div class="progress">
+                    <div id="material-progress" class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<!--<script type="text/javascript">$('#okedit').modal('show');</script>-->
 <% } %>
 <% if (materials && materials.length >= 1) { %>
 <!--删除期-->

+ 55 - 40
app/view/setting/user.ejs

@@ -4,9 +4,9 @@
         <div class="title-main">
             <h2>账号管理
                 <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
-                <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
+                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
                 <% } else { %>
-                <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
                 <% } %>
             </h2>
         </div>
@@ -17,9 +17,11 @@
                 <nav class="nav nav-tabs m-3" role="tablist">
                     <a class="nav-item nav-link active" href="/setting/user">账号列表</a>
                     <a class="nav-item nav-link" href="/setting/user/permission/set">账号权限</a>
+                    <a class="nav-item nav-link" href="/setting/user/unit">参建单位</a>
                     <div class="ml-auto">
                         <form class="input-group input-group-sm" method="get">
                             <input type="text" class="form-control" value="<%- keyword %>" name="keyword" placeholder="账号/姓名/单位/手机 搜索" aria-label="账号/姓名/单位/手机 搜索" aria-describedby="button-addon2">
+                            <input type="hidden" class="form-control" value="<%- company %>" name="company">
                             <div class="input-group-append">
                                 <button class="btn btn-outline-primary" type="submit" id="button-addon2"><i class="fa fa-search"></i></button>
                             </div>
@@ -27,44 +29,56 @@
                     </div>
                 </nav>
                 <div class="tab-content m-3">
-                    <div id="user-list" class="tab-pane active">
-                        <table class="table table-hover table-bordered table-sm">
-                            <thead>
-                            <tr>
-                                <th>账号</th>
-                                <th>姓名</th>
-                                <th>单位</th>
-                                <th>角色/职位</th>
-                                <th>手机</th>
-                                <th>电话</th>
-                                <th class="text-center">操作</th></tr>
-                            </thead>
-                            <tbody>
-                            <% for (const account of accountData) { %>
-                                <tr <% if (account.enable !== 1) { %> class="table-danger"<% } %>>
-                                    <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
-                                    <td><%= account.name %></td>
-                                    <td><%= account.company %></td>
-                                    <td><%= account.role %></td>
-                                    <td><%= account.mobile %><% if (account.bind === 1) { %>(已绑定第三方平台)<% } %></td>
-                                    <td><%= account.telephone %></td>
-                                    <td class="text-center"><a href="#edit-user" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
-                                        <% if (account.is_admin !== 1) { %>
-                                            <% if (account.enable !== 1) { %>
-                                                <!--<a href="" class="btn btn-sm btn-outline-success account-switch-btn" data-account="<%= account.id %>">启用</a>-->
-                                            <% } else { %>
-                                                <!--<a href="" class="btn btn-sm btn-outline-danger account-switch-btn" data-account="<%= account.id %>">停用</a>-->
-                                            <% } %>
-                                        <% } %>
-                                        <% if (account.bind === 1) { %>
-                                            <a href="#unlink-user" data-toggle="modal" data-target="#unlink-user" class="btn btn-sm btn-outline-dark unlink-user" data-account="<%= account.id %>" >解绑</a>
-                                        <% } %>
-                                    </td>
-                                </tr>
-                            <% } %>
-                            </tbody>
-                        </table>
-                        <% include ../layout/page.ejs %>
+                        <div id="user-list" class="tab-pane active">
+                        <div class="row">
+                            <div class="col-3">
+                                <div class="list-group">
+                                    <a href="/setting/user?company=" class="list-group-item list-group-item-action <% if (!company) { %>active<% } %>">全部</a>
+                                    <% for (const u of unitList) { %>
+                                    <a href="/setting/user?company=<%- u.name %>" class="list-group-item list-group-item-action <% if (company === u.name) { %>active<% } %>"><%- u.name %></a>
+                                    <% } %>
+                                </div>
+                            </div>
+                            <div class="col-9">
+                                <table class="table table-hover table-bordered table-sm">
+                                    <thead>
+                                    <tr>
+                                        <th>账号</th>
+                                        <th>姓名</th>
+                                        <th>单位</th>
+                                        <th>角色/职位</th>
+                                        <th>手机</th>
+                                        <th>电话</th>
+                                        <th class="text-center">操作</th></tr>
+                                    </thead>
+                                    <tbody>
+                                    <% for (const account of accountData) { %>
+                                        <tr <% if (account.enable !== 1) { %> class="table-danger"<% } %>>
+                                            <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
+                                            <td><%= account.name %></td>
+                                            <td><%= account.company %></td>
+                                            <td><%= account.role %></td>
+                                            <td><%= account.mobile %><% if (account.bind === 1) { %>(已绑定第三方平台)<% } %></td>
+                                            <td><%= account.telephone %></td>
+                                            <td class="text-center"><a href="#edit-user" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
+                                                <% if (account.is_admin !== 1) { %>
+                                                    <% if (account.enable !== 1) { %>
+                                                        <!--<a href="" class="btn btn-sm btn-outline-success account-switch-btn" data-account="<%= account.id %>">启用</a>-->
+                                                    <% } else { %>
+                                                        <!--<a href="" class="btn btn-sm btn-outline-danger account-switch-btn" data-account="<%= account.id %>">停用</a>-->
+                                                    <% } %>
+                                                <% } %>
+                                                <% if (account.bind === 1) { %>
+                                                    <a href="#unlink-user" data-toggle="modal" data-target="#unlink-user" class="btn btn-sm btn-outline-dark unlink-user" data-account="<%= account.id %>" >解绑</a>
+                                                <% } %>
+                                            </td>
+                                        </tr>
+                                    <% } %>
+                                    </tbody>
+                                </table>
+                                <% include ../layout/page.ejs %>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -73,6 +87,7 @@
 </div>
 <script>
     const accountList = JSON.parse(unescape('<%- escape(JSON.stringify(accountData)) %>'));
+    const unitList = JSON.parse(unescape('<%- escape(JSON.stringify(unitList)) %>'));
 </script>
 <script src="/public/js/setting.js"></script>
 <script>autoFlashHeight();</script>

+ 34 - 20
app/view/setting/user_modal.ejs

@@ -7,15 +7,15 @@
             </div>
             <form method="post" action="/setting/user/add?_csrf_j=<%= ctx.csrf %>" onsubmit="return checkUserForm('add');">
             <div class="modal-body">
-                <div class="form-group">
-                    <label><b class="text-danger">*</b>账号组</label>
-                    <select class="form-control form-control-sm" name="account_group">
-                        <option value="0">请选择</option>
-                        <% for (const dw in accountGroup) { %>
-                        <option value="<%= dw %>"><%= accountGroup[dw] %></option>
-                        <% } %>
-                    </select>
-                </div>
+                <!--<div class="form-group">-->
+                    <!--<label><b class="text-danger">*</b>账号组</label>-->
+                    <!--<select class="form-control form-control-sm" name="account_group">-->
+                        <!--<option value="0">请选择</option>-->
+                        <!--<% for (const dw in accountGroup) { %>-->
+                        <!--<option value="<%= dw %>"><%= accountGroup[dw] %></option>-->
+                        <!--<% } %>-->
+                    <!--</select>-->
+                <!--</div>-->
                 <div class="form-group">
                     <label>登录账号<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" name="account" placeholder="支持英文数字组合" type="text">
@@ -39,7 +39,14 @@
                 </div>
                 <div class="form-group">
                     <label>单位名称<b class="text-danger">*</b></label>
-                    <input class="form-control form-control-sm" name="company" value="" type="text">
+                    <!--<input class="form-control form-control-sm" name="company" value="" type="text">-->
+                    <input value="" name="account_group" type="hidden">
+                    <select class="form-control form-control-sm" name="company">
+                        <option>请选择</option>
+                        <% for (const u of unitList) { %>
+                            <option><%- u.name %></option>
+                        <% } %>
+                    </select>
                 </div>
                 <div class="form-group">
                     <label>角色/职位<b class="text-danger">*</b></label>
@@ -71,15 +78,15 @@
             </div>
             <form method="post" action="/setting/user/update?_csrf_j=<%= ctx.csrf %>" onsubmit="return checkUserForm('update');">
             <div class="modal-body">
-                <div class="form-group">
-                    <label>账号组<b class="text-danger">*</b></label>
-                    <select class="form-control form-control-sm" name="account_group">
-                        <option value="0">请选择</option>
-                        <% for (const dw in accountGroup) { %>
-                            <option value="<%= dw %>"><%= accountGroup[dw] %></option>
-                        <% } %>
-                    </select>
-                </div>
+                <!--<div class="form-group">-->
+                    <!--<label>账号组<b class="text-danger">*</b></label>-->
+                    <!--<select class="form-control form-control-sm" name="account_group">-->
+                        <!--<option value="0">请选择</option>-->
+                        <!--<% for (const dw in accountGroup) { %>-->
+                            <!--<option value="<%= dw %>"><%= accountGroup[dw] %></option>-->
+                        <!--<% } %>-->
+                    <!--</select>-->
+                <!--</div>-->
                 <div class="form-group">
                     <label>登录账号<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" value="" name="account" readonly placeholder="支持英文数字组合" type="text">
@@ -109,7 +116,14 @@
                 </div>
                 <div class="form-group">
                     <label>单位名称<b class="text-danger">*</b></label>
-                    <input class="form-control form-control-sm" value="" name="company" type="text">
+                    <!--<input class="form-control form-control-sm" value="" name="company" type="text">-->
+                    <input value="" name="account_group" type="hidden">
+                    <select class="form-control form-control-sm" name="company">
+                        <option>请选择</option>
+                        <% for (const u of unitList) { %>
+                            <option><%- u.name %></option>
+                        <% } %>
+                    </select>
                 </div>
                 <div class="form-group">
                     <label>职位名称<b class="text-danger">*</b></label>

+ 54 - 40
app/view/setting/user_permission.ejs

@@ -4,9 +4,9 @@
         <div class="title-main">
             <h2>账号管理
                 <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
-                <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
+                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
                 <% } else { %>
-                <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
                 <% } %>
             </h2>
         </div>
@@ -17,9 +17,11 @@
                 <nav class="nav nav-tabs m-3" role="tablist">
                     <a class="nav-item nav-link" href="/setting/user">账号列表</a>
                     <a class="nav-item nav-link active" href="/setting/user/permission/set">账号权限</a>
+                    <a class="nav-item nav-link" href="/setting/user/unit">参建单位</a>
                     <div class="ml-auto">
                         <form class="input-group input-group-sm" method="get">
                             <input type="text" class="form-control" value="<%- keyword %>" name="keyword" placeholder="账号/姓名/单位/手机 搜索" aria-label="账号/姓名/单位/手机 搜索" aria-describedby="button-addon2">
+                            <input type="hidden" class="form-control" value="<%- company %>" name="company">
                             <div class="input-group-append">
                                 <button class="btn btn-outline-primary" type="submit" id="button-addon2"><i class="fa fa-search"></i></button>
                             </div>
@@ -28,47 +30,59 @@
                 </nav>
                 <div class="tab-content m-3">
                     <div id="user-purview" class="tab-pane active">
-                        <table class="table table-hover table-bordered table-sm">
-                            <thead>
-                            <tr>
-                                <th>账号</th>
-                                <th>姓名</th>
-                                <th>单位</th>
-                                <th>角色/职位</th>
-                                <th>协作办公</th>
-                                <th>权限</th>
-                            </thead>
-                            <tbody>
-                            <% for (const account of accountData) { %>
-                                <tr>
-                                    <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
-                                    <td><%= account.name %></td>
-                                    <td><%= account.company %></td>
-                                    <td><%= account.role %></td>
-                                    <td><% if (account.cooperation === 1) { %>启用<% } %></td>
-                                    <td>
-                                        <% if (account.permission !== '' && account.permission !== null) { %>
-                                            <% const accountPermission = JSON.parse(account.permission); %>
-                                            <% for(const ap in accountPermission) { %>
-                                                <% if (permission[ap].type === 'checkbox') { %>
-                                                    <% for (const tc in permission[ap].children) { %>
-                                                        <% if (accountPermission[ap].indexOf(permission[ap].children[tc].value.toString()) !== -1) { %>
-                                                            <%= permission[ap].children[tc].title %>
+                        <div class="row">
+                            <div class="col-3">
+                                <div class="list-group">
+                                    <a href="/setting/user?company=" class="list-group-item list-group-item-action <% if (!company) { %>active<% } %>">全部</a>
+                                    <% for (const u of unitList) { %>
+                                        <a href="/setting/user?company=<%- u.name %>" class="list-group-item list-group-item-action <% if (company === u.name) { %>active<% } %>"><%- u.name %></a>
+                                    <% } %>
+                                </div>
+                            </div>
+                            <div class="col-9">
+                                <table class="table table-hover table-bordered table-sm">
+                                    <thead>
+                                    <tr>
+                                        <th>账号</th>
+                                        <th>姓名</th>
+                                        <th>单位</th>
+                                        <th>角色/职位</th>
+                                        <th>协作办公</th>
+                                        <th>权限</th>
+                                    </thead>
+                                    <tbody>
+                                    <% for (const account of accountData) { %>
+                                        <tr>
+                                            <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
+                                            <td><%= account.name %></td>
+                                            <td><%= account.company %></td>
+                                            <td><%= account.role %></td>
+                                            <td><% if (account.cooperation === 1) { %>启用<% } %></td>
+                                            <td>
+                                                <% if (account.permission !== '' && account.permission !== null) { %>
+                                                    <% const accountPermission = JSON.parse(account.permission); %>
+                                                    <% for(const ap in accountPermission) { %>
+                                                        <% if (permission[ap].type === 'checkbox') { %>
+                                                            <% for (const tc in permission[ap].children) { %>
+                                                                <% if (accountPermission[ap].indexOf(permission[ap].children[tc].value.toString()) !== -1) { %>
+                                                                    <%= permission[ap].children[tc].title %>
+                                                                <% } %>
+                                                            <% } %>
+                                                        <% } else if (permission[ap].type === 'radio') { %>
+                                                            <% if (parseInt(accountPermission[ap]) === permission[ap].children[0].value) { %>
+                                                                <%= permission[ap].title %>
+                                                            <% } %>
                                                         <% } %>
                                                     <% } %>
-                                                <% } else if (permission[ap].type === 'radio') { %>
-                                                    <% if (parseInt(accountPermission[ap]) === permission[ap].children[0].value) { %>
-                                                        <%= permission[ap].title %>
-                                                    <% } %>
                                                 <% } %>
-                                            <% } %>
-                                        <% } %>
-                                        <a href="#edit-user2" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user2" class="btn btn-sm btn-outline-primary pull-right">编辑</a></td>
-                                </tr>
-                            <% } %>
-                            </tbody>
-                        </table>
-                        <% include ../layout/page.ejs %>
+                                                <a href="#edit-user2" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user2" class="btn btn-sm btn-outline-primary pull-right">编辑</a></td>
+                                        </tr>
+                                    <% } %>
+                                    </tbody>
+                                </table>
+                                <% include ../layout/page.ejs %>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>

+ 16 - 10
app/view/setting/user_permission_modal.ejs

@@ -7,15 +7,15 @@
             </div>
             <form method="post" action="/setting/user/add?_csrf_j=<%= ctx.csrf %>" onsubmit="return checkUserForm('add');">
             <div class="modal-body">
-                <div class="form-group">
-                    <label><b class="text-danger">*</b>账号组</label>
-                    <select class="form-control form-control-sm" name="account_group">
-                        <option value="0">请选择</option>
-                        <% for (const dw in accountGroup) { %>
-                        <option value="<%= dw %>"><%= accountGroup[dw] %></option>
-                        <% } %>
-                    </select>
-                </div>
+                <!--<div class="form-group">-->
+                    <!--<label><b class="text-danger">*</b>账号组</label>-->
+                    <!--<select class="form-control form-control-sm" name="account_group">-->
+                        <!--<option value="0">请选择</option>-->
+                        <!--<% for (const dw in accountGroup) { %>-->
+                        <!--<option value="<%= dw %>"><%= accountGroup[dw] %></option>-->
+                        <!--<% } %>-->
+                    <!--</select>-->
+                <!--</div>-->
                 <div class="form-group">
                     <label>登录账号<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" name="account" placeholder="支持英文数字组合" type="text">
@@ -39,7 +39,13 @@
                 </div>
                 <div class="form-group">
                     <label>单位名称<b class="text-danger">*</b></label>
-                    <input class="form-control form-control-sm" name="company" value="" type="text">
+                    <input value="" name="account_group" type="hidden">
+                    <select class="form-control form-control-sm" name="company">
+                        <option>请选择</option>
+                        <% for (const u of unitList) { %>
+                            <option><%- u.name %></option>
+                        <% } %>
+                    </select>
                 </div>
                 <div class="form-group">
                     <label>角色/职位<b class="text-danger">*</b></label>

+ 139 - 0
app/view/setting/user_unit.ejs

@@ -0,0 +1,139 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>账号管理
+                <a href="#add-company" data-toggle="modal" data-target="#add-company" class="btn btn-primary btn-sm pull-right">添加单位</a>
+                <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
+                <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right mr-2">添加账号</a>
+                <% } else { %>
+                <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-2">添加账号(受限)</a>
+                <% } %>
+            </h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0">
+                <nav class="nav nav-tabs m-3" role="tablist">
+                    <a class="nav-item nav-link" href="/setting/user">账号列表</a>
+                    <a class="nav-item nav-link" href="/setting/user/permission/set">账号权限</a>
+                    <a class="nav-item nav-link active" href="/setting/user/unit">参建单位</a>
+                </nav>
+                <div class="tab-content m-3">
+                    <div id="unit-list" class="tab-pane active">
+                        <div class="row">
+                            <div class="col-6">
+                                <table class="table table-hover table-bordered table-sm">
+                                    <thead>
+                                    <tr>
+                                        <th>序号</th>
+                                        <th>单位名称</th>
+                                        <th>账号数</th>
+                                        <th>类型</th>
+                                        <th class="text-center">备注</th></tr>
+                                    </thead>
+                                    <tbody id="unit_list" style="cursor: pointer">
+                                    <% if (unitList.length > 0) { %>
+                                    <% for (const [index, u] of unitList.entries()) { %>
+                                    <tr <% if (index === 0) { %>class="table-warning" <% } %> data-id="<%- u.id %>">
+                                        <td width="50px"><%- index+1 %></td>
+                                        <td ><a href="javascript:void(0)"><%- u.name %></a></td>
+                                        <td width="80px"><%- u.account_num %></td>
+                                        <td width="100px"><%- accountGroup[u.type] %></td>
+                                        <td width="150px"><%- u.basic %></td>
+                                    </tr>
+                                    <% } %>
+                                    <% } %>
+                                    </tbody>
+                                </table>
+                            </div>
+                            <% if (unitList.length > 0) { %>
+                            <div class="col-6">
+                                <div>
+                                    <div class="row px-3">
+                                        <div>
+                                            <legend>单位详情</legend>
+                                        </div>
+                                        <div class="ml-auto">
+                                            <a href="#del-company" data-toggle="modal" data-target="#del-company" id="del-modal-btn" class="btn btn-outline-danger btn-sm btn-block">删除单位</a>
+                                        </div>
+                                    </div>
+                                    <table class="table table-hover table-bordered table-sm" id="one_unit">
+                                        <tr>
+                                            <th width="120">单位名称</th>
+                                            <td width="200"><input class="form-control form-control-sm" type="text" data-name="name" id="unit_name" value="<%- unitList[0].name %>" placeholder=""></td>
+                                            <th width="120">法人代表</th>
+                                            <td width="200"><input class="form-control form-control-sm" type="text" data-name="corporation" id="unit_corporation" value="<%- unitList[0].corporation %>" placeholder=""></td>
+                                        </tr>
+                                        <tr>
+                                            <th>企业信用代码</th>
+                                            <td><input class="form-control form-control-sm" type="text" data-name="credit_code" id="unit_credit_code" value="<%- unitList[0].credit_code %>" placeholder=""></td>
+                                            <th>类型</th>
+                                            <td>
+                                                <select class="form-control form-control-sm" id="unit_type" data-name="type">
+                                                    <option value="0">请选择</option>
+                                                    <% for (const dw in accountGroup) { %>
+                                                        <option value="<%= dw %>" <% if (unitList[0].type === parseInt(dw)) { %>selected<% } %>><%- accountGroup[dw] %></option>
+                                                    <% } %>
+                                                </select>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <th>电话</th>
+                                            <td><input class="form-control form-control-sm" type="text" data-name="tel" id="unit_tel" value="<%- unitList[0].tel %>" placeholder=""></td>
+                                            <th>网站</th>
+                                            <td><input class="form-control form-control-sm" type="text" data-name="website" id="unit_website" value="<%- unitList[0].website %>" placeholder=""></td>
+                                        </tr>
+                                        <tr>
+                                            <th>所属地区</th>
+                                            <td><input class="form-control form-control-sm" type="text" data-name="region" id="unit_region" value="<%- unitList[0].region %>" placeholder=""></td>
+                                            <th>地址</th>
+                                            <td><input class="form-control form-control-sm" type="text" data-name="address" id="unit_address" value="<%- unitList[0].address %>" placeholder=""></td>
+                                        </tr>
+                                        <tr>
+                                            <th>备注</th>
+                                            <td colspan="3">
+                                                <textarea class="form-control form-control-sm" id="unit_basic" data-name="basic" value="<%- unitList[0].basic %>" rows="2"></textarea>
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </div>
+                                <div <% if (unitList[0].sign_path) { %>style="display: none" <% } %> id="upload-sign" class="form-group">
+                                    <label for="sign-upload">上传签章</label>
+                                    <input type="file" class="form-control-file" id="sign-upload">
+                                    <small class="form-text text-danger">图片大小为500x500px,格式PNG透明背景。</small>
+                                </div>
+                                <button <% if (!unitList[0].sign_path) { %>style="display: none" <% } %> type="button" class="btn btn-sm btn-danger" id="delete-sign">移除签章</button>
+                                <div class="form-group">
+                                    <label>签章图预览</label>
+                                    <div>
+                                        <div class="position-relative">
+                                            <img src="/public/images/baobiao3.png">
+                                            <div class="position-absolute fixed-top" id="sign-show" style="left:290px;top:210px">
+                                                <% if (unitList[0].sign_path) { %>
+                                                    <img src="<%- fujianOssPath + unitList[0].sign_path %>" width="120">
+                                                <% } %>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <% } %>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+</script>
+<script src="/public/js/setting.js"></script>
+<script>
+    const unitList = JSON.parse(unescape('<%- escape(JSON.stringify(unitList)) %>'));
+    const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));
+    const fujianOssPath = JSON.parse(unescape('<%- escape(JSON.stringify(fujianOssPath)) %>'));
+    let oneUnit = unitList.length > 0 ? unitList[0] : null;
+</script>
+<script>autoFlashHeight();</script>

+ 137 - 0
app/view/setting/user_unit_modal.ejs

@@ -0,0 +1,137 @@
+<!--弹出添加账号-->
+<div class="modal fade" id="add-user" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">添加账号</h5>
+            </div>
+            <form method="post" action="/setting/user/add?_csrf_j=<%= ctx.csrf %>" onsubmit="return checkUserForm('add');">
+            <div class="modal-body">
+                <!--<div class="form-group">-->
+                    <!--<label><b class="text-danger">*</b>账号组</label>-->
+                    <!--<select class="form-control form-control-sm" name="account_group">-->
+                        <!--<option value="0">请选择</option>-->
+                        <!--<% for (const dw in accountGroup) { %>-->
+                        <!--<option value="<%= dw %>"><%= accountGroup[dw] %></option>-->
+                        <!--<% } %>-->
+                    <!--</select>-->
+                <!--</div>-->
+                <div class="form-group">
+                    <label>登录账号<b class="text-danger">*</b></label>
+                    <input class="form-control form-control-sm" name="account" placeholder="支持英文数字组合" type="text">
+                    <input value="" class="account-check" type="hidden">
+                    <div class="invalid-feedback">
+                        该账号已存在。
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>登录密码<b class="text-danger">*</b></label>
+                    <div class="input-group">
+                        <input type="text" name="password" class="form-control form-control-sm" placeholder="密码支持英文数字及符号">
+                        <div class="input-group-append">
+                            <button id="rand-password" class="btn btn-outline-secondary btn-sm" type="button">随机密码</button>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>姓名<b class="text-danger">*</b></label>
+                    <input class="form-control form-control-sm" name="name" value="" type="text">
+                </div>
+                <div class="form-group">
+                    <label>单位名称<b class="text-danger">*</b></label>
+                    <input value="" name="account_group" type="hidden">
+                    <select class="form-control form-control-sm" name="company">
+                        <option value="0">请选择</option>
+                        <% for (const u of unitList) { %>
+                            <option><%- u.name %></option>
+                        <% } %>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label>角色/职位<b class="text-danger">*</b></label>
+                    <input class="form-control form-control-sm" name="role" value="" type="text">
+                </div>
+                <div class="form-group">
+                    <label>手机</label>
+                    <input class="form-control form-control-sm" name="mobile" value="" type="number">
+                </div>
+                <div class="form-group">
+                    <label>电话</label>
+                    <input class="form-control form-control-sm" name="telephone" placeholder="格式000-0000000" type="text">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-primary btn-sm">确定添加</button>
+            </div>
+            </form>
+        </div>
+    </div>
+</div>
+<!--弹出账号受限-->
+<div class="modal" tabindex="-1" role="dialog" id="add-unpass">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">无法添加账号</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <p>账号已超过最大账号数,无法添加新账号。</p>
+                <p>当前限制账号总数:<b><%= projectData.max_user %></b></p>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="modal fade" id="add-company" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <form method="post" class="modal-content" action="/setting/user/unit/add?_csrf_j=<%= ctx.csrf %>" onsubmit="return checkUnitForm();">
+            <div class="modal-header">
+                <h5 class="modal-title">添加单位</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>单位名称<b class="text-danger">*</b></label>
+                    <input class="form-control form-control-sm" name="name" placeholder="请输入单位名称" value="" type="text">
+                </div>
+                <div class="form-group">
+                    <label>类型<b class="text-danger">*</b></label>
+                    <select class="form-control form-control-sm" name="type">
+                        <option value="0">请选择</option>
+                        <% for (const dw in accountGroup) { %>
+                            <option value="<%= dw %>"><%- accountGroup[dw] %></option>
+                        <% } %>
+                    </select>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-sm btn-sm btn-primary">确定添加</button>
+            </div>
+        </form>
+    </div>
+</div>
+<!--删除单位-->
+<div class="modal fade" id="del-company" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">删除单位</h5>
+            </div>
+            <div class="modal-body">
+                <h6 class="del-btn">确认删除当前单位?</h6>
+                <h6 class="not-del-btn">当前单位下存在账号,不允许删除。</h6>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary del-btn" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-danger del-btn" id="delete-unit">确定删除</button>
+                <button type="button" class="btn btn-sm btn-secondary not-del-btn" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 1 - 96
sql/update.sql

@@ -1,105 +1 @@
-ALTER TABLE `zh_change_apply`
-ADD `total_price` DECIMAL(30,8) NULL DEFAULT NULL COMMENT '金额' AFTER `content`,
-ADD `decimal` VARCHAR(1000) NULL DEFAULT NULL COMMENT '小数位数设置JSON' AFTER `total_price`;
-
-CREATE TABLE `zh_change_plan`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `selected` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '报表用,是否选择',
-  `uid` int(11) NOT NULL COMMENT '发起人',
-  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '变更方案编号',
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '变更工程名称',
-  `in_time` datetime NOT NULL COMMENT '发起时间',
-  `status` tinyint(2) NOT NULL COMMENT '方案状态',
-  `times` tinyint(2) NOT NULL COMMENT '审批次数',
-  `apply_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更申请编号',
-  `org_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '原设计图名称',
-  `peg` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '桩号',
-  `new_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '图号',
-  `c_new_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更图号',
-  `design_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更设计名称',
-  `class` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '工程变更类别',
-  `quality` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '工程变更性质',
-  `reason` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '变更原因',
-  `content` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '变更内容',
-  `memo` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '方案描述',
-  `total_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '金额',
-  `decimal` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '小数位数设置JSON',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更方案表' ROW_FORMAT = Dynamic;
-
-CREATE TABLE `zh_change_plan_attachment`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `cpid` int(11) NOT NULL COMMENT '方案id',
-  `uid` int(11) NOT NULL COMMENT '上传者id',
-  `filename` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件名称',
-  `fileext` varchar(5) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件后缀',
-  `filesize` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件大小',
-  `filepath` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件存储路径',
-  `upload_time` datetime NOT NULL COMMENT '上传时间',
-  `extra_upload` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为审核通过后再次上传的文件,0为否',
-  PRIMARY KEY (`id`) USING BTREE,
-  INDEX `idx_cid`(`cpid`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更立项附件表' ROW_FORMAT = Dynamic;
-
-CREATE TABLE `zh_change_plan_audit`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `cpid` int(11) NOT NULL COMMENT '方案id',
-  `aid` int(11) NOT NULL COMMENT '审批人id',
-  `order` int(11) NOT NULL COMMENT '审批顺序',
-  `times` int(11) NOT NULL COMMENT '审批次数',
-  `status` tinyint(1) NOT NULL COMMENT '审批状态',
-  `begin_time` datetime NULL DEFAULT NULL COMMENT '开始审批时间',
-  `end_time` datetime NULL DEFAULT NULL COMMENT '结束审批时间',
-  `opinion` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '审批意见',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更立项审批表' ROW_FORMAT = Dynamic;
-
-CREATE TABLE `zh_change_plan_list`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `cpid` int(11) NOT NULL COMMENT '方案id',
-  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单编号',
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单名称',
-  `unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '单位',
-  `unit_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '单价',
-  `oamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '原数量',
-  `camount` decimal(30, 8) NULL DEFAULT NULL COMMENT '变更数量',
-  `samount` decimal(30, 8) NULL DEFAULT NULL COMMENT '审批完成后变更数量',
-  `audit_amount` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '用户填的数目,json',
-  `spamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '审批流程中读取数量',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更方案清单表' ROW_FORMAT = Dynamic;
-
-ALTER TABLE `zh_material` ADD `period` VARCHAR(255) NULL DEFAULT NULL COMMENT '调差周期' AFTER `s_order`;
-
-ALTER TABLE `zh_tender`
-ADD `c_apply_list_rule` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更申请统一原设计数量读取规则' AFTER `pos_file`,
-ADD `c_plan_list_rule` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更方案统一原设计数量读取规则' AFTER `c_apply_list_rule`;
-
-ALTER TABLE `zh_change` ADD `plan_code` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更方案编号' AFTER `name`;
-
-CREATE TABLE `zh_change_apply_list`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `caid` int(11) NOT NULL COMMENT '申请id',
-  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单编号',
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单名称',
-  `unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '单位',
-  `unit_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '单价',
-  `oamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '原数量',
-  `camount` decimal(30, 8) NULL DEFAULT NULL COMMENT '变更数量',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更申请清单表' ROW_FORMAT = Dynamic;
-
+ALTER TABLE `zh_material` ADD `is_new` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否是新建的调差,用于区分清单新建规则' AFTER `in_time`;

+ 105 - 0
sql/update20220402.sql

@@ -0,0 +1,105 @@
+ALTER TABLE `zh_change_apply`
+ADD `total_price` DECIMAL(30,8) NULL DEFAULT NULL COMMENT '金额' AFTER `content`,
+ADD `decimal` VARCHAR(1000) NULL DEFAULT NULL COMMENT '小数位数设置JSON' AFTER `total_price`;
+
+CREATE TABLE `zh_change_plan`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `selected` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '报表用,是否选择',
+  `uid` int(11) NOT NULL COMMENT '发起人',
+  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '变更方案编号',
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '变更工程名称',
+  `in_time` datetime NOT NULL COMMENT '发起时间',
+  `status` tinyint(2) NOT NULL COMMENT '方案状态',
+  `times` tinyint(2) NOT NULL COMMENT '审批次数',
+  `apply_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更申请编号',
+  `org_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '原设计图名称',
+  `peg` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '桩号',
+  `new_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '图号',
+  `c_new_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更图号',
+  `design_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '变更设计名称',
+  `class` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '工程变更类别',
+  `quality` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '工程变更性质',
+  `reason` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '变更原因',
+  `content` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '变更内容',
+  `memo` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '方案描述',
+  `total_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '金额',
+  `decimal` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '小数位数设置JSON',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更方案表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for zh_change_plan_attachment
+-- ----------------------------
+CREATE TABLE `zh_change_plan_attachment`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `cpid` int(11) NOT NULL COMMENT '方案id',
+  `uid` int(11) NOT NULL COMMENT '上传者id',
+  `filename` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件名称',
+  `fileext` varchar(5) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件后缀',
+  `filesize` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件大小',
+  `filepath` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文件存储路径',
+  `upload_time` datetime NOT NULL COMMENT '上传时间',
+  `extra_upload` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为审核通过后再次上传的文件,0为否',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_cid`(`cpid`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更立项附件表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for zh_change_plan_audit
+-- ----------------------------
+CREATE TABLE `zh_change_plan_audit`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `cpid` int(11) NOT NULL COMMENT '方案id',
+  `aid` int(11) NOT NULL COMMENT '审批人id',
+  `order` int(11) NOT NULL COMMENT '审批顺序',
+  `times` int(11) NOT NULL COMMENT '审批次数',
+  `status` tinyint(1) NOT NULL COMMENT '审批状态',
+  `begin_time` datetime NULL DEFAULT NULL COMMENT '开始审批时间',
+  `end_time` datetime NULL DEFAULT NULL COMMENT '结束审批时间',
+  `opinion` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '审批意见',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更立项审批表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for zh_change_plan_list
+-- ----------------------------
+CREATE TABLE `zh_change_plan_list`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `cpid` int(11) NOT NULL COMMENT '方案id',
+  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单编号',
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单名称',
+  `unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '单位',
+  `unit_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '单价',
+  `oamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '原数量',
+  `camount` decimal(30, 8) NULL DEFAULT NULL COMMENT '变更数量',
+  `samount` decimal(30, 8) NULL DEFAULT NULL COMMENT '审批完成后变更数量',
+  `audit_amount` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '用户填的数目,json',
+  `spamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '审批流程中读取数量',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更方案清单表' ROW_FORMAT = Dynamic;
+
+ALTER TABLE `zh_material` ADD `period` VARCHAR(255) NULL DEFAULT NULL COMMENT '调差周期' AFTER `s_order`;
+
+ALTER TABLE `zh_tender`
+ADD `c_apply_list_rule` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更申请统一原设计数量读取规则' AFTER `pos_file`,
+ADD `c_plan_list_rule` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更方案统一原设计数量读取规则' AFTER `c_apply_list_rule`;
+
+ALTER TABLE `zh_change` ADD `plan_code` VARCHAR(255) NULL DEFAULT NULL COMMENT '变更方案编号' AFTER `name`;
+
+CREATE TABLE `zh_change_apply_list`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `caid` int(11) NOT NULL COMMENT '申请id',
+  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单编号',
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '清单名称',
+  `unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '单位',
+  `unit_price` decimal(30, 8) NULL DEFAULT NULL COMMENT '单价',
+  `oamount` decimal(30, 8) NULL DEFAULT NULL COMMENT '原数量',
+  `camount` decimal(30, 8) NULL DEFAULT NULL COMMENT '变更数量',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '变更申请清单表' ROW_FORMAT = Dynamic;
+