Browse Source

自定义分类

MaiXinRong 2 years ago
parent
commit
d9ee183fa9

+ 13 - 0
app/controller/setting_controller.js

@@ -764,6 +764,19 @@ module.exports = app => {
                 ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
+        async selfCategoryLevel(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+
+                await ctx.service.projectAccount.defaultUpdate({id: ctx.session.sessionUser.accountId, self_category_level: data.self_category_level || ''});
+                ctx.body = {
+                    err: 0, msg: '', data: null,
+                };
+            } catch (err) {
+                ctx.log(err);
+                ctx.ajaxErrorBody(err, '保存自定义分类失败');
+            }
+        }
 
         /** update porject info
          * @author wangfeng

+ 4 - 0
app/controller/tender_controller.js

@@ -181,6 +181,7 @@ module.exports = app => {
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
                 };
+                renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -213,6 +214,7 @@ module.exports = app => {
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
                 };
+                renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -237,6 +239,7 @@ module.exports = app => {
                 renderData.auditConst = auditConst;
                 renderData.uid = this.ctx.session.sessionUser.accountId;
                 renderData.pid = this.ctx.session.sessionProject.id;
+                renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -280,6 +283,7 @@ module.exports = app => {
                 renderData.auditConst = auditConst;
                 renderData.uid = this.ctx.session.sessionUser.accountId;
                 renderData.pid = this.ctx.session.sessionProject.id;
+                renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);

+ 60 - 449
app/public/js/tender_list.js

@@ -1,351 +1,5 @@
-'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 = [];
-let parentId = 0;
-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 !== null && targetNode.lid !== 1) {
-        const parent = targetNode.getParentNode();
-        if (parent && parent.lid === 1) {
-            return false;
-        }
-    }
-    for (var i=0,l=treeNodes.length; i<l; i++) {
-        if (treeNodes[i].drag === false) {
-            return false;
-        }
-        if (!targetNode && treeNodes[i].dropRoot === false) {
-            return false;
-        }
-        if(treeNodes[i].isParent === true && targetNode.lid !== 1){
-            return false;
-        }
-    }
-    return true;
-}
-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 !== null && targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
-        moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
-    } else if (targetNode !== null && 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, drag: false},
-        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true, drag: false}
-    );
-    for (const c of category) {
-        const cate = JSON.parse(JSON.stringify(c));
-        cate.lid = levelNodes.length + 1;
-        cate.open = true;
-        cate.dropRoot = false;
-        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('<label>', cate.name, '</label>');
-        html.push('<select class="form-control form-control-sm">');
-        for (const v of cate.value) {
-            html.push('<option value="' + v.id + '">', v.value, '</option>');
-        }
-        html.push('<option value="0">不选</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('<label>', cate.name, '</label>');
-        html.push('<div>');
-        for (const iV in cate.value) {
-            const v = cate.value[iV];
-            html.push('<div class="form-check-inline">');
-            html.push('<input class="form-check-input" type="radio"', 'name="' + cate.name + '" ', 'value="' , v.id, (iV == 0 ? '" checked="' : ''),  '">');
-            html.push('<label class="form-check-label">', v.value, '</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, i = null) {
-        const array = parent ?  parent.children : tenderTree;
-        let cate = findCategoryNode(category.id, value, array);
-        if (!cate) {
-            const cateValue = findNode('id', value, category.value);
-            if (!cateValue) return null;
-            cate = {
-                cid: category.id,
-                vid: value,
-                name: cateValue.value,
-                children: [],
-                level: i ? i : category.level,
-                sort_id: ++parentId,
-                sort: cateValue.sort,
-            };
-            array.push(cate);
-        }
-        return cate;
-    }
-    function loadTenderCategory (tender) {
-        let tenderCategory = null;
-        for (const [index,lc] of levelCategory.entries()) {
-            const tenderCate = findNode('cid', lc.id, tender.category);
-            if (tenderCate) {
-                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
-            } else {
-                if (index === 0 && tender.category) {
-                    for (const [i,c] of tender.category.entries()) {
-                        const cate = findNode('id', c.cid, category);
-                        if (cate) {
-                            tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
-                        } else {
-                            console.log(tender.name, c.cid, c.value);
-                        }
-                    }
-                }
-                return tenderCategory;
-            }
-        }
-        return tenderCategory;
-    }
-    function calculateTender(tender) {
-        if (tender.lastStage) {
-            tender.gather_tp = ZhCalc.add(tender.lastStage.contract_tp, tender.lastStage.qc_tp);
-            tender.end_contract_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp);
-            tender.end_qc_tp = ZhCalc.add(tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp);
-            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
-            tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
-            tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
-            tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
-        }
-    }
-    tenderTree.splice(0, tenderTree.length);
-    for (const t of tenders) {
-        calculateTender(t);
-        t.valid = true;
-        delete t.level;
-        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);
-        }
-    }
-    sortTenderTree();
-}
-
-function recursiveGetTenderNodeHtml (node, arr, pid) {
-    const html = [];
-    html.push('<tr pid="' + pid + '">');
-    // 名称
-    html.push('<td style="width: 40%" class="in-' + node.level + '">');
-    if (node.cid) {
-        html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
-    } 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('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
-    }
-    html.push('</td>');
-    // 计量模式
-    html.push('<td style="width: 9%" class="text-center">');
-    if (node.measure_type) {
-        html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
-    }
-    html.push('</td>');
-    // 创建人
-    html.push('<td style="width: 9%" class="text-center">', node.user_name ? node.user_name : '', '</td>');
-    // 游客
-    const visitor = node.visitor && node.visitor.length > 0
-        ? `<a href="javascirpt: void(0)" data-toggle="tooltip" data-placement="top" data-original-title="${node.visitor.join(',')}">${node.visitor.length}</a>`
-        : '';
-    html.push('<td style="width: 9%" class="text-center">', visitor, '</td>');
-    // 创建时间
-    html.push('<td style="width: 9%">', node.create_time ? moment(node.create_time).format('YYYY-MM-DD HH:mm:ss') : '', '</td>');
-    // 计量模式
-    // html.push('<td>');
-    // if (node.measure_type) {
-    //     html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
-    // }
-    // html.push('</td>');
-    // 计量期数
-    html.push('<td style="width: 9%" class="text-center">');
-    if (!node.cid) {
-        if (node.progress) {
-            html.push(node.progress.title === '台账' ? '' : node.progress.title);
-        } else {
-            html.push(node.lastStage ? '第' + node.lastStage.order + '期' : '台账');
-        }
-    }
-    html.push('</td>');
-    // 审批状态
-    html.push('<td style="width: 15%">');
-    if (!node.cid && node.cur_flow) {
-        if (node.stage_status !== undefined) {
-            html.push(`<span class="${node.progress.status_class}">${node.progress.status}</span>(${node.cur_flow.name})`);
-        } else {
-            html.push(`<span class="${node.lastStage ? auditConst.stage.tiStatusStringClass[node.lastStage.status] : auditConst.ledger.tiStatusStringClass[node.ledger_status]}">`);
-            html.push(node.lastStage ? auditConst.stage.statusString[node.lastStage.status] : auditConst.ledger.statusString[node.ledger_status]);
-            html.push('</span>');
-            html.push(node.status_users ? '(' + node.status_users + ')' : '');
-        }
-    }
-    html.push('</td>');
-    html.push('</tr>');
-    if (node.children) {
-        for (const c of node.children) {
-            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
-        }
-    }
-    return html.join('');
-}
-// 根据TenderTree数据获取Html代码
-function getTenderTreeHtml () {
-    if (tenderTree.length > 0) {
+const tenderListSpec = (function(){
+    function getTenderTreeHeaderHtml() {
         const html = [];
         html.push('<table class="table table-hover table-bordered">');
         html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
@@ -357,112 +11,69 @@ function getTenderTreeHtml () {
         html.push('<th class="text-center" style="width: 9%">', '计量期数', '</th>');
         html.push('<th class="text-center" style="width: 15%">', '审批状态', '</th>');
         html.push('</tr>', '</thead>');
-        parentId = 0;
-        for (const t of tenderTree) {
-            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
-        }
-        html.push('</table>');
         return html.join('');
-    } else {
-        return EmptyTenderHtml.join('');
     }
-}
-function bindTenderUrl() {
-    $('.c-body').on('click', 'a', function () {
-        const tenderId = parseInt($(this).attr('id'));
-        const tender = _.find(tenders, function (t) {
-            return t.id === tenderId;
-        });
-        if (!tender) return;
-        if (!tender.measure_type && tender.user_id !== userID) return;
-        if (tender.measure_type) {
-            // window.location.href = '/tender/' + tenderId;
-            window.open('/tender/' + tenderId, '_blank');
+    function getTenderNodeHtml(node, arr, pid) {
+        const html = [];
+        html.push('<tr pid="' + pid + '">');
+        // 名称
+        html.push('<td style="width: 40%" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
         } else {
-            for (const a of $('a', '#jlms')) {
-                a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
-            }
-            $('#jlms').modal('show');
-        }
-    });
-}
-
-$(document).ready(() => {
-    autoFlashHeight();
-    sortCategory();
-    // 初始化分类数据
-    initCategoryLevelNode();
-    $('.modal-body', '#add-bd').append(getCategoryHtml());
-    // 初始化标段树结构
-    tenderListOrder.reOrderTenders();
-    // initTenderTree();
-    // $('.c-body').html(getTenderTreeHtml());
-    bindTenderUrl();
-    tenderTreeShowLevel.initShowLevel();
-    // localHideList();
-
-    // 分类
-    $('#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});
+            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('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
+        }
+        html.push('</td>');
+        // 计量模式
+        html.push('<td style="width: 9%" class="text-center">');
+        if (node.measure_type) {
+            html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+        }
+        html.push('</td>');
+        // 创建人
+        html.push('<td style="width: 9%" class="text-center">', node.user_name ? node.user_name : '', '</td>');
+        // 游客
+        const visitor = node.visitor && node.visitor.length > 0
+            ? `<a href="javascirpt: void(0)" data-toggle="tooltip" data-placement="top" data-original-title="${node.visitor.join(',')}">${node.visitor.length}</a>`
+            : '';
+        html.push('<td style="width: 9%" class="text-center">', visitor, '</td>');
+        // 创建时间
+        html.push('<td style="width: 9%">', node.create_time ? moment(node.create_time).format('YYYY-MM-DD HH:mm:ss') : '', '</td>');
+        // 计量模式
+        // html.push('<td>');
+        // if (node.measure_type) {
+        //     html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+        // }
+        // html.push('</td>');
+        // 计量期数
+        html.push('<td style="width: 9%" class="text-center">');
+        if (!node.cid) {
+            if (node.progress) {
+                html.push(node.progress.title === '台账' ? '' : node.progress.title);
             } else {
-                data.push({id: c.id, level: node.getPath().length - 1});
+                html.push(node.lastStage ? '第' + node.lastStage.order + '期' : '台账');
             }
         }
-        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());
-            localHideList();
-            $('#cate-set').modal('hide');
-            tenderTreeShowLevel.refreshMenuVisible();
-        });
-    });
-    // 新增标段
-    $('#add-bd-ok').click(function () {
-        const data = {
-            name: cleanSymbols($('[name=name]', '#add-bd').val()),
-            valuation: $('[name=valuation]:checked').val(),
-            category: [],
-        };
-        if (!data.name || data.name === '') {
-            // TODO 提示用户
-            return;
-        }
-        for (const c of category) {
-            if (parseInt($('select', '[cate-id=' + c.id + ']').val()) !== 0) {
-                const cate = {cid: c.id};
-                // if (c.type === categoryType.key.dropDown) {
-                cate.value = parseInt($('select', '[cate-id=' + c.id + ']').val());
-                // } else if (c.type === categoryType.key.radio) {
-                //     cate.value = parseInt($('input:checked', '[cate-id=' + c.id + ']').val());
-                // }
-                data.category.push(cate);
+        html.push('</td>');
+        // 审批状态
+        html.push('<td style="width: 15%">');
+        if (!node.cid && node.cur_flow) {
+            if (node.stage_status !== undefined) {
+                html.push(`<span class="${node.progress.status_class}">${node.progress.status}</span>(${node.cur_flow.name})`);
+            } else {
+                html.push(`<span class="${node.lastStage ? auditConst.stage.tiStatusStringClass[node.lastStage.status] : auditConst.ledger.tiStatusStringClass[node.ledger_status]}">`);
+                html.push(node.lastStage ? auditConst.stage.statusString[node.lastStage.status] : auditConst.ledger.statusString[node.ledger_status]);
+                html.push('</span>');
+                html.push(node.status_users ? '(' + node.status_users + ')' : '');
             }
         }
-        $('#hide-all').show();
-        postData('/list/add', data, function (result) {
-            tenders.push(result);
-            initTenderTree();
-            $('.c-body').html(getTenderTreeHtml());
-            bindTenderUrl();
-            localHideList();
-            $('#add-bd').modal('hide');
-            $('[name=name]', '#add-bd').val('');
-            $('#hide-all').hide();
-        });
-    });
-});
+        html.push('</td>');
+        html.push('</tr>');
+        return html.join('');
+    }
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml }
+})();

+ 551 - 0
app/public/js/tender_list_base.js

@@ -0,0 +1,551 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2019/3/7
+ * @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: function (treeId, treeNodes, targetNode, moveType, isCopy) {
+            if (targetNode !== null && targetNode.lid !== 1) {
+                const parent = targetNode.getParentNode();
+                if (parent && parent.lid === 1) {
+                    return false;
+                }
+            }
+            for (var i=0,l=treeNodes.length; i<l; i++) {
+                if (treeNodes[i].drag === false) {
+                    return false;
+                }
+                if (!targetNode && treeNodes[i].dropRoot === false) {
+                    return false;
+                }
+                if(treeNodes[i].isParent === true && targetNode.lid !== 1){
+                    return false;
+                }
+            }
+            return true;
+        },
+        onDrop: 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 !== null && targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
+                moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
+            } else if (targetNode !== null && 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');
+                        }
+                    }
+                }
+            }
+        },
+    }
+};
+let selfLevelSort;
+const levelNodes =[];
+const tenderTree = [];
+let parentId = 0;
+function createTree(key) {
+    const zTree = $.fn.zTree.getZTreeObj(key);
+    if (zTree) zTree.destroy();
+    $.fn.zTree.init($(`#${key}`), levelTreeSetting, levelNodes);
+}
+// 查询方法
+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 loadSelfCategoryLevel(selfLevel){
+    selfLevelSort = selfLevel ? selfLevel.split(',') : [];
+    selfLevelSort = selfLevelSort.filter(x => {
+        return category.find(c => { return c.id + '' === x; });
+    });
+    category.forEach(cate => {
+        cate.is_self = selfLevelSort.length > 0;
+        cate.self_level = selfLevelSort.indexOf(cate.id + '') + 1;
+    });
+}
+function sortCategory() {
+    category.forEach(cate => {
+        cate.show_level = cate.is_self ? cate.self_level : cate.level;
+    });
+    category.sort(function (a, b) {
+        return a.show_level ? (b.show_level ? a.show_level - b.show_level : -1) : a.id - b.id;
+    });
+}
+// 初始化分类树结构数据
+function initCategoryLevelNode() {
+    levelNodes.length = 0;
+    levelNodes.push(
+        { lid:1, lpId:0, name:"可用类别", open:true, isParent: true, drag: false},
+        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true, drag: false}
+    );
+    for (const c of category) {
+        const cate = JSON.parse(JSON.stringify(c));
+        cate.lid = levelNodes.length + 1;
+        cate.open = true;
+        cate.dropRoot = false;
+        if (!cate.show_level) {
+            cate.lpId = 1;
+            levelNodes.push(cate);
+        } else {
+            cate.lpId = getPId(cate.show_level);
+            levelNodes.push(cate);
+        }
+    }
+}
+// 新建标段 -- 分类属性选择
+function getCategoryHtml() {
+    function getSelectCategoryHtml (cate) {
+        const html = [];
+        html.push('<div class="form-group" cate-id="' + cate.id + '">');
+        html.push('<label>', cate.name, '</label>');
+        html.push('<select class="form-control form-control-sm">');
+        for (const v of cate.value) {
+            html.push('<option value="' + v.id + '">', v.value, '</option>');
+        }
+        html.push('<option value="0">不选</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 iV in cate.value) {
+            const v = cate.value[iV];
+            html.push('<div class="form-check-inline">');
+            html.push('<input class="form-check-input" type="radio"', 'name="' + cate.name + '" ', 'value="' , v.id, (iV == 0 ? '" checked="' : ''),  '">');
+            html.push('<label class="form-check-label">', v.value, '</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.show_level && c.show_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, i = null) {
+        const array = parent ?  parent.children : tenderTree;
+        let cate = findCategoryNode(category.id, value, array);
+        if (!cate) {
+            const cateValue = findNode('id', value, category.value);
+            if (!cateValue) return null;
+            cate = {
+                cid: category.id,
+                vid: value,
+                name: cateValue.value,
+                children: [],
+                level: i ? i : category.show_level,
+                sort_id: ++parentId,
+                sort: cateValue.sort,
+            };
+            array.push(cate);
+        }
+        return cate;
+    }
+
+    function loadTenderCategory (tender) {
+        let tenderCategory = null;
+        for (const [index,lc] of levelCategory.entries()) {
+            const tenderCate = findNode('cid', lc.id, tender.category);
+            if (tenderCate) {
+                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+            } else {
+                if (index === 0 && tender.category) {
+                    for (const [i,c] of tender.category.entries()) {
+                        const cate = findNode('id', c.cid, category);
+                        if (cate) {
+                            tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
+                        } else {
+                            console.log(tender.name, c.cid, c.value);
+                        }
+                    }
+                }
+                return tenderCategory;
+            }
+        }
+        return tenderCategory;
+    }
+    tenderTree.splice(0, tenderTree.length);
+    for (const t of tenders) {
+        if (tenderListSpec.calculateTender) tenderListSpec.calculateTender(t);
+        t.valid = true;
+        delete t.level;
+        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);
+        }
+    }
+    sortTenderTree();
+    if (tenderListSpec.calculateParent) {
+        for (const t of tenderTree) {
+            tenderListSpec.calculateParent(t);
+        }
+    }
+}
+function recursiveGetTenderNodeHtml (node, arr, pid) {
+    const html = [];
+    html.push(tenderListSpec.getTenderNodeHtml(node, arr, pid));
+    if (node.children) {
+        for (const c of node.children) {
+            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
+        }
+    }
+    return html.join('');
+}
+// 根据TenderTree数据获取Html代码
+function getTenderTreeHtml () {
+    if (tenderTree.length > 0) {
+        const html = [];
+        html.push(tenderListSpec.getTenderTreeHeaderHtml());
+        parentId = 0;
+        for (const t of tenderTree) {
+            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
+        }
+        html.push('</table>');
+        return html.join('');
+    } else {
+        return EmptyTenderHtml.join('');
+    }
+}
+function bindTenderUrl() {
+    // 打开标段
+    $('body').on('click', '.c-body a[name=name]', function () {
+        const tenderId = parseInt($(this).attr('id'));
+        const tender = _.find(tenders, function (t) {
+            return t.id === tenderId;
+        });
+        if (!tender) return;
+        if (!tender.measure_type && tender.user_id !== userID) return;
+        if (tender.measure_type) {
+            // window.location.href = '/tender/' + tenderId;
+            window.open('/tender/' + tenderId, '_blank');
+        } else {
+            for (const a of $('a', '#jlms')) {
+                a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
+            }
+            $('#jlms').modal('show');
+        }
+    });
+    // 编辑
+    $('body').on('click', '.c-body a[name=edit]', function () {
+        const tid = parseInt($(this).parent().attr('tid'));
+        const tender = _.find(tenders, {id: tid});
+        $('[name=name]', '#edit-bd').val(tender.name);
+        $('input[type=radio]', '#add-bd').prop('checked', false);
+        $('option[value=0]', '#edit-bd').prop('selected', true);
+        for (const c of tender.category) {
+            // $('input[value=' + c.value + ']', '#edit-bd').prop('checked', 'checked');
+            $('option[value=' + c.value + ']', '#edit-bd').prop('selected', true);
+        }
+        $('#edit-bd-ok').attr('tid', tid);
+        $('#edit-bd').modal('show');
+    });
+    // 删除
+    $('body').on('click', '.c-body a[name=del]', function () {
+        const tid = parseInt($(this).parent().attr('tid'));
+        const tender = _.find(tenders, {id: tid});
+        $('#del-bd-ok').attr('tid', tid);
+        $('#del-tender-name').text(tender.name);
+        $('#del-bd').modal('show');
+    });
+}
+
+$(document).ready(() => {
+    autoFlashHeight();
+    loadSelfCategoryLevel(selfCategoryLevel);
+    sortCategory();
+    // 初始化分类数据
+    initCategoryLevelNode();
+    $('.modal-body', '#add-bd').append(getCategoryHtml());
+    $('.modal-body', '#edit-bd').append(getCategoryHtml());
+    // 初始化标段树结构
+    tenderListOrder.reOrderTenders();
+    initTenderTree();
+    $('.c-body').html(getTenderTreeHtml());
+    bindTenderUrl();
+    localHideList();
+    tenderTreeShowLevel.initShowLevel();
+    // 分类
+    $('#cate-set').on('show.bs.modal', function () {
+        createTree('treeLevel');
+    });
+    $('#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());
+            localHideList();
+            $('#cate-set').modal('hide');
+            tenderTreeShowLevel.refreshMenuVisible();
+        });
+    });
+    $('#cate-set-self').on('show.bs.modal', function () {
+        createTree('treeLevel-self');
+    });
+    $('#set-cate-self-reset').click(function () {
+        postData('/setting/category/self-level', {self_category_level: ''}, function (rst) {
+            loadSelfCategoryLevel('');
+            sortCategory();
+            initCategoryLevelNode();
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+            localHideList();
+            $('#cate-set-self').modal('hide');
+            tenderTreeShowLevel.refreshMenuVisible();
+        });
+    });
+    $('#set-cate-self-ok').click(function () {
+        const zTree = $.fn.zTree.getZTreeObj('treeLevel-self');
+        const defaultLevel = [], selfLevel = [];
+        for (const c of category) {
+            const node = zTree.getNodeByParam('id', c.id);
+            const parent = node.getParentNode();
+            if (c.level > 0) defaultLevel.push({id: c.id, level: c.level});
+            if (parent.lid === 2) {
+                selfLevel.push({id: c.id, level: node.getPath().length - 1});
+            }
+        }
+        const defaultLevelStr = defaultLevel.sort((x, y) => { return x.level - y.level; }).map(x => {return x.id; }).join(',');
+        const selfLevelStr = selfLevel.sort((x, y) => { return x.level - y.level; }).map(x => {return x.id; }).join(',');
+        const self_category_level = selfLevelStr === defaultLevelStr ? '' : selfLevelStr;
+        postData('/setting/category/self-level', {self_category_level}, function (rst) {
+            loadSelfCategoryLevel(self_category_level);
+            sortCategory();
+            initCategoryLevelNode();
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+            localHideList();
+            $('#cate-set-self').modal('hide');
+            tenderTreeShowLevel.refreshMenuVisible();
+        });
+    });
+
+    $('a[name=add]').click(function () {
+        $('input[type=radio]', '#edit-bd').prop('checked', false);
+        $('input[type=radio]', '#add-bd').eq(0).prop('checked', true);
+    });
+    // 新增标段
+    $('#add-bd-ok').click(function () {
+        const data = {
+            name: cleanSymbols($('[name=name]', '#add-bd').val()),
+            valuation: $('[name=valuation]:checked').val(),
+            category: [],
+        };
+        if (!data.name || data.name === '') {
+            // TODO 提示用户
+            return;
+        }
+        for (const c of category) {
+            const cateObj = $('[cate-id=' + c.id + ']', '#add-bd');
+            if (parseInt($('select', cateObj).val()) !== 0) {
+                const cate = {cid: c.id};
+                cate.value = parseInt($('select', cateObj).val());
+                data.category.push(cate);
+            }
+            // if (c.type === categoryType.key.dropDown) {
+            //     cate.value = parseInt($('select', cateObj).val());
+            // } else if (c.type === categoryType.key.radio) {
+            //     cate.value = parseInt($('input:checked', cateObj).val());
+            // }
+
+        }
+        postData('/list/add', data, function (result) {
+            tenders.push(result);
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+            bindTenderUrl();
+            localHideList();
+            $('#add-bd').modal('hide');
+            $('[name=name]', '#add-bd').val('');
+        });
+    });
+    // 编辑标段
+    $('#edit-bd-ok').click(function () {
+        const data = {
+            id: parseInt($(this).attr('tid')),
+            name: cleanSymbols($('[name=name]', '#edit-bd').val()),
+            category: [],
+        };
+        if (!data.name || data.name === '') {
+            // TODO 提示用户
+            return;
+        }
+        for (const c of category) {
+            const cateObj = $('[cate-id=' + c.id + ']', '#edit-bd');
+            if (parseInt($('select', cateObj).val()) !== 0) {
+                const cate = {cid: c.id};
+                cate.value = parseInt($('select', cateObj).val());
+                data.category.push(cate);
+            }
+            // if (c.type === categoryType.key.dropDown) {
+            //     cate.value = parseInt($('select', cateObj).val());
+            // } else if (c.type === categoryType.key.radio) {
+            //     cate.value = parseInt($('input:checked', cateObj).val());
+            // }
+            // data.category.push(cate);
+        }
+        postData('/list/update', data, function (result) {
+            const tender = _.find(tenders, {id: result.id});
+            _.assign(tender, result);
+            initTenderTree();
+            $('.c-body').html(getTenderTreeHtml());
+            bindTenderUrl();
+            localHideList();
+            $('#edit-bd').modal('hide');
+        });
+    });
+    // 删除标段
+    $('#del-bd-ok').click(function () {
+        const tid = parseInt($(this).attr('tid'));
+        if (tid >= 0) {
+            postData('/list/del', [tid], function (result) {
+                function getCategory(arr, id) {
+                    for (const a of arr) {
+                        if (a.cid) {
+                            const ac = getCategory(a.children, id);
+                            if (ac) {
+                                return ac;
+                            }
+                        } else if (a.id === id) {
+                            return arr;
+                        }
+                    }
+                    return null;
+                }
+                for (const rid of result) {
+                    const tr = $('td[tid=' + rid + ']').parent();
+                    const arr = getCategory(tenderTree, rid);
+                    if (arr) {
+                        const a = arr.find(function (x) {
+                            return x.id === rid;
+                        });
+                        if (arr.length > 1 && arr.indexOf(a) === arr.length - 1) {
+                            const span = $('span', tr.prev());
+                            span.text('└');
+                        }
+                        arr.splice(arr.indexOf(a), 1);
+                    }
+                    _.remove(tenders, function (n) {
+                        return n.id === rid;
+                    });
+                    tr.remove();
+                    $('#del-bd').modal('hide');
+                }
+            });
+        } else {
+            $('#del-bd').modal('hide');
+        }
+    });
+});

+ 142 - 506
app/public/js/tender_list_info.js

@@ -7,418 +7,109 @@
  * @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 = [];
-let parentId = 0;
-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 !== null && targetNode.lid !== 1) {
-        const parent = targetNode.getParentNode();
-        if (parent && parent.lid === 1) {
-            return false;
-        }
-    }
-    for (var i=0,l=treeNodes.length; i<l; i++) {
-        if (treeNodes[i].drag === false) {
-            return false;
-        }
-        if (!targetNode && treeNodes[i].dropRoot === false) {
-            return false;
-        }
-        if(treeNodes[i].isParent === true && targetNode.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 !== null && targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
-        moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
-    } else if (targetNode !== null && 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, drag: false},
-        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true, drag: false}
-    );
-    for (const c of category) {
-        const cate = JSON.parse(JSON.stringify(c));
-        cate.lid = levelNodes.length + 1;
-        cate.open = true;
-        cate.dropRoot = false;
-        if (!cate.level) {
-            cate.lpId = 1;
-            levelNodes.push(cate);
-        } else {
-            cate.lpId = getPId(cate.level);
-            levelNodes.push(cate);
-        }
-    }
-}
-// 新建标段 -- 分类属性选择
-function getCategoryHtml() {
-    function getSelectCategoryHtml (cate) {
+const tenderListSpec = (function(){
+    function getTenderNodeHtml(node, arr, pid) {
         const html = [];
-        html.push('<div class="form-group" cate-id="' + cate.id + '">');
-        html.push('<lable>', cate.name, '</lable>');
-        html.push('<select class="form-control form-control-sm">');
-        for (const v of cate.value) {
-            html.push('<option value="' + v.id + '">', v.value, '</option>');
-        }
-        html.push('<option value="0">不选</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 iV in cate.value) {
-            const v = cate.value[iV];
-            html.push('<div class="form-check-inline">');
-            html.push('<input class="form-check-input" type="radio"', 'name="' + cate.name + '" ', 'value="' , v.id, (iV == 0 ? '" checked="' : ''),  '">');
-            html.push('<label class="form-check-label">', v.value, '</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 calculateParent(node) {
-    if (node.children && node.cid) {
-        node.total_price = 0;
-        node.gather_tp = 0;
-        node.end_contract_tp = 0;
-        node.end_qc_tp = 0;
-        node.end_gather_tp = 0;
-        node.pre_gather_tp = 0;
-        node.yf_tp = 0;
-        node.end_yf_tp = 0;
-        node.advance_tp = 0;
-        node.contract_price = 0;
-        for (const c of node.children) {
-            calculateParent(c);
-            node.total_price = ZhCalc.add(node.total_price, c.total_price);
-            node.gather_tp = ZhCalc.add(node.gather_tp, c.gather_tp);
-            node.end_contract_tp = ZhCalc.add(node.end_contract_tp, c.end_contract_tp);
-            node.end_qc_tp = ZhCalc.add(node.end_qc_tp, c.end_qc_tp);
-            node.end_gather_tp = ZhCalc.add(node.end_gather_tp, c.end_gather_tp);
-            node.pre_gather_tp = ZhCalc.add(node.pre_gather_tp, c.pre_gather_tp);
-            node.yf_tp = ZhCalc.add(node.yf_tp, c.yf_tp);
-            node.end_yf_tp = ZhCalc.add(node.end_yf_tp, c.end_yf_tp);
-            node.advance_tp = ZhCalc.add(node.advance_tp, c.advance_tp);
-            node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
-        }
-    }
-}
-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, i = null) {
-        const array = parent ?  parent.children : tenderTree;
-        let cate = findCategoryNode(category.id, value, array);
-        if (!cate) {
-            const cateValue = findNode('id', value, category.value);
-            if (!cateValue) return null;
-            cate = {
-                cid: category.id,
-                vid: value,
-                name: cateValue.value,
-                children: [],
-                level: i ? i : category.level,
-                sort_id: ++parentId,
-                sort: cateValue.sort,
-            };
-            array.push(cate);
-        }
-        return cate;
-    }
-    function loadTenderCategory (tender) {
-        let tenderCategory = null;
-        for (const [index, lc] of levelCategory.entries()) {
-            const tenderCate = findNode('cid', lc.id, tender.category);
-            if (tenderCate) {
-                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+        html.push('<tr pid="' + pid + '">');
+        // 名称
+        html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
+        } 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('<a href="javascript: void(0)" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
+        }
+        html.push('</td>');
+        // 计量模式
+        html.push('<td style="width: 75px" class="text-center">');
+        if (node.measure_type) {
+            html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+        }
+        html.push('</td>');
+        // 计量进度
+        html.push('<td style="width: 105px">');
+        if (!node.cid && node.cur_flow) {
+            if (node.progress) {
+                html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
             } else {
-                if (index === 0 && tender.category) {
-                    for (const [i,c] of tender.category.entries()) {
-                        const cate = findNode('id', c.cid, category);
-                        if (cate) {
-                            tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
-                        } else {
-                            console.log(tender.name, c.cid, c.value);
-                        }
-                    }
-                }
-                return tenderCategory;
+                html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
             }
         }
-        return tenderCategory;
-    }
-    function calculateTender(tender) {
-        if (tender.stage_tp) {
-            tender.gather_tp = ZhCalc.sum([tender.stage_tp.contract_tp, tender.stage_tp.qc_tp, tender.stage_tp.pc_tp]);
-            tender.end_contract_tp = ZhCalc.sum([tender.stage_tp.pre_contract_tp, tender.stage_tp.contract_tp, tender.stage_tp.contract_pc_tp]);
-            tender.end_qc_tp = ZhCalc.sum([tender.stage_tp.pre_qc_tp, tender.stage_tp.qc_tp, tender.stage_tp.qc_pc_tp]);
-            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
-            tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
-            tender.yf_tp = ZhCalc.add(tender.stage_tp.yf_tp);
-            tender.end_yf_tp = ZhCalc.add(tender.stage_tp.pre_yf_tp, tender.yf_tp);
-        } else if (tender.lastStage) {
-            tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
-            tender.end_contract_tp = ZhCalc.sum([tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp, tender.lastStage.contract_pc_tp]);
-            tender.end_qc_tp = ZhCalc.sum([tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp, tender.lastStage.qc_pc_tp]);
-            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
-            tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
-            tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
-            tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
-        }
-    }
-    tenderTree.splice(0, tenderTree.length);
-    for (const t of tenders) {
-        calculateTender(t);
-        t.valid = true;
-        delete t.level;
-        if (t.category && levelCategory.length > 0) {
-            const parent = loadTenderCategory(t);
-            if (parent) {
-                t.level = parent.level + 1;
-                parent.children.push(t);
+        html.push('</td>');
+        // 当前流程
+        html.push('<td style="width: 230px">');
+        if (!node.cid && node.cur_flow) {
+            if (node.stage_status !== undefined) {
+                const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
+                html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
+                    ? curUser
+                    : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+                );
+                html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
             } else {
-                tenderTree.push(t);
+                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
+                    '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
+                    ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
+                html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
+                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
+                    '</a> ');
+                html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
             }
-        } else {
-            tenderTree.push(t);
-        }
-    }
-    sortTenderTree();
-    for (const t of tenderTree) {
-        calculateParent(t);
-    }
-}
-function recursiveGetTenderNodeHtml (node, arr, pid) {
-    const html = [];
-    html.push('<tr pid="' + pid + '">');
-    // 名称
-    html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
-    if (node.cid) {
-        html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
-    } 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('<a href="javascript: void(0)" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
-    }
-    html.push('</td>');
-    // 计量模式
-    html.push('<td style="width: 75px" class="text-center">');
-    if (node.measure_type) {
-        html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
-    }
-    html.push('</td>');
-    // 计量进度
-    html.push('<td style="width: 105px">');
-    if (!node.cid && node.cur_flow) {
-        if (node.progress) {
-            html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
-        } else {
-            html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
-        }
-    }
-    html.push('</td>');
-    // 当前流程
-    html.push('<td style="width: 230px">');
-    if (!node.cid && node.cur_flow) {
-        if (node.stage_status !== undefined) {
-            const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
-            html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
-                ? curUser
-                : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
-            );
-            html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
-        } else {
-            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-                '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-                ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-            html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
-                '</a> ');
-            html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
-        }
-    }
-    html.push('</td>');
-    // 上一流程审批时间
-    // html.push('<td style="width: 7%">');
-    // if (!node.cid && node.pre_flow) {
-    //     html.push(node.pre_flow.name + ' ' + moment(node.pre_flow.time).format('YYYY-MM-DD'));
-    // }
-    // html.push('</td>');
-    // 签约合同价
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.contract_price || '');
-    html.push('</td>');
-    // 0号台账合同
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.total_price || '');
-    html.push('</td>');
-    // 本期完成
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.gather_tp || '');
-    html.push('</td>');
-    // 截止本期合同
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.end_contract_tp || '');
-    html.push('</td>');
-    // 截止本期变更
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.end_qc_tp || '');
-    html.push('</td>');
-    // 截止本期完成
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.end_gather_tp || '');
-    html.push('</td>');
-    // 截止上期完成
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.pre_gather_tp || '');
-    html.push('</td>');
-    // 预付款
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.advance_tp || '');
-    html.push('</td>');
-    // 本期应付
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.yf_tp || '');
-    html.push('</td>');
-    // 截止本期应付
-    html.push('<td style="width: 100px" class="text-right">');
-    html.push(node.end_yf_tp || '');
-    html.push('</td>');
-    html.push('</tr>');
-    if (node.children) {
-        for (const c of node.children) {
-            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
         }
+        html.push('</td>');
+        // 上一流程审批时间
+        // html.push('<td style="width: 7%">');
+        // if (!node.cid && node.pre_flow) {
+        //     html.push(node.pre_flow.name + ' ' + moment(node.pre_flow.time).format('YYYY-MM-DD'));
+        // }
+        // html.push('</td>');
+        // 签约合同价
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.contract_price || '');
+        html.push('</td>');
+        // 0号台账合同
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.total_price || '');
+        html.push('</td>');
+        // 本期完成
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.gather_tp || '');
+        html.push('</td>');
+        // 截止本期合同
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.end_contract_tp || '');
+        html.push('</td>');
+        // 截止本期变更
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.end_qc_tp || '');
+        html.push('</td>');
+        // 截止本期完成
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.end_gather_tp || '');
+        html.push('</td>');
+        // 截止上期完成
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.pre_gather_tp || '');
+        html.push('</td>');
+        // 预付款
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.advance_tp || '');
+        html.push('</td>');
+        // 本期应付
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.yf_tp || '');
+        html.push('</td>');
+        // 截止本期应付
+        html.push('<td style="width: 100px" class="text-right">');
+        html.push(node.end_yf_tp || '');
+        html.push('</td>');
+        html.push('</tr>');
+        return html.join('');
     }
-    return html.join('');
-}
-// 根据TenderTree数据获取Html代码
-function getTenderTreeHtml () {
-    if (tenderTree.length > 0) {
+    function getTenderTreeHeaderHtml() {
         const html = [];
         html.push('<table class="table table-hover table-bordered">');
         html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
@@ -438,110 +129,55 @@ function getTenderTreeHtml () {
         html.push('<th class="text-center" style="width: 100px">', '本期应付', '</th>');
         html.push('<th class="text-center" style="width: 100px">', '截止本期应付', '</th>');
         html.push('</tr>', '</thead>');
-        parentId = 0;
-        for (const t of tenderTree) {
-            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
-        }
-        html.push('</table>');
         return html.join('');
-    } else {
-        return EmptyTenderHtml.join('');
     }
-}
-function bindTenderUrl() {
-    $('.c-body').on('click', 'a', function () {
-        const tenderId = parseInt($(this).attr('id'));
-        const tender = _.find(tenders, function (t) {
-            return t.id === tenderId;
-        });
-        if (!tender) return;
-        if (!tender.measure_type && tender.user_id !== userID) return;
-        if (tender.measure_type) {
-            // window.location.href = '/tender/' + tenderId;
-            window.open('/tender/' + tenderId, '_blank');
-        } else {
-            for (const a of $('a', '#jlms')) {
-                a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
-            }
-            $('#jlms').modal('show');
-        }
-    });
-}
-
-$(document).ready(() => {
-    autoFlashHeight();
-    sortCategory();
-    // 初始化分类数据
-    initCategoryLevelNode();
-    $('.modal-body', '#add-bd').append(getCategoryHtml());
-    // 初始化标段树结构
-    initTenderTree();
-    $('.c-body').html(getTenderTreeHtml());
-    bindTenderUrl();
-    localHideList();
-    tenderTreeShowLevel.initShowLevel();
-    // 分类
-    $('#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());
-            localHideList();
-            $('#cate-set').modal('hide');
-            tenderTreeShowLevel.refreshMenuVisible();
-        });
-    });
-    // 新增标段
-    $('#add-bd-ok').click(function () {
-        const data = {
-            name: cleanSymbols($('[name=name]', '#add-bd').val()),
-            valuation: $('[name=valuation]:checked').val(),
-            category: [],
-        };
-        if (!data.name || data.name === '') {
-            // TODO 提示用户
-            return;
+    function calculateTender(tender) {
+        if (tender.stage_tp) {
+            tender.gather_tp = ZhCalc.sum([tender.stage_tp.contract_tp, tender.stage_tp.qc_tp, tender.stage_tp.pc_tp]);
+            tender.end_contract_tp = ZhCalc.sum([tender.stage_tp.pre_contract_tp, tender.stage_tp.contract_tp, tender.stage_tp.contract_pc_tp]);
+            tender.end_qc_tp = ZhCalc.sum([tender.stage_tp.pre_qc_tp, tender.stage_tp.qc_tp, tender.stage_tp.qc_pc_tp]);
+            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
+            tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
+            tender.yf_tp = ZhCalc.add(tender.stage_tp.yf_tp);
+            tender.end_yf_tp = ZhCalc.add(tender.stage_tp.pre_yf_tp, tender.yf_tp);
+        } else if (tender.lastStage) {
+            tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
+            tender.end_contract_tp = ZhCalc.sum([tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp, tender.lastStage.contract_pc_tp]);
+            tender.end_qc_tp = ZhCalc.sum([tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp, tender.lastStage.qc_pc_tp]);
+            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
+            tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
+            tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
+            tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
         }
-        for (const c of category) {
-            if (parseInt($('select', '[cate-id=' + c.id + ']').val()) !== 0) {
-                const cate = {cid: c.id};
-                // if (c.type === categoryType.key.dropDown) {
-                cate.value = parseInt($('select', '[cate-id=' + c.id + ']').val());
-                // } else if (c.type === categoryType.key.radio) {
-                //     cate.value = parseInt($('input:checked', '[cate-id=' + c.id + ']').val());
-                // }
-                data.category.push(cate);
+    }
+    function calculateParent(node) {
+        if (node.children && node.cid) {
+            node.total_price = 0;
+            node.gather_tp = 0;
+            node.end_contract_tp = 0;
+            node.end_qc_tp = 0;
+            node.end_gather_tp = 0;
+            node.pre_gather_tp = 0;
+            node.yf_tp = 0;
+            node.end_yf_tp = 0;
+            node.advance_tp = 0;
+            node.contract_price = 0;
+            for (const c of node.children) {
+                calculateParent(c);
+                node.total_price = ZhCalc.add(node.total_price, c.total_price);
+                node.gather_tp = ZhCalc.add(node.gather_tp, c.gather_tp);
+                node.end_contract_tp = ZhCalc.add(node.end_contract_tp, c.end_contract_tp);
+                node.end_qc_tp = ZhCalc.add(node.end_qc_tp, c.end_qc_tp);
+                node.end_gather_tp = ZhCalc.add(node.end_gather_tp, c.end_gather_tp);
+                node.pre_gather_tp = ZhCalc.add(node.pre_gather_tp, c.pre_gather_tp);
+                node.yf_tp = ZhCalc.add(node.yf_tp, c.yf_tp);
+                node.end_yf_tp = ZhCalc.add(node.end_yf_tp, c.end_yf_tp);
+                node.advance_tp = ZhCalc.add(node.advance_tp, c.advance_tp);
+                node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
             }
         }
-        $('#hide-all').show();
-        postData('/list/add', data, function (result) {
-            tenders.push(result);
-            initTenderTree();
-            $('.c-body').html(getTenderTreeHtml());
-            bindTenderUrl();
-            localHideList();
-            $('#add-bd').modal('hide');
-            $('[name=name]', '#add-bd').val('');
-            $('#hide-all').hide();
-        });
-    });
-});
+    }
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml, calculateTender, calculateParent }
+})();
+
+

+ 47 - 533
app/public/js/tender_list_manage.js

@@ -1,544 +1,58 @@
-'use strict';
-
-/**
- *
- *
- * @author Mai
- * @date 2019/3/7
- * @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 = [];
-let parentId = 0;
-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 !== null && targetNode.lid !== 1) {
-        const parent = targetNode.getParentNode();
-        if (parent && parent.lid === 1) {
-            return false;
-        }
-    }
-    for (var i=0,l=treeNodes.length; i<l; i++) {
-        if (treeNodes[i].drag === false) {
-            return false;
-        }
-        if (!targetNode && treeNodes[i].dropRoot === false) {
-            return false;
-        }
-        if(treeNodes[i].isParent === true && targetNode.lid !== 1){
-            return false;
-        }
-    }
-    return true;
-}
-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 !== null && targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
-        moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
-    } else if (targetNode !== null && 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, drag: false},
-        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true, drag: false}
-    );
-    for (const c of category) {
-        const cate = JSON.parse(JSON.stringify(c));
-        cate.lid = levelNodes.length + 1;
-        cate.open = true;
-        cate.dropRoot = false;
-        if (!cate.level) {
-            cate.lpId = 1;
-            levelNodes.push(cate);
-        } else {
-            cate.lpId = getPId(cate.level);
-            levelNodes.push(cate);
-        }
-    }
-}
-// 新建标段 -- 分类属性选择
-function getCategoryHtml() {
-    function getSelectCategoryHtml (cate) {
+const tenderListSpec = (function(){
+    function getTenderNodeHtml(node, arr, pid) {
         const html = [];
-        html.push('<div class="form-group" cate-id="' + cate.id + '">');
-        html.push('<label>', cate.name, '</label>');
-        html.push('<select class="form-control form-control-sm">');
-        for (const v of cate.value) {
-            html.push('<option value="' + v.id + '">', v.value, '</option>');
-        }
-        html.push('<option value="0">不选</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 iV in cate.value) {
-            const v = cate.value[iV];
-            html.push('<div class="form-check-inline">');
-            html.push('<input class="form-check-input" type="radio"', 'name="' + cate.name + '" ', 'value="' , v.id, (iV == 0 ? '" checked="' : ''),  '">');
-            html.push('<label class="form-check-label">', v.value, '</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, i = null) {
-        const array = parent ?  parent.children : tenderTree;
-        let cate = findCategoryNode(category.id, value, array);
-        if (!cate) {
-            const cateValue = findNode('id', value, category.value);
-            if (!cateValue) return null;
-            cate = {
-                cid: category.id,
-                vid: value,
-                name: cateValue.value,
-                children: [],
-                level: i ? i : category.level,
-                sort_id: ++parentId,
-                sort: cateValue.sort,
-            };
-            array.push(cate);
-        }
-        return cate;
-    }
-
-    function loadTenderCategory (tender) {
-        let tenderCategory = null;
-        for (const [index,lc] of levelCategory.entries()) {
-            const tenderCate = findNode('cid', lc.id, tender.category);
-            if (tenderCate) {
-                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+        html.push('<tr pid="' + pid + '">');
+        // 名称
+        html.push('<td style="width: 45%" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
+        } else {
+            html.push('<span class="text-muted mr-2">');
+            html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+            html.push('</span>');
+            html.push('<a href="javascript: void(0)" name="name" id="' + node.id + '">', node.name, '</a>');
+        }
+        html.push('</td>');
+        // 创建人
+        html.push('<td style="width: 10%" class="text-center">', node.user_name, '</td>');
+        // 创建时间
+        html.push('<td style="width: 15%">', node.create_time ? moment(node.create_time).format('YYYY-MM-DD HH:mm:ss') : '', '</td>');
+        // 完成期数
+        html.push('<td style="width: 10%" class="text-center">');
+        if (!node.cid) {
+            if (node.progress) {
+                html.push(node.progress.title);
             } else {
-                if (index === 0 && tender.category) {
-                    for (const [i,c] of tender.category.entries()) {
-                        const cate = findNode('id', c.cid, category);
-                        if (cate) {
-                            tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
-                        } else {
-                            console.log(tender.name, c.cid, c.value);
-                        }
-                    }
-                }
-                return tenderCategory;
+                html.push(node.lastStage ? '第' + node.lastStage.order + '期' : '第0期');
             }
         }
-        return tenderCategory;
-    }
-    tenderTree.splice(0, tenderTree.length);
-    for (const t of tenders) {
-        t.valid = true;
-        delete t.level;
-        if (t.category && levelCategory.length > 0) {
-            const parent = loadTenderCategory(t);
-            if (parent) {
-                t.level = parent.level + 1;
-                parent.children.push(t);
+        html.push('</td>');
+        // 管理
+        html.push('<td style="width: 20%" tid="' + node.id + '">');
+        if (!node.cid) {
+            html.push('<a href="javascript: void(0)" name="edit" class="btn btn-outline-primary btn-sm">编辑</a>');
+            if (node.lastStage === null || node.lastStage === undefined) {
+                html.push('<a href="javascript: void(0)" name="del" class="btn btn-outline-danger btn-sm ml-1">删除</a>');
             } else {
-                tenderTree.push(t);
+                html.push('<button class="btn btn-outline-secondary btn-sm ml-1" data-toggle="tooltip" data-placement="top" title="请先删除所有期">删除</button>');
             }
-        } else {
-            tenderTree.push(t);
-        }
-    }
-    sortTenderTree();
-}
-function recursiveGetTenderNodeHtml (node, arr, pid) {
-    const html = [];
-    html.push('<tr pid="' + pid + '">');
-    // 名称
-    html.push('<td style="width: 45%" class="in-' + node.level + '">');
-    if (node.cid) {
-        html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
-    } else {
-        html.push('<span class="text-muted mr-2">');
-        html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
-        html.push('</span>');
-        html.push('<a href="javascript: void(0)" name="name" id="' + node.id + '">', node.name, '</a>');
-    }
-    html.push('</td>');
-    // 创建人
-    html.push('<td style="width: 10%" class="text-center">', node.user_name, '</td>');
-    // 创建时间
-    html.push('<td style="width: 15%">', node.create_time ? moment(node.create_time).format('YYYY-MM-DD HH:mm:ss') : '', '</td>');
-    // 完成期数
-    html.push('<td style="width: 10%" class="text-center">');
-    if (!node.cid) {
-        if (node.progress) {
-            html.push(node.progress.title);
-        } else {
-            html.push(node.lastStage ? '第' + node.lastStage.order + '期' : '第0期');
-        }
-    }
-    html.push('</td>');
-    // 管理
-    html.push('<td style="width: 20%" tid="' + node.id + '">');
-    if (!node.cid) {
-        html.push('<a href="javascript: void(0)" name="edit" class="btn btn-outline-primary btn-sm">编辑</a>');
-        if (node.lastStage === null || node.lastStage === undefined) {
-            html.push('<a href="javascript: void(0)" name="del" class="btn btn-outline-danger btn-sm ml-1">删除</a>');
-        } else {
-            html.push('<button class="btn btn-outline-secondary btn-sm ml-1" data-toggle="tooltip" data-placement="top" title="请先删除所有期">删除</button>');
-        }
-        if (cache) html.push(`<a href="/list/refreshCache?tid=${node.id}" class="btn btn-outline-primary btn-sm ml-1">更新缓存</a>`);
-    }
-    html.push('</td>');
-    html.push('</tr>');
-    if (node.children) {
-        for (const c of node.children) {
-            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
+            if (cache) html.push(`<a href="/list/refreshCache?tid=${node.id}" class="btn btn-outline-primary btn-sm ml-1">更新缓存</a>`);
         }
+        html.push('</td>');
+        html.push('</tr>');
+        return html.join('');
     }
-    return html.join('');
-}
-function getTenderTreeHeaderHtml() {
-    const html = [];
-    html.push('<table class="table table-hover table-bordered">');
-    html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
-    html.push('<th class="text-center" style="width: 45%">', '标段名称', tenderListOrder.getOrderButton('name'), '</th>');
-    html.push('<th class="text-center" style="width: 10%">', '创建人', '</th>');
-    html.push('<th class="text-center" style="width: 15%">', '创建时间', tenderListOrder.getOrderButton('create_time'), '</th>');
-    html.push('<th class="text-center" style="width: 10%">', '完成期数', '</th>');
-    html.push('<th class="text-center" style="width: 20%">', '管理', '</th>');
-    html.push('</tr>', '</thead>');
-    return html.join('');
-}
-// 根据TenderTree数据获取Html代码
-function getTenderTreeHtml () {
-    if (tenderTree.length > 0) {
+    function getTenderTreeHeaderHtml() {
         const html = [];
-        html.push(getTenderTreeHeaderHtml());
-        parentId = 0;
-        for (const t of tenderTree) {
-            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
-        }
-        html.push('</table>');
+        html.push('<table class="table table-hover table-bordered">');
+        html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
+        html.push('<th class="text-center" style="width: 45%">', '标段名称', tenderListOrder.getOrderButton('name'), '</th>');
+        html.push('<th class="text-center" style="width: 10%">', '创建人', '</th>');
+        html.push('<th class="text-center" style="width: 15%">', '创建时间', tenderListOrder.getOrderButton('create_time'), '</th>');
+        html.push('<th class="text-center" style="width: 10%">', '完成期数', '</th>');
+        html.push('<th class="text-center" style="width: 20%">', '管理', '</th>');
+        html.push('</tr>', '</thead>');
         return html.join('');
-    } else {
-        return EmptyTenderHtml.join('');
     }
-}
-function bindTenderUrl() {
-    // 打开标段
-    $('body').on('click', '.c-body a[name=name]', function () {
-        const tenderId = parseInt($(this).attr('id'));
-        const tender = _.find(tenders, function (t) {
-            return t.id === tenderId;
-        });
-        if (!tender) return;
-        if (!tender.measure_type && tender.user_id !== userID) return;
-        if (tender.measure_type) {
-            // window.location.href = '/tender/' + tenderId;
-            window.open('/tender/' + tenderId, '_blank');
-        } else {
-            for (const a of $('a', '#jlms')) {
-                a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
-            }
-            $('#jlms').modal('show');
-        }
-    });
-    // 编辑
-    $('body').on('click', '.c-body a[name=edit]', function () {
-        const tid = parseInt($(this).parent().attr('tid'));
-        const tender = _.find(tenders, {id: tid});
-        $('[name=name]', '#edit-bd').val(tender.name);
-        $('input[type=radio]', '#add-bd').prop('checked', false);
-        $('option[value=0]', '#edit-bd').prop('selected', true);
-        for (const c of tender.category) {
-            // $('input[value=' + c.value + ']', '#edit-bd').prop('checked', 'checked');
-            $('option[value=' + c.value + ']', '#edit-bd').prop('selected', true);
-        }
-        $('#edit-bd-ok').attr('tid', tid);
-        $('#edit-bd').modal('show');
-    });
-    // 删除
-    $('body').on('click', '.c-body a[name=del]', function () {
-        const tid = parseInt($(this).parent().attr('tid'));
-        const tender = _.find(tenders, {id: tid});
-        $('#del-bd-ok').attr('tid', tid);
-        $('#del-tender-name').text(tender.name);
-        $('#del-bd').modal('show');
-    });
-}
-
-$(document).ready(() => {
-    autoFlashHeight();
-    sortCategory();
-    // 初始化分类数据
-    initCategoryLevelNode();
-    $('.modal-body', '#add-bd').append(getCategoryHtml());
-    $('.modal-body', '#edit-bd').append(getCategoryHtml());
-    // 初始化标段树结构
-    tenderListOrder.reOrderTenders();
-    initTenderTree();
-    $('.c-body').html(getTenderTreeHtml());
-    bindTenderUrl();
-    localHideList();
-    tenderTreeShowLevel.initShowLevel();
-    // 分类
-    $('#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());
-            localHideList();
-            $('#cate-set').modal('hide');
-            tenderTreeShowLevel.refreshMenuVisible();
-        });
-    });
-
-    $('a[name=add]').click(function () {
-        $('input[type=radio]', '#edit-bd').prop('checked', false);
-        $('input[type=radio]', '#add-bd').eq(0).prop('checked', true);
-    });
-    // 新增标段
-    $('#add-bd-ok').click(function () {
-        const data = {
-            name: cleanSymbols($('[name=name]', '#add-bd').val()),
-            valuation: $('[name=valuation]:checked').val(),
-            category: [],
-        };
-        if (!data.name || data.name === '') {
-            // TODO 提示用户
-            return;
-        }
-        for (const c of category) {
-            const cateObj = $('[cate-id=' + c.id + ']', '#add-bd');
-            if (parseInt($('select', cateObj).val()) !== 0) {
-                const cate = {cid: c.id};
-                cate.value = parseInt($('select', cateObj).val());
-                data.category.push(cate);
-            }
-            // if (c.type === categoryType.key.dropDown) {
-            //     cate.value = parseInt($('select', cateObj).val());
-            // } else if (c.type === categoryType.key.radio) {
-            //     cate.value = parseInt($('input:checked', cateObj).val());
-            // }
-
-        }
-        postData('/list/add', data, function (result) {
-            tenders.push(result);
-            initTenderTree();
-            $('.c-body').html(getTenderTreeHtml());
-            bindTenderUrl();
-            localHideList();
-            $('#add-bd').modal('hide');
-            $('[name=name]', '#add-bd').val('');
-        });
-    });
-    // 编辑标段
-    $('#edit-bd-ok').click(function () {
-        const data = {
-            id: parseInt($(this).attr('tid')),
-            name: cleanSymbols($('[name=name]', '#edit-bd').val()),
-            category: [],
-        };
-        if (!data.name || data.name === '') {
-            // TODO 提示用户
-            return;
-        }
-        for (const c of category) {
-            const cateObj = $('[cate-id=' + c.id + ']', '#edit-bd');
-            if (parseInt($('select', cateObj).val()) !== 0) {
-                const cate = {cid: c.id};
-                cate.value = parseInt($('select', cateObj).val());
-                data.category.push(cate);
-            }
-            // if (c.type === categoryType.key.dropDown) {
-            //     cate.value = parseInt($('select', cateObj).val());
-            // } else if (c.type === categoryType.key.radio) {
-            //     cate.value = parseInt($('input:checked', cateObj).val());
-            // }
-            // data.category.push(cate);
-        }
-        postData('/list/update', data, function (result) {
-            const tender = _.find(tenders, {id: result.id});
-            _.assign(tender, result);
-            initTenderTree();
-            $('.c-body').html(getTenderTreeHtml());
-            bindTenderUrl();
-            localHideList();
-            $('#edit-bd').modal('hide');
-        });
-    });
-    // 删除标段
-    $('#del-bd-ok').click(function () {
-        const tid = parseInt($(this).attr('tid'));
-        if (tid >= 0) {
-            postData('/list/del', [tid], function (result) {
-                function getCategory(arr, id) {
-                    for (const a of arr) {
-                        if (a.cid) {
-                            const ac = getCategory(a.children, id);
-                            if (ac) {
-                                return ac;
-                            }
-                        } else if (a.id === id) {
-                            return arr;
-                        }
-                    }
-                    return null;
-                }
-                for (const rid of result) {
-                    const tr = $('td[tid=' + rid + ']').parent();
-                    const arr = getCategory(tenderTree, rid);
-                    if (arr) {
-                        const a = arr.find(function (x) {
-                            return x.id === rid;
-                        });
-                        if (arr.length > 1 && arr.indexOf(a) === arr.length - 1) {
-                            const span = $('span', tr.prev());
-                            span.text('└');
-                        }
-                        arr.splice(arr.indexOf(a), 1);
-                    }
-                    _.remove(tenders, function (n) {
-                        return n.id === rid;
-                    });
-                    tr.remove();
-                    $('#del-bd').modal('hide');
-                }
-            });
-        } else {
-            $('#del-bd').modal('hide');
-        }
-    });
-});
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml }
+})();

+ 114 - 477
app/public/js/tender_list_progress.js

@@ -7,265 +7,110 @@
  * @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 = [];
-let parentId = 0;
-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 !== null && targetNode.lid !== 1) {
-        const parent = targetNode.getParentNode();
-        if (parent && parent.lid === 1) {
-            return false;
-        }
-    }
-    for (var i=0,l=treeNodes.length; i<l; i++) {
-        if (treeNodes[i].drag === false) {
-            return false;
-        }
-        if (!targetNode && treeNodes[i].dropRoot === false) {
-            return false;
-        }
-        if(treeNodes[i].isParent === true && targetNode.lid !== 1){
-            return false;
-        }
-    }
-    return true;
-}
-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');
+
+const tenderListSpec = (function(){
+    function getProgressHtml(total, pre, cur) {
+        if (total !== 0) {
+            let preP = ZhCalc.mul(ZhCalc.div(pre, total, 2), 100, 0);
+            let curP = ZhCalc.mul(ZhCalc.div(cur, total, 2), 100, 0);
+            let other = Math.max(ZhCalc.sub(ZhCalc.sub(total, pre), cur), 0);
+            let otherP = Math.max(100 - preP - curP, 0);
+            const html = '<div class="progress">' +
+                '<div class="progress-bar bg-success" style="width: ' + preP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期完成:¥' + (pre || 0) + '">' + preP + '%</div>' +
+                '<div class="progress-bar bg-info" style="width: ' + curP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥' + (cur || 0) + '">' + curP + '%</div>' +
+                '<div class="progress-bar bg-gray" style="width: ' + otherP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥' + (other || 0) + '">' + otherP + '%</div>' +
+                '</div>';
+            return html;
+        } else {
+            return '';
         }
     }
-    resetFixNode(1);
-    resetFixNode(2);
-    if (targetNode !== null && targetNode.lid === 1 && treeNodes[0].children && treeNodes[0].children.length !== 0) {
-        moveChildren(treeNodes[0].children, zTree.getNodeByParam('lid', 1));
-    } else if (targetNode !== null && 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 getTenderNodeHtml(node, arr, pid) {
+        const html = [];
+        html.push('<tr pid="' + pid + '">');
+        // 名称
+        html.push('<td width="20%" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
+        } 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('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
+        }
+        html.push('</td>');
+        // 计量进度
+        html.push('<td style="width: 8%">');
+        if (!node.cid && node.cur_flow) {
+            if (node.progress) {
+                html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
+            } else {
+                html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
             }
         }
-    }
-}
-// 查询方法
-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;
+        html.push('</td>');
+        // 当前流程
+        html.push('<td style="width: 13%">');
+        if (!node.cid && node.cur_flow) {
+            if (node.stage_status !== undefined) {
+                const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
+                html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
+                    ? curUser
+                    : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+                );
+                html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
+            } else {
+                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
+                    '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
+                    ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
+                html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
+                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
+                    '</a> ');
+                html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+            }
         }
-    } 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, drag: false},
-        { lid:2, lpId:0, name:"已用类别", open:true, isParent: true, drag: false}
-    );
-    for (const c of category) {
-        const cate = JSON.parse(JSON.stringify(c));
-        cate.lid = levelNodes.length + 1;
-        cate.open = true;
-        cate.dropRoot = false;
-        if (!cate.level) {
-            cate.lpId = 1;
-            levelNodes.push(cate);
+        html.push('</td>');
+        // 上一流程审批时间
+        html.push('<td style="width: 8%">');
+        if (!node.cid && node.pre_flow) {
+            if (node.name === '123456677') console.log(node.pre_flow);
+            html.push(node.pre_flow.name + ' ' + moment(node.pre_flow.time).format('YYYY-MM-DD'));
+        }
+        html.push('</td>');
+        // 签约合同价
+        html.push('<td width="8%" class="text-right">');
+        html.push(node.contract_price ? node.contract_price : '');
+        html.push('</td>');
+        // 总价
+        html.push('<td width="8%" class="text-right">');
+        html.push(node.sum_tp ? node.sum_tp : '');
+        html.push('</td>');
+        // 截止本期累计完成/本期完成/未完成
+        html.push('<td>');
+        if (node.lastStage || node.stage_count > 0) {
+            html.push(getProgressHtml(node.sum_tp, node.pre_gather_tp, node.gather_tp));
         } 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 form-control-sm">');
-        for (const v of cate.value) {
-            html.push('<option value="' + v.id + '">', v.value, '</option>');
+            html.push('');
         }
-        html.push('<option value="0">不选</option>');
-        html.push('</select>');
-        html.push('</div>');
+        html.push('</td>');
+        html.push('</tr>');
         return html.join('');
     }
-    function getRadioCategoryHtml (cate) {
+    function getTenderTreeHeaderHtml() {
         const html = [];
-        html.push('<div class="form-group" cate-id="' + cate.id + '">');
-        html.push('<lable>', cate.name, '</lable>');
-        html.push('<div>');
-        for (const iV in cate.value) {
-            const v = cate.value[iV];
-            html.push('<div class="form-check-inline">');
-            html.push('<input class="form-check-input" type="radio"', 'name="' + cate.name + '" ', 'value="' , v.id, (iV == 0 ? '" checked="' : ''),  '">');
-            html.push('<label class="form-check-label">', v.value, '</label>');
-            html.push('</div>');
-        }
-        html.push('</div>');
-        html.push('</div>');
+        html.push('<table class="table table-hover table-bordered">');
+        html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
+        html.push('<th style="width: 25%" class="text-center">', '标段名称', '</th>');
+        html.push('<th class="text-center" style="width: 8%">', '计量进度', '</th>');
+        html.push('<th class="text-center" style="width: 8%">', '当前流程', '</th>');
+        html.push('<th class="text-center" style="width: 8%">', '上一流程审批时间', '</th>');
+        html.push('<th class="text-center" style="width: 8%">', '签约合同价', '</th>');
+        html.push('<th style="width: 8%" class="text-center">', '总价 <i class="fa fa-question-circle text-primary"  data-placement="bottom" data-toggle="tooltip" data-original-title="0号台账+截止本期数量变更"></i>', '</th>');
+        html.push('<th style="width: 35%" class="text-center">', '截止上期完成/本期完成/未完成', '</th>');
+        html.push('</tr>', '</thead>');
         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('');
-}
-function calculateParent(node) {
-    if (node.children && node.cid) {
-        node.end_qc_tp = 0;
-        node.pre_gather_tp = 0;
-        node.gather_tp = 0;
-        node.sum_tp = 0;
-        node.lastStage = 0;
-        node.contract_price = 0;
-        node.stage_count = 0;
-        for (const c of node.children) {
-            calculateParent(c);
-            node.end_qc_tp = ZhCalc.add(node.end_qc_tp, c.end_qc_tp);
-            node.pre_gather_tp = ZhCalc.add(node.pre_gather_tp, c.pre_gather_tp);
-            node.gather_tp = ZhCalc.add(node.gather_tp, c.gather_tp);
-            node.sum_tp = ZhCalc.add(node.sum_tp, c.sum_tp);
-            node.lastStage = c.cid
-                ? Math.max(node.lastStage, c.lastStage)
-                : (c.lastStage ? Math.max(node.lastStage, c.lastStage.order) : node.lastStage);
-            node.stage_count = c.cid ? Math.max(node.stage_count, c.stage_count) : (c.stage_count ? Math.max(node.stage_count, c.stage_count): node.stage_count);
-            node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
-        }
-    }
-}
-// 初始化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, i = null) {
-        const array = parent ?  parent.children : tenderTree;
-        let cate = findCategoryNode(category.id, value, array);
-        if (!cate) {
-            const cateValue = findNode('id', value, category.value);
-            if (!cateValue) return null;
-            cate = {
-                cid: category.id,
-                vid: value,
-                name: cateValue.value,
-                children: [],
-                level: i ? i : category.level,
-                sort_id: ++parentId,
-                sort: cateValue.sort,
-            };
-            array.push(cate);
-        }
-        return cate;
-    }
-    function loadTenderCategory (tender) {
-        let tenderCategory = null;
-        for (const [index, lc] of levelCategory.entries()) {
-            const tenderCate = findNode('cid', lc.id, tender.category);
-            if (tenderCate) {
-                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
-            } else {
-                if (index === 0 && tender.category) {
-                    for (const [i,c] of tender.category.entries()) {
-                        const cate = findNode('id', c.cid, category);
-                        if (cate) {
-                            tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
-                        } else {
-                            console.log(tender.name, c.cid, c.value);
-                        }
-                    }
-                }
-                return tenderCategory;
-            }
-        }
-        return tenderCategory;
-    }
     function calculateTender(tender) {
         if (tender.stage_tp) {
             tender.end_qc_tp = ZhCalc.sum([tender.stage_tp.pre_qc_tp, tender.stage_tp.qc_tp, tender.stage_tp.qc_pc_tp]);
@@ -281,237 +126,29 @@ function initTenderTree () {
             tender.sum_tp = tender.total_price;
         }
     }
-    tenderTree.splice(0, tenderTree.length);
-    for (const t of tenders) {
-        calculateTender(t);
-        t.valid = true;
-        delete t.level;
-        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);
+    function calculateParent(node) {
+        if (node.children && node.cid) {
+            node.end_qc_tp = 0;
+            node.pre_gather_tp = 0;
+            node.gather_tp = 0;
+            node.sum_tp = 0;
+            node.lastStage = 0;
+            node.contract_price = 0;
+            node.stage_count = 0;
+            for (const c of node.children) {
+                calculateParent(c);
+                node.end_qc_tp = ZhCalc.add(node.end_qc_tp, c.end_qc_tp);
+                node.pre_gather_tp = ZhCalc.add(node.pre_gather_tp, c.pre_gather_tp);
+                node.gather_tp = ZhCalc.add(node.gather_tp, c.gather_tp);
+                node.sum_tp = ZhCalc.add(node.sum_tp, c.sum_tp);
+                node.lastStage = c.cid
+                    ? Math.max(node.lastStage, c.lastStage)
+                    : (c.lastStage ? Math.max(node.lastStage, c.lastStage.order) : node.lastStage);
+                node.stage_count = c.cid ? Math.max(node.stage_count, c.stage_count) : (c.stage_count ? Math.max(node.stage_count, c.stage_count): node.stage_count);
+                node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
             }
-        } else {
-            tenderTree.push(t);
-        }
-    }
-    sortTenderTree();
-    for (const t of tenderTree) {
-        calculateParent(t);
-    }
-}
-function getProgressHtml(total, pre, cur) {
-    if (total !== 0) {
-        let preP = ZhCalc.mul(ZhCalc.div(pre, total, 2), 100, 0);
-        let curP = ZhCalc.mul(ZhCalc.div(cur, total, 2), 100, 0);
-        let other = Math.max(ZhCalc.sub(ZhCalc.sub(total, pre), cur), 0);
-        let otherP = Math.max(100 - preP - curP, 0);
-        const html = '<div class="progress">' +
-            '<div class="progress-bar bg-success" style="width: ' + preP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期完成:¥' + (pre || 0) + '">' + preP + '%</div>' +
-            '<div class="progress-bar bg-info" style="width: ' + curP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥' + (cur || 0) + '">' + curP + '%</div>' +
-            '<div class="progress-bar bg-gray" style="width: ' + otherP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥' + (other || 0) + '">' + otherP + '%</div>' +
-            '</div>';
-        return html;
-    } else {
-        return '';
-    }
-}
-function recursiveGetTenderNodeHtml (node, arr, pid) {
-    const html = [];
-    html.push('<tr pid="' + pid + '">');
-    // 名称
-    html.push('<td width="20%" class="in-' + node.level + '">');
-    if (node.cid) {
-        html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
-    } 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('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
-    }
-    html.push('</td>');
-    // 计量进度
-    html.push('<td style="width: 8%">');
-    if (!node.cid && node.cur_flow) {
-        if (node.progress) {
-            html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
-        } else {
-            html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
-        }
-    }
-    html.push('</td>');
-    // 当前流程
-    html.push('<td style="width: 13%">');
-    if (!node.cid && node.cur_flow) {
-        if (node.stage_status !== undefined) {
-            const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
-            html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
-                ? curUser
-                : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
-            );
-            html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
-        } else {
-            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-                '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-                ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-            html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
-                '</a> ');
-            html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
-        }
-    }
-    html.push('</td>');
-    // 上一流程审批时间
-    html.push('<td style="width: 8%">');
-    if (!node.cid && node.pre_flow) {
-        if (node.name === '123456677') console.log(node.pre_flow);
-        html.push(node.pre_flow.name + ' ' + moment(node.pre_flow.time).format('YYYY-MM-DD'));
-    }
-    html.push('</td>');
-    // 签约合同价
-    html.push('<td width="8%" class="text-right">');
-    html.push(node.contract_price ? node.contract_price : '');
-    html.push('</td>');
-    // 总价
-    html.push('<td width="8%" class="text-right">');
-    html.push(node.sum_tp ? node.sum_tp : '');
-    html.push('</td>');
-    // 截止本期累计完成/本期完成/未完成
-    html.push('<td>');
-    if (node.lastStage || node.stage_count > 0) {
-        html.push(getProgressHtml(node.sum_tp, node.pre_gather_tp, node.gather_tp));
-    } else {
-        html.push('');
-    }
-    html.push('</td>');
-    html.push('</tr>');
-    if (node.children) {
-        for (const c of node.children) {
-            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
-        }
-    }
-    return html.join('');
-}
-// 根据TenderTree数据获取Html代码
-function getTenderTreeHtml () {
-    if (tenderTree.length > 0) {
-        const html = [];
-        html.push('<table class="table table-hover table-bordered">');
-        html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
-        html.push('<th style="width: 25%" class="text-center">', '标段名称', '</th>');
-        html.push('<th class="text-center" style="width: 8%">', '计量进度', '</th>');
-        html.push('<th class="text-center" style="width: 8%">', '当前流程', '</th>');
-        html.push('<th class="text-center" style="width: 8%">', '上一流程审批时间', '</th>');
-        html.push('<th class="text-center" style="width: 8%">', '签约合同价', '</th>');
-        html.push('<th style="width: 8%" class="text-center">', '总价 <i class="fa fa-question-circle text-primary"  data-placement="bottom" data-toggle="tooltip" data-original-title="0号台账+截止本期数量变更"></i>', '</th>');
-        html.push('<th style="width: 35%" class="text-center">', '截止上期完成/本期完成/未完成', '</th>');
-        html.push('</tr>', '</thead>');
-        parentId = 0;
-        for (const t of tenderTree) {
-            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
         }
-        html.push('</table>');
-        return html.join('');
-    } else {
-        return EmptyTenderHtml.join('');
     }
-}
-function bindTenderUrl() {
-    $('.c-body').on('click', 'a', function () {
-        const tenderId = parseInt($(this).attr('id'));
-        const tender = _.find(tenders, function (t) {
-            return t.id === tenderId;
-        });
-        if (!tender) return;
-        if (!tender.measure_type && tender.user_id !== userID) return;
-        if (tender.measure_type) {
-            // window.location.href = '/tender/' + tenderId;
-            window.open('/tender/' + tenderId, '_blank');
-        } else {
-            for (const a of $('a', '#jlms')) {
-                a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
-            }
-            $('#jlms').modal('show');
-        }
-    });
-}
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml, calculateTender, calculateParent }
+})();
 
-$(document).ready(() => {
-    autoFlashHeight();
-    sortCategory();
-    // 初始化分类数据
-    initCategoryLevelNode();
-    $('.modal-body', '#add-bd').append(getCategoryHtml());
-    // 初始化标段树结构
-    initTenderTree();
-    $('.c-body').html(getTenderTreeHtml());
-    bindTenderUrl();
-    localHideList();
-    tenderTreeShowLevel.initShowLevel();
-    // 分类
-    $('#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());
-            localHideList();
-            $('#cate-set').modal('hide');
-            tenderTreeShowLevel.refreshMenuVisible();
-        });
-    });
-    // 新增标段
-    $('#add-bd-ok').click(function () {
-        const data = {
-            name: cleanSymbols($('[name=name]', '#add-bd').val()),
-            valuation: $('[name=valuation]:checked').val(),
-            category: [],
-        };
-        if (!data.name || data.name === '') {
-            // TODO 提示用户
-            return;
-        }
-        for (const c of category) {
-            if (parseInt($('select', '[cate-id=' + c.id + ']').val()) !== 0) {
-                const cate = {cid: c.id};
-                // if (c.type === categoryType.key.dropDown) {
-                cate.value = parseInt($('select', '[cate-id=' + c.id + ']').val());
-                // } else if (c.type === categoryType.key.radio) {
-                //     cate.value = parseInt($('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());
-            bindTenderUrl();
-            localHideList();
-            $('#add-bd').modal('hide');
-            $('[name=name]', '#add-bd').val('');
-        });
-    });
-});

+ 1 - 0
app/router.js

@@ -108,6 +108,7 @@ module.exports = app => {
     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.post('/setting/category/self-level', sessionAuth, 'settingController.selfCategoryLevel');
     // 操作日志
     app.get('/setting/logs', sessionAuth, 'settingController.logs');
     app.get('/setting/logs/type/:type', sessionAuth, 'settingController.logs');

+ 5 - 0
app/service/project_account.js

@@ -913,6 +913,11 @@ module.exports = app => {
             const result = await this.db.queryOne(sql, [id]);
             return this._.assign(result, defaultData);
         }
+
+        async getSelfCategoryLevel(id) {
+            const result = await this.getDataById(id);
+            return result ? result.self_category_level : '';
+        }
     }
 
     return ProjectAccount;

+ 1 - 0
app/view/tender/index.ejs

@@ -11,6 +11,7 @@
     const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
     const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const selfCategoryLevel = '<%- (selfCategoryLevel || '') %>';
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const uid = '<%- uid %>';

+ 1 - 0
app/view/tender/info.ejs

@@ -11,6 +11,7 @@
     const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
     const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const selfCategoryLevel = '<%- (selfCategoryLevel || '') %>';
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const uid = '<%- uid %>';

+ 1 - 0
app/view/tender/manage.ejs

@@ -11,6 +11,7 @@
     const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
     const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const selfCategoryLevel = '<%- (selfCategoryLevel || '') %>';
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
     const uid = '<%- uid %>';
     const pid = '<%- pid %>';

+ 19 - 0
app/view/tender/modal.ejs

@@ -53,6 +53,25 @@
         </div>
     </div>
 </div>
+<div class="modal fade" id="cate-set-self" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">分类设置</h5>
+            </div>
+            <div class="modal-body">
+                <div class="modal-height-300">
+                    <ul id="treeLevel-self" class="ztree"></ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary btn-sm" id="set-cate-self-reset">重置</button>
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary btn-sm" id="set-cate-self-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
 <!--弹出计量模式选择-->
 <div class="modal fade" id="jlms" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">

+ 1 - 0
app/view/tender/progress.ejs

@@ -11,6 +11,7 @@
     const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
     const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const selfCategoryLevel = '<%- (selfCategoryLevel || '') %>';
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
     const uid = '<%- uid %>';
     const pid = '<%- pid %>';

+ 6 - 2
app/view/tender/sub_menu.ejs

@@ -2,7 +2,11 @@
     <div class="title-main  d-flex justify-content-between">
         <div>
             <div class="d-inline-block mr-2">
+                <% if (ctx.session.sessionUser.is_admin) { %>
                 <button href="#cate-set" class="btn btn-sm btn-light text-primary" data-toggle="modal" data-target="#cate-set"><i class="fa fa-sitemap fa-rotate-270"></i> 分类</button>
+                <% } else { %>
+                <button href="#cate-set-self" class="btn btn-sm btn-light text-primary" data-toggle="modal" data-target="#cate-set-self"><i class="fa fa-sitemap fa-rotate-270"></i> 自定义分类</button>
+                <% } %>
             </div>
             <div class="d-inline-block" id="show-level"></div>
             <div class="d-inline-block">
@@ -23,7 +27,7 @@
                     <% } %>
                     <% if (ctx.app.config.is_debug) { %>
                     <label class="btn btn-sm btn-light <% if (ctx.url === '/listOrg') { %>active<% } %>" onclick="window.location.href='/listOrg'">
-                        <input type="radio" name="options" id="option1" autocomplete="off"> 标段列表
+                        <input type="radio" name="options" id="option1" autocomplete="off"> 标段列表(旧)
                     </label>
                     <label class="btn btn-sm btn-light <% if (ctx.url === '/list/infoOrg') { %>active<% } %>" onclick="window.location.href='/list/infoOrg'">
                         <input type="radio" name="options" id="option1" autocomplete="off"> 金额概况(旧)
@@ -33,7 +37,7 @@
                     </label>
                     <% if (userPermission !== null && userPermission.tender !== undefined && userPermission.tender.indexOf('1') !== -1) { %>
                     <label class="btn btn-sm btn-light  <% if (ctx.url === '/list/manageOrg') { %>active<% } %>" onclick="window.location.href='/list/manageOrg'">
-                        <input type="radio" name="options" id="option2" autocomplete="off"> 管理标段
+                        <input type="radio" name="options" id="option2" autocomplete="off"> 管理标段(旧)
                     </label>
                     <% } %>
                     <% } %>

+ 4 - 0
config/web.js

@@ -63,6 +63,7 @@ const JsFiles = {
                     '/public/js/shares/show_level.js',
                     '/public/js/tender_showhide.js',
                     '/public/js/tender_list.js',
+                    '/public/js/tender_list_base.js',
                 ],
                 mergeFile: 'tender_list',
             },
@@ -75,6 +76,7 @@ const JsFiles = {
                     '/public/js/shares/show_level.js',
                     '/public/js/tender_showhide.js',
                     '/public/js/tender_list_info.js',
+                    '/public/js/tender_list_base.js',
                 ],
                 mergeFile: 'tender_list_info',
             },
@@ -87,6 +89,7 @@ const JsFiles = {
                     '/public/js/shares/show_level.js',
                     '/public/js/tender_showhide.js',
                     '/public/js/tender_list_progress.js',
+                    '/public/js/tender_list_base.js',
                 ],
                 mergeFile: 'tender_list_progress',
             },
@@ -99,6 +102,7 @@ const JsFiles = {
                     '/public/js/shares/show_level.js',
                     '/public/js/tender_showhide.js',
                     '/public/js/tender_list_manage.js',
+                    '/public/js/tender_list_base.js',
                 ],
                 mergeFile: 'tender_list_manage',
             },

File diff suppressed because it is too large
+ 4 - 1
sql/update.sql