Browse Source

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	app/controller/setting_controller.js
wangfeng 6 years ago
parent
commit
c383b8fef4

+ 1 - 0
app/base/base_service.js

@@ -25,6 +25,7 @@ class BaseService extends Service {
         this.uuid = this.app.uuid;
         this.transaction = null;
         this.sqlBuilder = null;
+        this._ = require('lodash');
     }
 
     /**

+ 27 - 0
app/const/tender.js

@@ -23,6 +23,30 @@ const type = {
     YY: 3
 };
 
+const infoTableCol = [
+    { title: '名称', field: 'name', folderCell: true, },
+    { title: '计量期数', field: '', },
+    { title: '审批状态', field: '', },
+    { title: '0号台帐合同', field: '', },
+    { title: '本期完成', field: '', },
+    { title: '截止本期合同', field: '', },
+    { title: '截止本期变更', field: '', },
+    { title: '截止本期完成', field: '', },
+    { title: '截止上期完成', field: '', },
+    { title: '本期应付', field: '', },
+];
+const progressTableCol = [
+    { title: '名称', field: 'name', folderCell: true, },
+    { title: '完成期数', field: '', },
+    { title: '累计合同计量', field: '', },
+    { title: '截止本期累计完成/本期完成/未完成', field: '', },
+];
+const manageTableCol = [
+    { title: '名称', field: 'name', folderCell: true, },
+    { title: '完成期数', field: '', },
+    { title: '管理', field: '', },
+];
+
 const typeString = [];
 typeString[type.TJ] = '土建标';
 typeString[type.XX] = 'XX标';
@@ -33,4 +57,7 @@ module.exports = {
     statusString,
     type,
     typeString,
+    infoTableCol,
+    progressTableCol,
+    manageTableCol,
 };

+ 5 - 4
app/controller/change_controller.js

@@ -29,8 +29,9 @@ module.exports = app => {
         }
 
         async _filterChanges(ctx, status) {
-            const tender = ctx.tenderData;
-            const tenderList = ctx.tenderList;
+            const tenderId = ctx.params.id;
+            const tender = await this.service.tender.getDataById(tenderId);
+            const tenderList = await this.service.tender.getList();
 
             const changes = await ctx.service.change.checkingDatas(tender.id, ctx.session.sessionUser.accountId);
             const filter = JSON.parse(JSON.stringify(audit.filter));
@@ -103,7 +104,7 @@ module.exports = app => {
                 data: '',
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -147,7 +148,7 @@ module.exports = app => {
          */
         async add(ctx) {
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }

+ 9 - 15
app/controller/ledger_audit_controller.js

@@ -30,21 +30,15 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async index(ctx) {
+            const tenderId = parseInt(ctx.params.id);
             try {
-                if (!ctx.request.query.tenderId) {
-                    throw '标段信息错误';
-                }
-
-                const tenderId = ctx.request.query.tenderId;
                 const tender = await ctx.service.tender.getDataById(tenderId);
                 if (!tender.ledger_times) {
                     tender.ledger_times = 1;
                 }
-                ctx.session.sessionUser.tenderId = tender.id;
-                ctx.session.sessionUser.tenderName = tender.name;
 
                 const curAuditor = await ctx.service.ledgerAudit.getCurAuditor(tenderId, tender.ledger_times);
-                if (curAuditor.audit_id !== ctx.session.sessionUser.accountId) {
+                if (curAuditor && curAuditor.audit_id !== ctx.session.sessionUser.accountId) {
                     throw '审核信息错误';
                 }
 
@@ -66,7 +60,7 @@ module.exports = app => {
                 await this.layout('ledger/audit.ejs', renderData, 'ledger/audit_modal.ejs');
             } catch(err) {
                 console.log(err);
-                ctx.redirect('/dashboard');
+                ctx.redirect('/tender/'+tenderId);
             }
         }
 
@@ -83,7 +77,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -120,7 +114,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -152,7 +146,7 @@ module.exports = app => {
          */
         async start(ctx) {
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '未打开标段';
                 }
@@ -185,7 +179,7 @@ module.exports = app => {
          */
         async check(ctx) {
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -227,7 +221,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -269,7 +263,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }

+ 13 - 14
app/controller/ledger_controller.js

@@ -40,9 +40,9 @@ module.exports = app => {
          */
         async explode(ctx) {
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
-                const tenderList = ctx.tenderList;
-                const tenderData = ctx.tenderData;
+                const tenderId = ctx.params.id;
+                const tenderList = await this.service.tender.getList();
+                const tenderData = await this.service.tender.getDataById(tenderId);
 
                 if (!tenderData.ledger_status) {
                     tenderData.ledger_status = auditConst.status.uncheck;
@@ -96,7 +96,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -127,7 +127,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -183,7 +183,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -212,7 +212,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -243,7 +243,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -277,7 +277,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -340,7 +340,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -384,7 +384,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -418,7 +418,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -449,7 +449,7 @@ module.exports = app => {
                 data: [],
             };
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -475,7 +475,6 @@ module.exports = app => {
          * @return {void}
          */
         async change(ctx) {
-
             const renderData = {};
             await this.layout('ledger/change.ejs', renderData, 'ledger/change_modal.ejs');
         }

+ 80 - 10
app/controller/setting_controller.js

@@ -28,7 +28,7 @@ module.exports = app => {
         }
 
         /**
-         * 项目信息页面
+         * 项目信息页面(Get)
          *
          * @param {Object} ctx - egg全局变量
          * @return {void}
@@ -72,6 +72,11 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 项目设置 -- 账号设置(Get)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
         async user(ctx) {
             try {
                 // 获取项目数据
@@ -91,6 +96,12 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 项目设置 -- 自定义标段分类(Get)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
         async category(ctx) {
             try {
                 // 获取项目数据
@@ -100,11 +111,13 @@ module.exports = app => {
                     throw '没有对应的项目数据';
                 }
 
-                const categoryData = await ctx.service.category.getAllCategory({ where: { pid: projectId } });
+                const categoryData = await ctx.service.category.getAllCategory(projectId);
+                const tenderData = await ctx.service.tender.getList();
                 const renderData = {
                     projectData,
                     categoryType: settingConst.cType,
                     categoryData,
+                    tenderData,
                 };
                 await this.layout('setting/category.ejs', renderData, 'setting/category_modal.ejs');
             } catch (error) {
@@ -113,6 +126,12 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 新增分类(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
         async addCategory(ctx) {
             try {
                 const projectId = ctx.session.sessionProject.id;
@@ -133,12 +152,16 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 编辑分类(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
         async updateCategory(ctx) {
             try {
                 const projectId = ctx.session.sessionProject.id;
-                const responseData = {
-                    err: 0, msg: '', data: null,
-                }
+                const responseData = { err: 0, msg: '', data: null, };
 
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data.id) {
@@ -151,15 +174,13 @@ module.exports = app => {
                     }
                 }
 
-                if (data.value) {
-                    data.value = JSON.stringify(data.value)
-                }
                 const result = await ctx.service.category.update(data, {id: data.id});
                 if (!result) {
-                    throw '提交数据失败'
+                    throw '提交数据失败';
                 }
 
-                responseData.data = await ctx.service.category.getCategory({id: data.id});
+                responseData.data = await ctx.service.category.getCategory(data.id);
+
                 ctx.body = responseData;
             } catch (err) {
                 console.log(err);
@@ -167,6 +188,32 @@ module.exports = app => {
             }
         }
 
+        async setCategoryValue(ctx) {
+            try {
+                const responseData = { err: 0, msg: '', data: {}, };
+
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.id) {
+                    throw '提交数据错误';
+                }
+                await ctx.service.categoryValue.setCategoryValue(data.id, data.value);
+
+                responseData.data.category = await ctx.service.category.getCategory(data.id);
+                responseData.data.tenders = await ctx.service.tender.getList();
+
+                ctx.body = responseData;
+            } catch (err) {
+                console.log(err);
+                ctx.body = {err: 1, msg: err instanceof string ? err : '提交数据失败', data: null};
+            }
+        }
+
+        /**
+         * 删除分类(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
         async deleteCategory(ctx) {
             try {
                 const projectId = ctx.session.sessionProject.id;
@@ -191,6 +238,29 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 调整分类层次排序(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async resetCategoryLevel(ctx) {
+            try {
+                const projectId = ctx.session.sessionProject.id;
+                const responseData = {
+                    err: 0, msg: '', data: null,
+                }
+                const data = JSON.parse(ctx.request.body.data);
+
+                await ctx.service.category.resetCategoryLevel(data);
+                responseData.data = await ctx.service.category.getAllCategory(projectId);
+                ctx.body = responseData;
+            } catch (err) {
+                console.log(err);
+                ctx.body = {err: 1, msg: err.toString(), data: null};
+            }
+        }
+
         /** update porject info
          * @author wangfeng
          * @date 2018-10-12 15:48:05

+ 5 - 4
app/controller/stage_controller.js

@@ -33,8 +33,9 @@ module.exports = app => {
          */
         async index(ctx) {
             try {
-                const tender = ctx.tenderData;
-                const tenderList = ctx.tenderList;
+                const tenderId = ctx.params.id;
+                const tender = await this.service.tender.getDataById(tenderId);
+                const tenderList = await this.service.tender.getList();
 
                 const stages = await ctx.service.stage.getAllDataByCondition({
                     where: {tid: tender.id},
@@ -63,7 +64,7 @@ module.exports = app => {
          */
         async add(ctx) {
             try {
-                const tenderId = ctx.session.sessionUser.tenderId;
+                const tenderId = ctx.params.id;
                 if (!tenderId) {
                     throw '当前未打开标段';
                 }
@@ -129,7 +130,7 @@ module.exports = app => {
                     tenderList,
                     stage,
                     auditConst: audit.flow,
-                }
+                };
                 await this.layout('stage/deal.ejs', renderData, 'stage/deal_modal.ejs');
             } catch (err) {
                 console.log(err);

+ 100 - 25
app/controller/tender_controller.js

@@ -11,6 +11,7 @@
 const tenderConst = require('../const/tender');
 const codeRuleConst = require('../const/code_rule');
 const settingConst = require('../const/setting.js');
+const tenderMenu = require('../../config/menu').tenderMenu;
 
 module.exports = app => {
 
@@ -28,52 +29,126 @@ module.exports = app => {
             ctx.showTitle = true;
         }
 
+        async _list(view, setting, modal = '') {
+            try {
+                const tenderList = await this.ctx.service.tender.getList();
+                const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+
+                const renderData = {
+                    tenderList,
+                    tenderConst,
+                    settingConst,
+                    categoryData,
+                    tableColSetting: setting,
+                };
+                await this.layout(view, renderData, modal);
+            } catch(error) {
+                console.log(error);
+                this.ctx.redirect('/dashboard');
+            }
+        }
+
         /**
-         * 标段概况
+         * 标段概况(Get)
          *
          * @param {object} ctx - egg全局变量
          * @return {void}
          */
-        async index(ctx) {
-            // 根据项目id获取标段数据
-            const tenderList = await ctx.service.tender.getList();
-            const categoryData = await ctx.service.category.getAllCategory({
-                where: { pid: ctx.session.sessionProject.id }
-            });
-
-            const renderData = {
-                tenderList,
-                tenderConst,
-                settingConst,
-                categoryData,
-            };
-            await this.layout('tender/index.ejs', renderData, 'tender/modal.ejs');
+        async listInfo(ctx) {
+            await this._list('tender/index.ejs', tenderConst.infoTableCol, 'tender/modal.ejs');
         }
 
         /**
-         * 计量进度
+         * 计量进度(Get)
          *
          * @param ctx
          * @returns {Promise<void>}
          */
-        async progress(ctx) {
-            const renderData = {
+        async listProgress(ctx) {
+            await this._list('tender/progress.ejs', tenderConst.progressTableCol);
+        }
 
-            };
-            await this.layout('tender/progress.ejs', renderData);
+        /**
+         * 标段管理(Get)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async listManage(ctx) {
+            await this._list('tender/manage.ejs', tenderConst.manageTableCol, 'tender/manage_modal.ejs');
         }
 
         /**
-         * 标段管理
+         * 新增标段(Ajax)
          *
          * @param ctx
          * @returns {Promise<void>}
          */
-        async manage(ctx) {
-            const renderData = {
+        async addTender(ctx) {
+            try {
+                const responseData = {
+                    err: 0, msg: '', data: null,
+                };
 
-            };
-            await this.layout('tender/manage.ejs', renderData, 'tender/manage_modal.ejs');
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.name || data.name === '') {
+                    throw '标段信息不完整';
+                }
+
+                responseData.data = await ctx.service.tender.add(data);
+                ctx.body = responseData;
+            } catch (error) {
+                console.log(error);
+                ctx.body = {err: 1, msg: error.toString(), data: null};
+            }
+        }
+
+        /**
+         * 编辑标段(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async updateTender(ctx) {
+
+        }
+
+        /**
+         * 删除标段(Ajax)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async deleteTender(ctx) {
+
+        }
+
+        /**
+         * 标段概况(Get)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async tenderInfo(ctx) {
+            try {
+                const tenderId = ctx.params.id;
+                const tenderData = await ctx.service.tender.getTender(tenderId);
+
+                if (tenderData.project_id !== ctx.session.sessionProject.id) {
+                    this.setMessage('您无权查看该项目', this.messageType.ERROR);
+                    throw '您无权查看该项目';
+                }
+                const renderData = {
+                    tenderData,
+                    tenderMenu,
+                    preUrl: '/tender/' + tenderId,
+                };
+                await this.layout('tender/detail.ejs', renderData);
+            } catch (error) {
+                console.log(error);
+                this.ctx.redirect('/list');
+
+            }
         }
 
         /**

+ 40 - 14
app/public/js/category.js

@@ -36,8 +36,12 @@ function getCategoryHtml(category) {
         html.push('<td>', d.name, '</td>');
         html.push('<td>', d.typeStr, '</td>');
         html.push('<td>');
-        for (const v of d.value) {
-            html.push('<span class="h5"><span class="badge badge-secondary">', v, '</span></span>\n');
+        if (d.value && d.value.length > 0) {
+            for (const v of d.value) {
+                html.push('<span class="h5"><span class="badge badge-secondary">', v.value, '</span></span>\n');
+            }
+        } else {
+            html.push('请在右侧添加值');
         }
         html.push('</td>');
         html.push('<td>');
@@ -50,11 +54,29 @@ function getCategoryHtml(category) {
     return html.join('');
 }
 
+function getValueTenderCount(value) {
+    function findTenderCate(tender) {
+        for (const c of tender.category) {
+            if (c.cid == value.cid) {
+                return c;
+            }
+        }
+    }
+    const valueTender = tenders.filter(function (t) {
+        const cate = findTenderCate(t);
+        console.log(cate);
+        return cate ? cate.value == value.id : false;
+    });
+    return valueTender ? valueTender.length : 0;
+}
+
 function getValueHtml(value) {
     const html = [];
     for (const v of value) {
         html.push('<tr name="value">');
-        html.push('<td><input class="form-control form-control-sm" name="value" placeholder="请输入值" value="' + v + '"></td>');
+        html.push('<td><input class="form-control form-control-sm" name="value" placeholder="请输入值" value="' + v.value + '" vid ="' + v.id +  '"></td>');
+        console.log(v);
+        html.push('<td>', getValueTenderCount(v) ,'</td>');
         html.push('<td><a href="javasrcipt: void(0);" class="text-danger">删除</a></td>');
         html.push('</tr>');
     }
@@ -77,9 +99,9 @@ function bindCategoryControl() {
         $('#add-ok').attr('cid', id);
         if (category) {
             const list = $('#value-list');
-            list.html(getValueHtml(category.value) + '<tr id="add-value-row"><td colspan="2"><a href="javascript: void(0);">添加新值</a></td></tr>');
+            list.html(getValueHtml(category.value) + '<tr id="add-value-row"><td colspan="3"><a href="javascript: void(0);">添加新值</a></td></tr>');
             $('#add-value-row').click(function () {
-                $(this).before('<tr><td><input class="form-control form-control-sm" name="value" placeholder="请输入值"></td><td><a href="javasrcipt: void(0);" class="text-danger">删除</a></td></tr>');
+                $(this).before('<tr><td><input class="form-control form-control-sm" name="value" placeholder="请输入值"></td><td>0</td><td><a href="javasrcipt: void(0);" class="text-danger">删除</a></td></tr>');
             });
             $('#add').modal('show');
         }
@@ -132,20 +154,23 @@ $(document).ready(() => {
         const value = $('input[name=value]');
         for (const v of value) {
             if (v.value !== '') {
-                valueArr.push(v.value);
+                valueArr.push({
+                    id: $(v).attr('id'),
+                    value: $(v).val(),
+                });
             }
         }
         const data = {
-            id: $(this).attr('cid'),
+            id: parseInt($(this).attr('cid')),
             value: valueArr,
-        }
-        postData('/setting/category/update', data, function (data) {
-            const category = findCategory(data.id);
-            for (const c in data) {
-                category[c] = data[c];
-            }
+        };
+        postData('/setting/category/value', data, function (data) {
+            tenders = data.tenders;
+            const category = findCategory(data.category.id);
+            category.value = data.category.value;
             InitCategoryData(category);
-            $('tr[cid=' + data.id + ']')[0].outerHTML = getCategoryHtml(category);
+            $('tr[cid=' + data.category.id + ']')[0].outerHTML = getCategoryHtml(category);
+            bindCategoryControl();
             $('#add').modal('hide');
         }, function () {
             $('#add').modal('hide');
@@ -167,6 +192,7 @@ $(document).ready(() => {
             }
             InitCategoryData(category);
             $('tr[cid=' + data.id + ']')[0].outerHTML = getCategoryHtml(category);
+            bindCategoryControl();
             $('#edit-cate').modal('hide');
         }, function () {
             $('#edit-cate').modal('hide');

+ 16 - 2
app/public/js/global.js

@@ -1,8 +1,22 @@
 /*全局自适应高度*/
+/*全局自适应高度*/
 function autoFlashHeight(){
     var cHeader = $(".c-header").height();
-    $(".sjs-height-1").height($(window).height()-cHeader-160);
-    $(".sjs-height-2").height($(window).height()-cHeader-191);
+    var sBar = $(".sjs-bar").height();
+    var sBart = $(".sjs-bart").height();
+    var sBarz = $(".side-bar").height();
+    var pBarz = $(".toolsbar-f").height();
+    var bdtopc = $(".body-height-top").height();
+    var bcontent = $(".bcontent-wrap").height();
+    $(".sjs-height-0").height($(window).height()-cHeader-110);
+    $(".sjs-height-1").height($(window).height()-cHeader-bcontent-110);
+    $(".sjs-height-2").height($(window).height()-cHeader-sBarz-110);
+    $(".sjs-height-3").height($(window).height()-cHeader-sBar-510);
+    $(".sjs-height-4").height($(window).height()-cHeader-pBarz-110);
+    $(".sjs-height-5").height($(window).height()-cHeader-sBart-555);
+    $(".sjs-height-6").height($(window).height()-cHeader-bdtopc-156);
+    $(".sjs-height-7").height($(window).height()-cHeader-sBar-110);
+    $(".sp-wrap").height(bcontent-40);
 };
 $(window).resize(autoFlashHeight);
 /*全局自适应高度结束*/

File diff suppressed because it is too large
+ 29 - 0
app/public/js/lodash.js


+ 343 - 0
app/public/js/tender_list.js

@@ -0,0 +1,343 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/10/11
+ * @version
+ */
+const EmptyTenderHtml = [
+    '<div class="jumbotron">',
+    '<h3 class="display-6">还没有标段数据</h3>',
+    '</div>'
+];
+// levelTree - setting
+const levelTreeSetting = {
+    view: {
+        selectedMulti: false
+    },
+    data: {
+        simpleData: {
+            idKey: 'lid',
+            pIdKey: 'lpId',
+            rootPId: 0,
+            enable: true,
+        }
+    },
+    edit: {
+        enable: true,
+        showRemoveBtn: false,
+        showRenameBtn: false,
+        drag: {
+            autoExpandTrigger: true,
+            isCopy: false,
+            isMove:  true,
+            prev: false,
+            next: false,
+            inner: true,
+        }
+    },
+    callback: {
+        beforeDrop: beforeDropNode,
+        onDrop: onDropNode,
+    }
+};
+const levelNodes =[];
+const tenderTree = [];
+function createTree() {
+    const zTree = $.fn.zTree.getZTreeObj('treeLevel');
+    if (zTree) {
+        zTree.destroy();
+    }
+    $.fn.zTree.init($("#treeLevel"), levelTreeSetting, levelNodes);
+}
+function beforeDropNode(treeId, treeNodes, targetNode, moveType, isCopy) {
+    if (targetNode.lid !== 1) {
+        const parent = targetNode.getParentNode();
+        if (parent && parent.lid === 1) {
+            return false;
+        }
+    }
+}
+function onDropNode(event, treeId, treeNodes, targetNode, moveType) {
+    const zTree = $.fn.zTree.getZTreeObj(treeId);
+    function resetFixNode(id) {
+        const node = zTree.getNodeByParam('lid', id);
+        node.isParent = true;
+        zTree.updateNode(node, false);
+        zTree.expandNode(node, true);
+    }
+    function moveChildren(children, node) {
+        if (!children || children.length === 0) { return }
+        for (const c of children) {
+            moveChildren(c.children, node);
+            zTree.moveNode(node, c, 'inner');
+        }
+    }
+    resetFixNode(1);
+    resetFixNode(2);
+    if (targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
+        moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
+    } else if (targetNode.lid !== 1) {
+        if (targetNode.children.length >= 2) {
+            for (const c of targetNode.children) {
+                if (c.lid !== treeNodes[0].lid) {
+                    zTree.moveNode(treeNodes[0], c, 'inner');
+                }
+            }
+        }
+    }
+}
+// 查询方法
+function findNode (key, value, arr) {
+    for (const a of arr) {
+        if (a[key] && a[key] === value) {
+            return a;
+        }
+    }
+}
+function getPId(level) {
+    if (level !== 1) {
+        const p = findNode('level', level - 1, levelNodes);
+        if (p) {
+            return p.lid
+        } else {
+            return 1;
+        }
+    } else {
+        return 2;
+    }
+}
+// 分类数据排序
+function sortCategory() {
+    category.sort(function (a, b) {
+        return a.level ? (b.level ? a.level - b.level : -1) : a.id - b.id;
+    });
+}
+// 初始化分类树结构数据
+function initCategoryLevelNode() {
+    levelNodes.splice(0, levelNodes.length);
+    levelNodes.push(
+        { lid:1, lpId:0, name:"可用类别", open:true, isParent: true},
+        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true}
+    );
+    for (const c of category) {
+        const cate = JSON.parse(JSON.stringify(c));
+        cate.lid = levelNodes.length + 1;
+        cate.open = true;
+        if (!cate.level) {
+            cate.lpId = 1;
+            levelNodes.push(cate);
+        } else {
+            cate.lpId = getPId(cate.level);
+            levelNodes.push(cate);
+        }
+    }
+}
+// 新建标段 -- 分类属性选择
+function getCategoryHtml() {
+    function getSelectCategoryHtml (cate) {
+        const html = [];
+        html.push('<div class="form-group" cate-id="' + cate.id + '">');
+        html.push('<lable>', cate.name, '</lable>');
+        html.push('<select class="form-control">');
+        for (const v of cate.value) {
+            html.push('<option>', v, '</option>');
+        }
+        html.push('</select>');
+        html.push('</div>');
+        return html.join('');
+    }
+    function getRadioCategoryHtml (cate) {
+        const html = [];
+        html.push('<div class="form-group" cate-id="' + cate.id + '">');
+        html.push('<lable>', cate.name, '</lable>');
+        html.push('<div>');
+        for (const v of cate.value) {
+            html.push('<div class="form-check-inline">');
+            html.push('<input class="form-check-input" type="radio"', 'value="' , v,  '">');
+            html.push('<label class="form-check-label">', v, '</label>');
+            html.push('</div>');
+        }
+        html.push('</div>');
+        html.push('</div>');
+        return html.join('');
+    }
+    const html = [];
+    for (const c of category) {
+        if (c.type === categoryType.key.dropDown) {
+            html.push(getSelectCategoryHtml(c));
+        } else if (c.type === categoryType.key.radio) {
+            html.push(getRadioCategoryHtml(c));
+        }
+    }
+    return html.join('');
+}
+// 初始化TenderTree数据
+function initTenderTree () {
+    const levelCategory = category.filter(function (c) {
+        return c.level && c.level > 0;
+    });
+    function findCategoryNode(cid, value, array) {
+        for (const a of array) {
+            if (a.cid === cid && a.vid === value) {
+                return a;
+            }
+        }
+    }
+    function getCategoryNode(category, value, parent) {
+        const array = parent ?  parent.children : tenderTree;
+        let cate = findCategoryNode(category.id, value, array);
+        if (!cate) {
+            cate = {
+                cid: category.id,
+                vid: value,
+                name: findNode('id', value, category.value).value,
+                children: [],
+                level: category.level,
+            };
+            array.push(cate);
+        }
+        return cate;
+    }
+    function loadTenderCategory (tender) {
+        let tenderCategory = null;
+        for (const lc of levelCategory) {
+            const tenderCate = findNode('cid', lc.id, tender.category);
+            if (tenderCate) {
+                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+            } else {
+                return tenderCategory;
+            }
+        }
+        return tenderCategory;
+    }
+    tenderTree.splice(0, tenderTree.length);
+    for (const t of tenders) {
+        t.valid = true;
+        if (t.category && levelCategory.length > 0) {
+            const parent = loadTenderCategory(t);
+            if (parent) {
+                t.level = parent.level + 1;
+                parent.children.push(t);
+            } else {
+                tenderTree.push(t);
+            }
+        } else {
+            tenderTree.push(t);
+        }
+    }
+}
+function recursiveGetTenderNodeHtml (node, arr) {
+    const html = [];
+    html.push('<tr>');
+    for (const c of TenderTableCol) {
+        if (c.folderCell) {
+            html.push('<td class="in-' + node.level + '">');
+            if (node.cid) {
+                html.push('<i class="fa fa-folder-o"></i> ', node[c.field]);
+            } else {
+                html.push('<span class="text-muted mr-2">');
+                html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+                html.push('</span>');
+                html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+            }
+            html.push('</td>');
+        } else {
+            html.push('<td>');
+            html.push(node[c.field] ? node[c.field] : '');
+            html.push('</td>');
+        }
+    }
+    html.push('</tr>');
+    if (node.children) {
+        for (const c of node.children) {
+            html.push(recursiveGetTenderNodeHtml(c, node.children));
+        }
+    }
+    return html.join('');
+}
+// 根据TenderTree数据获取Html代码
+function getTenderTreeHtml () {
+    if (tenderTree.length > 0) {
+        const html = [];
+        html.push('<table class="table table-bordered">');
+        html.push('<thead>', '<tr>');
+        for (const c of TenderTableCol) {
+            html.push('<th>', c.title, '</th>');
+        }
+        html.push('</tr>', '</thead>');
+        for (const t of tenderTree) {
+            html.push(recursiveGetTenderNodeHtml(t, tenderTree));
+        }
+        html.push('</table>');
+        return html.join('');
+    } else {
+        return EmptyTenderHtml.join('');
+    }
+}
+
+$(document).ready(() => {
+    sortCategory();
+    // 初始化分类数据
+    initCategoryLevelNode();
+    $('.modal-body', '#add-bd').append(getCategoryHtml());
+    // 初始化标段树结构
+    initTenderTree();
+    console.log(tenderTree);
+    $('.c-body').html(getTenderTreeHtml());
+    // 分类
+    $('#cate-set').on('show.bs.modal', function () {
+        createTree();
+    });
+    $('#set-cate-ok').click(function () {
+        const data = [];
+        const zTree = $.fn.zTree.getZTreeObj('treeLevel');
+        for (const c of category) {
+            const node = zTree.getNodeByParam('id', c.id);
+            const parent = node.getParentNode();
+            if (parent.lid === 1) {
+                data.push({id: c.id, level: 0});
+            } else {
+                data.push({id: c.id, level: node.getPath().length - 1});
+            }
+        }
+        postData('/setting/category/level', data, function (rst) {
+            for (const d of data) {
+                const c = findNode('id', d.id, category);
+                c.level = d.level;
+            }
+            sortCategory();
+            initCategoryLevelNode();
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+            $('#cate-set').modal('hide');
+        });
+    });
+    // 新增标段
+    $('#add-bd-ok').click(function () {
+        const data = {
+            name: $('[name=name]', '#add-bd').val(),
+            category: [],
+        };
+        if (!data.name || data.name === '') {
+            // TODO 提示用户
+            return;
+        }
+        for (const c of category) {
+            const cate = {cid: c.id};
+            if (c.type === categoryType.key.dropDown) {
+                cate.value = $('select', '[cate-id=' + c.id + ']').val();
+            } else if (c.type === categoryType.key.radio) {
+                cate.value = $('input:checked', '[cate-id=' + c.id + ']').val();
+            }
+            data.category.push(cate);
+        }
+        postData('/list/add', data, function (result) {
+            tenders.push(result);
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+        });
+    });
+});

File diff suppressed because it is too large
+ 296 - 226
app/public/js/ztree/jquery.ztree.core.js


File diff suppressed because it is too large
+ 1203 - 0
app/public/js/ztree/jquery.ztree.exedit.js


+ 48 - 46
app/router.js

@@ -36,8 +36,9 @@ module.exports = app => {
     app.get('/setting/category', sessionAuth, 'settingController.category');
     app.post('/setting/category/add', sessionAuth, 'settingController.addCategory');
     app.post('/setting/category/del', sessionAuth, 'settingController.deleteCategory');
-    app.post('/setting/category/del', sessionAuth, 'settingController.deleteCategory');
     app.post('/setting/category/update', sessionAuth, 'settingController.updateCategory');
+    app.post('/setting/category/value', sessionAuth, 'settingController.setCategoryValue');
+    app.post('/setting/category/level', sessionAuth, 'settingController.resetCategoryLevel');
 
     // 项目相关
     app.get('/project/info', sessionAuth, 'projectController.info');
@@ -52,48 +53,57 @@ module.exports = app => {
      * 标段管理
      */
     // 金额概况
-    app.get('/tender', sessionAuth, 'tenderController.index');
+    app.get('/list', sessionAuth, 'tenderController.listInfo');
     // 计量进度
-    app.get('/tender/progress', sessionAuth, 'tenderController.progress');
+    app.get('/list/progress', sessionAuth, 'tenderController.listProgress');
     // 管理标段
-    app.get('/tender/manage', sessionAuth, 'tenderController.manage');
-    // 标段管理相关
-    app.post('/tender/add', sessionAuth, datetimeFill, 'tenderController.add');
-    app.get('/tender/switch/:tenderId', sessionAuth, 'tenderController.switchTender');
-    app.post('/tender/save', sessionAuth, datetimeFill, 'tenderController.save');
-    app.post('/tender/delete', sessionAuth, datetimeFill, 'tenderController.delete');
+    app.get('/list/manage', sessionAuth, 'tenderController.listManage');
+    app.post('/list/add', sessionAuth, 'tenderController.addTender');
+    app.post('/list/update', sessionAuth, 'tenderController.updateTender');
+    app.post('/list/del', sessionAuth, 'tenderController.deleteTender');
+    // 标段概况
+    app.get('/tender/:id', sessionAuth, 'tenderController.tenderInfo');
     app.post('/tender/rule', sessionAuth, 'tenderController.rule');
 
 
     // 台账管理相关
-    app.get('/ledger/explode', sessionAuth, tenderSelect, 'ledgerController.explode');
-    app.post('/ledger/get-children', sessionAuth, 'ledgerController.getChildren');
-    app.post('/ledger/base-operation', sessionAuth, 'ledgerController.baseOperation');
-    app.post('/ledger/update', sessionAuth, 'ledgerController.update');
-    app.post('/ledger/update-info', sessionAuth, 'ledgerController.updateInfo');
-    app.post('/ledger/paste-block', sessionAuth, 'ledgerController.pasteBlock');
-    app.post('/ledger/add-by-std', sessionAuth, 'ledgerController.addFromStandardLib');
-    app.post('/ledger/batch-insert', sessionAuth, 'ledgerController.batchInsert');
-    app.post('/ledger/search', sessionAuth, 'ledgerController.search');
-    app.post('/ledger/locate', sessionAuth, 'ledgerController.locate');
-    app.post('/ledger/posterity', sessionAuth, 'ledgerController.posterity');
-
-    app.get('/ledger/change', sessionAuth, 'ledgerController.change');
-    app.get('/ledger/index', sessionAuth, 'ledgerController.index');
+    app.get('/tender/:id/ledger/explode', sessionAuth, 'ledgerController.explode');
+    app.post('/tender/:id/ledger/get-children', sessionAuth, 'ledgerController.getChildren');
+    app.post('/tender/:id/ledger/base-operation', sessionAuth, 'ledgerController.baseOperation');
+    app.post('/tender/:id/ledger/update', sessionAuth, 'ledgerController.update');
+    app.post('/tender/:id/ledger/update-info', sessionAuth, 'ledgerController.updateInfo');
+    app.post('/tender/:id/ledger/paste-block', sessionAuth, 'ledgerController.pasteBlock');
+    app.post('/tender/:id/ledger/add-by-std', sessionAuth, 'ledgerController.addFromStandardLib');
+    app.post('/tender/:id/ledger/batch-insert', sessionAuth, 'ledgerController.batchInsert');
+    app.post('/tender/:id/ledger/search', sessionAuth, 'ledgerController.search');
+    app.post('/tender/:id/ledger/locate', sessionAuth, 'ledgerController.locate');
+    app.post('/tender/:id/ledger/posterity', sessionAuth, 'ledgerController.posterity');
+
+    app.get('/tender/:id/ledger/change', sessionAuth, 'ledgerController.change');
+    app.get('/tender/:id/ledger/index', sessionAuth, 'ledgerController.index');
 
     // 台账审批相关
-    app.get('/ledger/audit', sessionAuth, 'ledgerAuditController.index');
-    app.post('/ledger/audit/add', sessionAuth, 'ledgerAuditController.add');
-    app.post('/ledger/audit/delete', sessionAuth, 'ledgerAuditController.remove');
-    app.post('/ledger/audit/start', sessionAuth, 'ledgerAuditController.start');
-    app.post('/ledger/audit/check', sessionAuth, 'ledgerAuditController.check');
-    app.post('/ledger/audit/addContent', sessionAuth, 'ledgerAuditController.addContent');
-    app.post('/ledger/audit/getContent', sessionAuth, 'ledgerAuditController.getContent');
+    app.get('/tender/:id/ledger/audit', sessionAuth, 'ledgerAuditController.index');
+    app.post('/tender/:id/ledger/audit/add', sessionAuth, 'ledgerAuditController.add');
+    app.post('/tender/:id/ledger/audit/delete', sessionAuth, 'ledgerAuditController.remove');
+    app.post('/tender/:id/ledger/audit/start', sessionAuth, 'ledgerAuditController.start');
+    app.post('/tender/:id/ledger/audit/check', sessionAuth, 'ledgerAuditController.check');
+    app.post('/tender/:id/ledger/audit/addContent', sessionAuth, 'ledgerAuditController.addContent');
+    app.post('/tender/:id/ledger/audit/getContent', sessionAuth, 'ledgerAuditController.getContent');
 
     // 签约清单
-    app.post('/deal/get-data', sessionAuth, 'dealBillsController.getData');
-    app.post('/deal/upload-excel', sessionAuth, 'dealBillsController.loadExcel');
-    app.get('/deal/download/:file', sessionAuth, 'dealBillsController.download');
+    app.post('/tender/:id/deal/get-data', sessionAuth, 'dealBillsController.getData');
+    app.post('/tender/:id/deal/upload-excel', sessionAuth, 'dealBillsController.loadExcel');
+    app.get('/tender/:id/deal/download/:file', sessionAuth, 'dealBillsController.download');
+
+    // 变更管理
+    app.get('/tender/:id/change', sessionAuth, 'changeController.index');
+    app.get('/tender/:id/change/status/:status', sessionAuth, 'changeController.status');
+    app.post('/tender/:id/change/newCode', sessionAuth, 'changeController.newCode');
+    app.post('/tender/:id/change/add', sessionAuth, 'changeController.add');
+    app.get('/tender/:id/change/:cid/info', sessionAuth, 'changeController.info');
+    app.get('/tender/:id/change/:cid/bills', sessionAuth, 'changeController.bills');
+    app.get('/tender/:id/change/:cid/file', sessionAuth, 'changeController.file');
 
     // 个人账号相关
     app.get('/profile/info', sessionAuth, 'profileController.info');
@@ -124,20 +134,12 @@ module.exports = app => {
     app.post('/measure/audit/check', sessionAuth, 'measureAuditController.check');
 
     // 期计量管理相关
-    app.get('/stage', sessionAuth, tenderSelect, 'stageController.index');
-    app.post('/stage/add', sessionAuth, 'stageController.add');
-    app.get('/stage/:order/measure', sessionAuth, tenderSelect, 'stageController.stageMeasure');
-    app.get('/stage/:order/deal', sessionAuth, tenderSelect, 'stageController.stageDeal');
-    app.get('/stage/:order/report', sessionAuth, tenderSelect, 'stageController.stageReport');
+    app.get('/tender/:id/measure/stage', sessionAuth, 'stageController.index');
+    app.post('/tender/:id/stage/add', sessionAuth, 'stageController.add');
+    app.get('/tender/:id/stage/:order/measure', sessionAuth, tenderSelect, 'stageController.stageMeasure');
+    app.get('/tender/:id/stage/:order/deal', sessionAuth, tenderSelect, 'stageController.stageDeal');
+    app.get('/tender/:id/stage/:order/report', sessionAuth, tenderSelect, 'stageController.stageReport');
 
-    // 变更管理
-    app.get('/change', sessionAuth, tenderSelect, 'changeController.index');
-    app.get('/change/status/:status', sessionAuth, tenderSelect, 'changeController.status');
-    app.post('/change/newCode', sessionAuth, 'changeController.newCode');
-    app.post('/change/add', sessionAuth, 'changeController.add');
-    app.get('/change/:cid/info', sessionAuth, tenderSelect, 'changeController.info');
-    app.get('/change/:cid/bills', sessionAuth, tenderSelect, 'changeController.bills');
-    app.get('/change/:cid/file', sessionAuth, tenderSelect, 'changeController.file');
 
     //标准库相关
     app.post('/std/bills/get-data', sessionAuth, 'stdBillsController.getData');

+ 28 - 6
app/service/category.js

@@ -45,20 +45,42 @@ module.exports = app => {
             return category;
         }
 
-        async getCategory(condition) {
-            const data = await this.getDataByCondition(condition);
-            data.value = data.value && data.value !== '' ? JSON.parse(data.value) : [];
+        async getCategory(id) {
+            const data = await this.getDataByCondition({id: id});
+            data.value = await this.ctx.service.categoryValue.getAllDataByCondition({ where: {cid: id} });
             return data;
         }
 
-        async getAllCategory(condition) {
-            const data = await this.getAllDataByCondition(condition);
+        /**
+         * 获取标段分类数据
+         *
+         * @param {Number} pid - 标段id
+         * @returns {Promise<*>}
+         */
+        async getAllCategory(pid) {
+            const data = await this.getAllDataByCondition({where: {pid: pid}});
+            const values = await this.ctx.service.categoryValue.getAllDataByCondition({ where: {pid: pid} });
             for (const d of data) {
-                d.value = d.value && d.value !== '' ? JSON.parse(d.value) : [];
+                d.value = values.filter(function (v) {
+                    return v.cid === d.id;
+                });
             }
             return data;
         }
 
+        async resetCategoryLevel(data) {
+            this.transaction = await this.db.beginTransaction();
+            try {
+                for (const d of data) {
+                    this.transaction.update(this.tableName, {id: d.id, level: d.level});
+                }
+                this.transaction.commit();
+            } catch (err) {
+                await this.transaction.rollback();
+                throw err;
+            }
+        }
+
     }
 
     return Category;

+ 110 - 0
app/service/category_value.js

@@ -0,0 +1,110 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/10/15
+ * @version
+ */
+
+module.exports = app => {
+    class CategoryValue extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'category_value';
+        }
+
+        /**
+         * 新增分类值
+         *
+         * @param categoryId - 分类Id
+         * @param value - 值
+         * @returns {Promise<void>}
+         * @private
+         */
+        async _addValue(categoryId, value) {
+            const count = await this.count({cid: categoryId, value: value});
+            if (count > 0) {
+                throw '该分类下存在相同的值';
+            }
+
+            const newValue = {
+                cid: categoryId,
+                value: value,
+            };
+            const result = await this.transaction.insert(this.tableName, newValue);
+            if (result.affectedRows !== 1) {
+                throw '提交数据失败';
+            } else {
+                category.id = result.insertId;
+            }
+
+            category.value = category.value && category.value !== '' ? JSON.parse(category.value) : [];
+            return category;
+        }
+
+        async _deleteAndUpdateValue(orgValue, newValue) {
+            if (!orgValue || orgValue.length === 0) { return }
+            for (const ov of orgValue) {
+                const nv = _.find(newValue, function (v) {
+                    return v.id === orgValue.id;
+                });
+                if (!nv) {
+                    await this.transaction.delete(this.tableName, {id: orgValue.id});
+                } else if (nv.value !== ov.value) {
+                    await this.transaction.update(this.tableName, {id: orgValue.id, value: nv.value});
+                }
+            }
+        }
+
+        async setCategoryValue(cid, value) {
+            const orgValue = await this.getAllDataByCondition({ where: {cid: cid} });
+            const tenders = await this.ctx.service.tender.getList();
+
+            this.transaction = await this.db.beginTransaction();
+            try {
+                // 删除值 & 更新值
+                await this._deleteAndUpdateValue(orgValue, value);
+                // 新增值
+                const newValue = value.filter(function (v) {
+                    return !v.id;
+                });
+                for (const nv of newValue) {
+                    nv.cid = cid;
+                    nv.pid = this.ctx.session.sessionProject.id;
+                    const result = await this.transaction.insert(this.tableName, nv);
+                    nv.id = result.insertId;
+                }
+                // 更新标段属性
+                for (const t of tenders) {
+                    const category = t.category ? t.category : [];
+                    const cate = _.find(t.category, function (c) {
+                        return c.cid === cid;
+                    });
+                    const tenderValue = cate ? _.find(value, function (v) {return v.id === cate.value;}) : null;
+                    if (!tenderValue) {
+                        category.push({cid: cid, value: newValue[0].id});
+                        await this.transaction.update(this.service.tender.tableName, {
+                            id: t.id,
+                            category: JSON.stringify(category),
+                        });
+                    }
+                }
+                await this.transaction.commit();
+            } catch(error) {
+                await this.transaction.rollback();
+                throw error;
+            }
+        }
+
+    }
+
+    return CategoryValue;
+};

+ 27 - 8
app/service/tender.js

@@ -80,19 +80,38 @@ module.exports = app => {
                 value: sessionProject.id,
                 operate: '=',
             });
-            this.sqlBuilder.columns = ['id', 'name', 'status', 'type', 'ledger_times', 'ledger_status'];
+            this.sqlBuilder.columns = ['id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status'];
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
 
-            return await this.db.query(sql, sqlParam);
+            const list = await this.db.query(sql, sqlParam);
+            for (const l of list) {
+                l.category = l.category && l.category !== '' ? JSON.parse(l.category) : null;
+            }
+
+            return list;
+        }
+
+        async getTender (id) {
+            this.initSqlBuilder();
+            this.sqlBuilder.setAndWhere('id', {
+                value: id,
+                operate: '=',
+            });
+            this.sqlBuilder.columns = ['id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status'];
+            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
+
+            const tender = await this.db.queryOne(sql, sqlParam);
+            tender.category = tender.category && tender.category !== '' ? JSON.parse(tender.category) : null;
+            return tender;
         }
 
         /**
          * 新增标段
          *
-         * @param {Object} postData - 表单post过来的数据
+         * @param {Object} data - 提交的数据
          * @return {Boolean} - 返回新增结果
          */
-        async add(postData) {
+        async add(data) {
             let result = false;
             this.transaction = await this.db.beginTransaction();
             try {
@@ -102,12 +121,12 @@ module.exports = app => {
                 const sessionProject = this.ctx.session.sessionProject;
 
                 const insertData = {
-                    name: postData.name,
+                    name: data.name,
                     status: tenderConst.status.APPROVAL,
                     project_id: sessionProject.id,
                     user_id: sessionUser.accountId,
-                    create_time: postData.create_time,
-                    type: postData.type,
+                    create_time: new Date(),
+                    category: JSON.stringify(data.category),
                 };
                 const operate = await this.transaction.insert(this.tableName, insertData);
 
@@ -125,12 +144,12 @@ module.exports = app => {
                     throw '新增标段项目节点失败';
                 }
                 this.transaction.commit();
+                return await this.getTender(operate.insertId);
             } catch (error) {
                 console.log(error);
                 result = false;
                 this.transaction.rollback();
             }
-            return result;
         }
 
         /**

+ 1 - 0
app/view/layout/layout.ejs

@@ -25,6 +25,7 @@
     <script src="/public/js/cookies.js"></script>
     <script src="/public/js/jquery-contextmenu/jquery.ui.position.min.js"></script>
     <script src="/public/js/jquery-contextmenu/jquery.contextMenu.min.js"></script>
+    <script src="/public/js/lodash.js"></script>
 </head>
 
 <body>

+ 1 - 0
app/view/setting/category.ejs

@@ -27,5 +27,6 @@
 <script>
     let cData = JSON.parse('<%- JSON.stringify(categoryData) %>');
     const cType = JSON.parse('<%- JSON.stringify(categoryType) %>');
+    let tenders = JSON.parse('<%- JSON.stringify(tenderData) %>');
 </script>
 <script src="/public/js/category.js"></script>

+ 1 - 1
app/view/setting/category_modal.ejs

@@ -58,7 +58,7 @@
             <div class="modal-body">
                 <table class="table table-bordered">
                     <thead>
-                    <tr><th>值</th><th>删除</th></tr>
+                    <tr><th>值</th><th>包含标段</th><th>删除</th></tr>
                     </thead>
                     <tbody id="value-list">
                     </tbody>

+ 372 - 110
app/view/tender/detail.ejs

@@ -1,78 +1,372 @@
+<% include ./tender_sub_menu.ejs %>
 <div class="panel-content">
-    <div class="panel-title fluid">
+    <div class="panel-title">
         <div class="title-main  d-flex justify-content-between">
+            <h2>进行至 第7期<small class="text-warning">(审批中)</small></h2>
             <div>
-                <div class="btn-group">
-                    <a href="/tender">返回 </a>
-                </div>
-            </div>
-            <div>
-                <a href="#add-bd" data-toggle="modal" data-target="#save-bd" class="btn btn-outline-primary btn-sm">编辑</a> <a href="#del-bd" data-toggle="modal" data-target="#del-bd" class="btn btn-outline-danger btn-sm">删除</a>
+                <a href="biaoduan-xiezuo.html" class="btn btn-sm btn-light" ><i class="fa fa-users"></i> 协作办公</a>
             </div>
         </div>
     </div>
     <div class="content-wrap">
         <div class="c-body">
-            <table class="table table-bordered table-sm">
-                <thead><th width="300">名称</th><th width="120">标段类型</th><th width="120">审批状态</th><th width="120">创建时间</th><th>计量进度</th></thead>
-                <tr><td><%= tenderInfo.name %></td>
-                    <td><%= tenderConst.typeString[tenderInfo.type] %></td>
-                    <td><%= tenderConst.statusString[tenderInfo.status] %></td>
-                    <td><%= tenderInfo.create_time > 0 ? moment(tenderInfo.create_time * 1000).format('YYYY-MM-DD') : '-' %></td>
-                    <td>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width: 45%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止本期累计完成:¥731,121,121.00">45%</div>
-                            <div class="progress-bar bg-info" style="width:25%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥31,121,121.00">25%</div>
-                            <div class="progress-bar bg-gray" style="width:30%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥71,121,121.00">30%</div>
+            <!--金额概况-->
+            <div class="row mb-5">
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">163,000.00</h5>
+                            <p class="card-text text-muted">0号台帐合同</p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">30,000.00</h5>
+                            <p class="card-text text-muted">本期完成</p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">50,000.00 <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占合同比例">1%</small></h5>
+                            <p class="card-text text-muted">截止本期变更</p>
                         </div>
-                    </td>
-                </tr>
-            </table>
-            <table class="table table-bordered table-sm">
-                <thead>
-                <th width="120">计量期数</th>
-                <th>0号台帐合同</th>
-                <th>本期完成</th>
-                <th>截止本期合同</th>
-                <th>截止本期变更</th>
-                <th>截止本期完成</th>
-                <th>截止上期完成</th>
-                <th>本期应付</th>
-                </thead>
-                <tr>
-                    <td>15 <a href="jiliang-qi.html" target="_balnk"><i class="fa fa-ellipsis-h"></i></a></td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-            </table>
-            <!--图表1-->
-            <div id="chartContainer1" style="height: 400px; width: 100%;" class="mt-5">
+                    </div>
+                </div>
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">70,000.00</h5>
+                            <p class="card-text text-muted">截止本期完成</p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">40,000.00</h5>
+                            <p class="card-text text-muted">截止上期完成</p>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-auto">
+                    <div class="card text-center">
+                        <div class="card-body">
+                            <h5 class="card-title">30,000.00</h5>
+                            <p class="card-text text-muted">本期应付</p>
+                        </div>
+                    </div>
+                </div>
             </div>
-            <!--图表3-->
-            <div id="chartContainer3" style="height: 400px; width: 100%;" class="mt-5">
+            <!--进度条-->
+            <div class="mb-5">
+                <div class="progress">
+                    <div class="progress-bar bg-success" style="width: 24%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期累计完成:¥40,000.00">24%</div>
+                    <div class="progress-bar bg-info" style="width:18%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥30,000.00">18%</div>
+                    <div class="progress-bar bg-gray" style="width:58%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥930,00.00">58%</div>
+                </div>
             </div>
-            <!--图表2-->
-            <div id="chartContainer2" style="height: 600px; width: 100%;">
+            <ul class="nav nav-tabs">
+                <li class="nav-item">
+                    <a class="nav-link active" data-toggle="tab" href="#tubiao" role="tab">进度表</a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" data-toggle="tab" href="#shuxing" role="tab">标段属性</a>
+                </li>
+            </ul>
+            <div class="tab-content">
+                <!--进度表-->
+                <div id="tubiao" class="tab-pane active">
+                    <!--月进度图表-->
+                    <div id="chartContainer3" style="height: 300px; width: 100%;" class="my-5">
+                    </div>
+                    <!--期汇总图表-->
+                    <div id="chartContainer4" style="height: 300px; width: 100%;" class="mb-5">
+                    </div>
+                </div>
+                <!--标段属性-->
+                <div id="shuxing" class="tab-pane">
+                    <!--操作-->
+                    <div class="d-flex justify-content-end mt-3"><button type="button" class="btn btn-sm btn-outline-primary">编辑</button></div>
+                    <div class="d-flex justify-content-end mt-3"><button type="button" class="btn btn-sm btn-outline-success"><i class="fa fa-check"></i> 提交</button>&nbsp;<button type="button" class="btn btn-sm btn-outline-danger"><i class="fa fa-close"></i>  取消</button></div>
+                    <!--合同信息-->
+                    <legend class="mt-3">合同信息</legend>
+                    <!--默认显示-->
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">建设项目名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="项目A" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">合同编号</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">合同名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <!--参建单位-->
+                    <legend class="mt-3">参建单位</legend>
+                    <!--编辑模式-->
+                    <div class="form-group">
+                        <label>建设单位:</label>
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">单位名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">法人代表</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">签订日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label>承包单位1:</label>
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">单位名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">法人代表</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">签订日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label>承包单位2:</label>
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">单位名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">法人代表</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">签订日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label>监理单位1:</label>
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">单位名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">法人代表</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">签订日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label>监理单位2:</label>
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">单位名称</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">法人代表</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">签订日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <!--技术参数-->
+                    <legend class="mt-3">技术参数</legend>
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">公路等级</span>
+                                    </div>
+                                    <select class="form-control" disabled="">
+                                        <option>高速公路</option>
+                                        <option>一级公路</option>
+                                        <option>二级公路</option>
+                                        <option>三级公路</option>
+                                        <option>四级公路</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">长度(KM)</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">起始桩号</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">终止桩号</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">车道数</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">合同工期</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">开工日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text">计划完工日期</span>
+                                    </div>
+                                    <input type="date" class="form-control" value="" readonly="">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
             </div>
         </div>
     </div>
 </div>
 <script src=/public/js/echarts/echarts.min.js></script>
 <script type="text/javascript">
-    //1 标段期数计量进度//
-    var myChart = echarts.init(document.getElementById('chartContainer1'));
+    //4 标段期数计量进度//
+    var myChart = echarts.init(document.getElementById('chartContainer4'));
     var option = {
         color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
             '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
             '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
-            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],                  title : {
-            text: '期进度',
-            x:'left'
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        title : {
+            text: '标段期进度'
         },
         tooltip : {
             trigger: 'axis'
@@ -81,22 +375,24 @@
         legend: {
             data:['本期合同计量','本期数量变更计量','截至上期累计完成','本期完成计量','完成度']
         },
-        dataZoom : {
-            show : true,
-            start :0,
-            end : 100
-        },
+        dataZoom: [
+            {show: true,start: 0, end: 100}
+        ],
         xAxis : [
             {
                 type : 'category',
-                splitLine : {show :true},
+                splitLine : {show : true},
                 data : ['第一期','第二期','第三期','第四期','第五期','第六期','第七期']
             }
         ],
         yAxis : [
             {
                 type : 'value',
-                position: 'left',
+                name : '金额',
+                position:'left',
+                axisLabel : {
+                    formatter: '{value} 元'
+                },
                 splitArea : {show : true}
             },
             {
@@ -106,8 +402,7 @@
                     formatter: '{value} %'
                 },
                 position: 'right',
-                splitLine : {show :false},
-                splitArea : {show : false}
+                splitArea : {show : true}
             }
         ],
         series : [
@@ -151,51 +446,14 @@
 
     // 为echarts对象加载数据
     myChart.setOption(option);
-    //1 标段期数计量进度//
-    //2 期数组成//
-    var myChart = echarts.init(document.getElementById('chartContainer2'));
-    var option = {
-        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
-            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
-            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
-            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
-        title : {
-            text: '期完成占比',
-            x:'left'
-        },
-
-        tooltip : {
-            trigger: 'item',
-            formatter: "{a} <br/>{b}:{c} 元<br>占标段:{d} %"
-        },
-        calculable : true,
-        series : [
-            {
-                name:'标段计量分布',
-                type:'pie',
-                radius : '80%',
-                center: ['50%','50%'],
-                data:[
-                    {value:7814964.00, name:'第一期'},
-                    {value:6043186.10, name:'第二期'},
-                    {value:6917475.00, name:'第三期'},
-                    {value:7634982.00, name:'第四期'},
-                    {value:7634982.00, name:'第五期'},
-                    {value:7634982.00, name:'第六期'},
-                    {value:7634982.00, name:'第七期'}
-                ]
-            }
-        ]
-    };
-    // 为echarts对象加载数据
-    myChart.setOption(option);
-    //2 期数组成//
-    //3 标段计量分布//
+    //4 标段期数计量进度//
+    //3 标段月进度//
+    // 基于准备好的dom,初始化echarts图表
     var myChart = echarts.init(document.getElementById('chartContainer3'));
     var option = {
-        color:['#ff6666','#3cb371'],
+        color:["#e9af68","#57b7b6"],
         title : {
-            text: '月进度'
+            text: '标段月进度'
         },
         tooltip : {
             trigger: 'axis',
@@ -204,9 +462,15 @@
         legend: {
             data:['累计完成','本月完成']
         },
+        toolbox: {
+            show : true,
+            feature : {
+                magicType : {show: true, type: ['line', 'bar']}
+            }
+        },
         dataZoom : {
             show : true,
-            start :50,
+            start : 50,
             end : 100
         },
         xAxis : [
@@ -214,7 +478,7 @@
                 type : 'category',
                 boundaryGap : true,
                 data : [
-                    '2017-01','2017-02','2017-03','2017-04','2017-05','2017-06','2017-07','2017-08','2017-09'
+                    '2月','3月','4月','5月','6月','7月','8月','9月','10月'
                 ]
             }
         ],
@@ -260,9 +524,7 @@
             }
         ]
     };
-
-
     // 为echarts对象加载数据
     myChart.setOption(option);
-    //3 标段计量分布//
+    //3 标段月进度//
 </script>

+ 5 - 104
app/view/tender/index.ejs

@@ -2,112 +2,13 @@
     <% include ./sub_menu.ejs %>
     <div class="content-wrap">
         <div class="c-body">
-            <!--没有标段数据-->
-            <div class="jumbotron">
-                <h3 class="display-6">还没有标段数据</h3>
-            </div>
-            <!--默认-->
-            <table class="table table-bordered">
-                <thead>
-                <th>名称</th>
-                <th>计量期数</th>
-                <th>审批状态</th>
-                <th>0号台帐合同</th>
-                <th>本期完成</th>
-                <th>截止本期合同</th>
-                <th>截止本期变更</th>
-                <th>截止本期完成</th>
-                <th>截止上期完成</th>
-                <th>本期应付</th>
-                </thead>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2019</td>
-                    <td></td>
-                    <td></td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2018</td>
-                    <td></td>
-                    <td></td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;土建</td>
-                    <td></td>
-                    <td></td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">├</span><a href="biaoduan-panel.html">WWUJ-1</a></td>
-                    <td>共15期</td>
-                    <td>审批中</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;绿化</td>
-                    <td></td>
-                    <td></td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">├</span><a href="biaoduan-panel.html">WWUJ-2</a></td>
-                    <td>共15期</td>
-                    <td>审批中</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">└</span><a href="biaoduan-panel.html">WWUJ-3</a></td>
-                    <td>共15期</td>
-                    <td>审批中</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                    <td>0</td>
-                </tr>
-            </table>
         </div>
     </div>
 </div>
 <script>
     const tenders = JSON.parse('<%- JSON.stringify(tenderList) %>');
-</script>
+    const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
+    const TenderTableCol = JSON.parse('<%- JSON.stringify(tableColSetting) %>');
+</script>
+<script src="/public/js/tender_list.js"></script>

+ 8 - 55
app/view/tender/manage.ejs

@@ -2,60 +2,13 @@
     <% include ./sub_menu.ejs %>
     <div class="content-wrap">
         <div class="c-body">
-            <!--没有标段数据-->
-            <div class="jumbotron">
-                <h3 class="display-6">还没有标段数据</h3>
-            </div>
-            <!--管理标段-->
-            <table class="table table-bordered">
-                <thead>
-                <th>名称</th>
-                <th width="120">完成期数</th>
-                <th>操作</th>
-                </thead>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2019</td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2018</td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;土建</td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">└</span><a href="biaoduan-panel.html">WWUJ-1</a></td>
-                    <td>共15期</td>
-                    <td>
-                        <a href="#add-bd" data-toggle="modal" data-target="#add-bd" class="btn btn-outline-primary btn-sm">编辑</a>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">├</span><a href="biaoduan-panel.html">WWUJ-2</a></td>
-                    <td>共15期</td>
-                    <td>
-                        <a href="#add-bd" data-toggle="modal" data-target="#add-bd" class="btn btn-outline-primary btn-sm">编辑</a>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;绿化</td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">└</span><a href="biaoduan-panel.html">WWUJ-3</a></td>
-                    <td>共0期</td>
-                    <td>
-                        <a href="#add-bd" data-toggle="modal" data-target="#add-bd" class="btn btn-outline-primary btn-sm">编辑</a>
-                        <a href="#del-bd" data-toggle="modal" data-target="#del-bd" class="btn btn-outline-danger btn-sm">删除</a>
-                    </td>
-                </tr>
-            </table>
         </div>
     </div>
-</div>
+</div>
+<script>
+    const tenders = JSON.parse('<%- JSON.stringify(tenderList) %>');
+    const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
+    const TenderTableCol = JSON.parse('<%- JSON.stringify(tableColSetting) %>');
+</script>
+<script src="/public/js/tender_list.js"></script>

+ 6 - 48
app/view/tender/modal.ejs

@@ -8,53 +8,12 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label>标段名称<b class="text-danger">*</b></label>
-                    <input class="form-control"  placeholder="输入标段名称" type="text">
-                </div>
-                <div class="form-group">
-                    <label>年份</label>
-                    <select class="form-control">
-                        <option>2018</option>
-                        <option>2019</option>
-                    </select>
-                </div>
-                <div class="form-group">
-                    <label>标段类型</label>
-                    <div>
-                        <div class="form-check-inline">
-                            <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked>
-                            <label class="form-check-label" for="exampleRadios1">
-                                土建
-                            </label>
-                        </div>
-                        <div class="form-check-inline">
-                            <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2">
-                            <label class="form-check-label" for="exampleRadios2">
-                                绿化
-                            </label>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label>公路等级</label>
-                    <div>
-                        <div class="form-check-inline">
-                            <input class="form-check-input" type="radio" name="exampleRadios2" id="exampleRadios31" value="option3" checked>
-                            <label class="form-check-label" for="exampleRadios3">
-                                一级
-                            </label>
-                        </div>
-                        <div class="form-check-inline">
-                            <input class="form-check-input" type="radio" name="exampleRadios2" id="exampleRadios4" value="option4">
-                            <label class="form-check-label" for="exampleRadios4">
-                                二级
-                            </label>
-                        </div>
-                    </div>
+                    <input class="form-control"  placeholder="输入标段名称" type="text" name="name">
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">确定添加</button>
+                <button type="button" class="btn btn-primary" id="add-bd-ok">确定添加</button>
             </div>
         </div>
     </div>
@@ -73,12 +32,11 @@
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">确定添加</button>
+                <button type="button" class="btn btn-primary" id="set-cate-ok">确定</button>
             </div>
         </div>
     </div>
 </div>
-<script>
-    const settingConst = JSON.parse('<%- JSON.stringify(settingConst) %>');
-    const category = JSON.parse('<%- JSON.stringify(category) %>');
-</script>
+
+<script type="text/javascript" src="/public/js/ztree/jquery.ztree.core.js"></script>
+<script type="text/javascript" src="/public/js/ztree/jquery.ztree.exedit.js"></script>

+ 8 - 74
app/view/tender/progress.ejs

@@ -2,79 +2,13 @@
     <% include ./sub_menu.ejs %>
     <div class="content-wrap">
         <div class="c-body">
-            <!--没有标段数据-->
-            <div class="jumbotron">
-                <h3 class="display-6">还没有标段数据</h3>
-            </div>
-            <!--计量进度-->
-            <table class="table table-bordered">
-                <thead>
-                <th>名称</th>
-                <th width="120">完成期数</th>
-                <th>累计合同计量</th>
-                <th>截止本期累计完成/本期完成/未完成</th>
-                </thead>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2019</td>
-                    <td></td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-1"><i class="fa fa-folder-o"></i>&nbsp;2018</td>
-                    <td></td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;土建</td>
-                    <td></td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">└</span><a href="biaoduan-panel.html">WWUJ-1</a></td>
-                    <td>共15期</td>
-                    <td>¥5,000,000.00</td>
-                    <td>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width: 45%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期累计完成:¥731,121,121.00">45%</div>
-                            <div class="progress-bar bg-info" style="width:25%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥31,121,121.00">25%</div>
-                            <div class="progress-bar bg-gray" style="width:30%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥71,121,121.00">30%</div>
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="in-2"><i class="fa fa-folder-o"></i>&nbsp;绿化</td>
-                    <td></td>
-                    <td></td>
-                    <td></td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">├</span><a href="biaoduan-panel.html">WWUJ-2</a></td>
-                    <td>共15期</td>
-                    <td>¥5,000,000.00</td>
-                    <td>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width: 45%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期累计完成:¥731,121,121.00">45%</div>
-                            <div class="progress-bar bg-info" style="width:25%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥31,121,121.00">25%</div>
-                            <div class="progress-bar bg-gray" style="width:30%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥71,121,121.00">30%</div>
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="in-3"><span class="text-muted mr-2">└</span><a href="biaoduan-panel.html">WWUJ-3</a></td>
-                    <td>共15期</td>
-                    <td>¥5,000,000.00</td>
-                    <td>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width: 45%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期累计完成:¥731,121,121.00">45%</div>
-                            <div class="progress-bar bg-info" style="width:25%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥31,121,121.00">25%</div>
-                            <div class="progress-bar bg-gray" style="width:30%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥71,121,121.00">30%</div>
-                        </div>
-                    </td>
-                </tr>
-            </table>
         </div>
     </div>
-</div>
+</div>
+<script>
+    const tenders = JSON.parse('<%- JSON.stringify(tenderList) %>');
+    const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
+    const TenderTableCol = JSON.parse('<%- JSON.stringify(tableColSetting) %>');
+</script>
+<script src="/public/js/tender_list.js"></script>

+ 4 - 4
app/view/tender/sub_menu.ejs

@@ -6,18 +6,18 @@
             </div>
             <div class="d-inline-block">
                 <div class="btn-group btn-group-toggle" data-toggle="buttons">
-                    <label class="btn btn-sm btn-light <% if (ctx.url === '/tender') { %>active<% } %>" onclick="window.location.href='/tender'">
+                    <label class="btn btn-sm btn-light <% if (ctx.url === '/list') { %>active<% } %>" onclick="window.location.href='/list'">
                         <input type="radio" name="options" id="option1" autocomplete="off"> 金额概况
                     </label>
-                    <label class="btn btn-sm btn-light  <% if (ctx.url === '/tender/progress') { %>active<% } %>" onclick="window.location.href='/tender/progress'">
+                    <label class="btn btn-sm btn-light  <% if (ctx.url === '/list/progress') { %>active<% } %>" onclick="window.location.href='/list/progress'">
                         <input type="radio" name="options" id="option2" autocomplete="off"> 计量进度
                     </label>
                 </div>
             </div>
             <div class="d-inline-block ml-3">
                 <div class="form-check-inline">
-                    <label class="form-check-label" onclick="window.location.href='/tender/manage'">
-                        <input class="form-check-input" type="checkbox" <% if (ctx.url === '/tender/manage') { %>checked="checked"<% } %>>
+                    <label class="form-check-label" onclick="window.location.href='/list/manage'">
+                        <input class="form-check-input" type="checkbox" <% if (ctx.url === '/list/manage') { %>checked="checked"<% } %>>
                         管理标段
                     </label>
                 </div>

+ 26 - 0
app/view/tender/tender_sub_menu.ejs

@@ -0,0 +1,26 @@
+<div class="panel-sidebar">
+    <div class="panel-title">
+        <div class="title-bar">
+            <h2><%- tenderData.name %></h2>
+        </div>
+    </div>
+    <div class="scrollbar-auto">
+        <% for (const m in tenderMenu) { %>
+        <div class="nav-box">
+            <% const menu = tenderMenu[m]; %>
+            <% if (menu.display) { %>
+            <h3><%- menu.icon %><%- menu.name %></h3>
+            <% } %>
+            <% if (menu.children && menu.children.length > 0) { %>
+            <ul class="nav-list list-unstyled <% if (menu.display) { %>sub-list<% } %>">
+                <% for (const mc of menu.children) { %>
+                <li <% if (ctx.url === preUrl + mc.url) { %>class="active"<% } %>>
+                    <a href="<%- preUrl %><%- mc.url %>"><%- mc.icon %><span><%- mc.name %></span></a>
+                </li>
+                <% } %>
+            </ul>
+            <% } %>
+        </div>
+        <% } %>
+    </div>
+</div>

+ 77 - 2
config/menu.js

@@ -21,7 +21,7 @@ const menu = {
         name: '标段管理',
         icon: 'fa-list-ul',
         display: true,
-        url: '/tender',
+        url: '/list',
         children: null,
         caption: '项目',
     },
@@ -36,7 +36,82 @@ const menu = {
 };
 
 const tenderMenu = {
-
+    info: {
+        name: '标段概况',
+        display: false,
+        children: [
+            {
+                name: '标段概况',
+                icon: '<i class="fa fa-pie-chart"></i> ',
+                display: true,
+                url: '',
+            }
+        ]
+    },
+    ledger: {
+        name: '0号台帐',
+        icon: '<i class="fa fa-list-alt"></i> ',
+        display: true,
+        children: [
+            {
+                name: '台帐分解',
+                display: true,
+                url: '/ledger/explode',
+            }, {
+                name: '台帐审批',
+                display: true,
+                url: '/ledger/audit',
+            },{
+                name: '台帐修订',
+                display: true,
+                url: '/ledger/change',
+            },
+        ]
+    },
+    measure: {
+        name: '计量台帐',
+        icon: '<i class="fa fa-calendar-check-o"></i> ',
+        display: true,
+        children: [
+            {
+                name: '期列表',
+                display: true,
+                url: '/measure/stage',
+            }, {
+                name: '清单汇总',
+                display: true,
+                url: '/measure/gather',
+            },{
+                name: '审核比较',
+                display: true,
+                url: '/measure/compare',
+            },
+        ]
+    },
+    change: {
+        name: '工程变更',
+        display: false,
+        children: [
+            {
+                name: '工程变更',
+                icon: '<i class="fa fa-retweet"></i> ',
+                display: true,
+                url: '/change',
+            }
+        ]
+    },
+    report: {
+        name: '报表',
+        display: false,
+        children: [
+            {
+                name: '报表',
+                icon: '<i class="fa fa-file-text-o"></i> ',
+                display: true,
+                url: '/report',
+            }
+        ]
+    },
 };
 
 const settingMenu = {

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "egg-view-ejs": "^1.1.0",
     "gt3-sdk": "^2.0.0",
     "koa-is-json": "^1.0.0",
+    "lodash": "^4.17.11",
     "moment": "^2.20.1",
     "node-uuid": "^1.4.8",
     "node-xlsx": "^0.12.0",