Browse Source

billsTemplate

MaiXinRong 7 years ago
parent
commit
e115b83daf

+ 5 - 2
modules/common/base/base_controller.js

@@ -25,9 +25,12 @@ class BaseController {
      * @return {void}
      */
     constructor() {
-        if (new.target === BaseController) {
+        /**
+         * 使BaseController可以实例化,可作为中间件使用
+         */
+        /*if (new.target === BaseController) {
             throw new Error('BaseController不能实例化,只能继承使用。');
-        }
+        }*/
     }
 
     /**

+ 29 - 38
modules/templates/controllers/bills_template_controller.js

@@ -2,52 +2,43 @@
  * 清单模板控制器
  * Created by Mai on 2017/4/17.
  */
-/*
-var BillsTemplateData = require('../models/bills_template_model');
 
-var callback = function(req, res, err, message, data){
+import BillsTemplateModel from "../../templates/models/bills_template_model";
+
+let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
 };
-/!*
+
 class BillsTemplateController {
-    /!**
+    /**
      * 清单模板编辑页面
      * @param req
      * @param res
-     *!/
+     */
     async index(req, res) {
         let id = req.query.id;
-        let
-    }
-};*!/
+        let billsTemplateModel = new BillsTemplateModel();
+        let billsTemplateData = await billsTemplateModel.getTemplateData(id);
+
+        let renderData = {
+            valuationId: id,
+            billsTemplateData: billsTemplateData,
+            layout: 'users/views/layout/layout'
+        };
+        res.render('maintain/templates/html/bills', renderData);
+    };
 
-module.exports = {
-    getBillsTemplate: function(req, res){
-        var data = JSON.parse(req.body.data);
-        BillsTemplateData.getTemplate(data.tempType, function(err, message, templates){
-            if (templates) {
-                callback(req, res, err, message, templates);
-            } else {
-                callback(req, res, err, message, null);
-            }
-        });
-    },
-    updateBillsTemplate: function (req, res) {
-        var data = JSON.parse(req.body.data);
-        BillsTemplateData.updateTemplate(data.user_id, data.tempType, data.updateData, function (err, message, data) {
-            if (err === 0) {
-                callback(req, res, err, message, data);
-            } else {
-                callback(req, res, err, message, null);
-            }
-        });
-    },
-    getNewBillsTemplateID: function (req, res) {
-        var data = JSON.parse(req.body.data);
-        BillsTemplateData.getNewBillsTemplateID(data.count, function (err, message, data) {
-            callback(req, res, err, message, data);
-        });
-    }
-}
+    async updateBillsTemplate (req, res) {
+        let data = JSON.parse(req.body.data);
+        let billsTemplateModel = new BillsTemplateModel();
+        let result = await billsTemplateModel.updateTemplate(data.user_id, data.valuationId, data.updateData);
+
+        if (result) {
+            callback(req, res, 0, '', data);
+        } else {
+            callback(req, res, 1, '更新数据错误', null);
+        }
+    };
+};
 
-export default BillsTemplateController;*/
+export default BillsTemplateController;

+ 35 - 60
modules/templates/models/bills_template_model.js

@@ -17,6 +17,11 @@ class BillsTemplateModel extends BaseModel {
         parent.init();
     }
 
+    /**
+     * 获取计价类别对应的清单模板
+     * @param valuationId
+     * @returns {*}
+     */
     async getTemplateData (valuationId) {
         // 筛选字段
         let field = {_id: 1, valuationId: 1, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1};
@@ -24,71 +29,41 @@ class BillsTemplateModel extends BaseModel {
 
         return data === null ? [] : data;
     }
-};
 
-export default BillsTemplateModel;
-/*
-var BillsTemplateDAO = function(){};
+    /**
+     * 新建项目时,获取计价类别对应的清单模板
+     * @param valuationId
+     * @returns {*}
+     */
+    async getTemplateDataForNewProj (valuationId) {
+        // 筛选字段
+        let field = {ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1};
+        let data = await this.findDataByCondition({valuationId: valuationId}, field, false);
 
-BillsTemplateDAO.prototype.getTemplate = function (type, callback) {
-    if (callback) {
-        BillsTemplates.find({'$or': [{tempType: type, deleteInfo: null}, {tempType: type, 'deleteInfo.deleted': {$in: [null, false]}}]}, '-_id').exec()
-            .then(function (result, err) {
-                if (err) {
-                    callback(1, '找不到模板', null);
-                } else {
-                    callback(0, '', result);
-                }
-            });
-        return null;
-    } else {
-        return BillsTemplates.find({'$or': [{tempType: type, deleteInfo: null}, {tempType: type, 'deleteInfo.deleted': {$in: [null, false]}}]}, '-_id').exec();
+        return data === null ? [] : data;
     }
-};
-BillsTemplateDAO.prototype.updateTemplate = function (userID, tempType, datas, callback) {
-    var data, project, updateLength = 0, hasError = false, deleteInfo = null;
-    var updateAll = function (err) {
-        if (!err){
-            updateLength += 1;
-            if (updateLength === datas.length) {
-                callback(0, '', datas);
-            }
-        } else {
-            hasError = true;
-            callback(1, '升级数据出错', null);
-        }
-    };
-    if (datas){
-        for (var i = 0; i < datas.length && !hasError; i++){
-            data = datas[i];
-            if (data.type === 'update') {
-                BillsTemplates.update({tempType: tempType, ID: data.data.ID}, data.data, updateAll)
-            } else if (data.type === 'new') {
-                data.data['tempType'] = tempType;
-                newProject = new BillsTemplates(data.data);
-                newProject.save(updateAll);
-            } else if (data.type === 'delete') {
-                deleteInfo = {};
-                deleteInfo['deleted'] = true;
-                deleteInfo['deleteDateTime'] = new Date();
-                deleteInfo['deleteBy'] = userID;
-                BillsTemplates.update({ID: data.data.ID}, {deleteInfo: deleteInfo}, updateAll);
-            } else {
-                hasError = true;
-                callback(1, '升级数据出错', null)
+
+    async updateTemplate (valuationId, datas) {
+        try {
+            for (let data of datas) {
+                data.valuationId = valuationId;
+                let condition = {valuationId: valuationId, ID: data.data.ID}, result;
+                if (data.updateType === 'update') {
+                    result = await this.db.update(condition, data.data);
+                } else if (data.updateType === 'new') {
+                    result = await this.db.create(data.data);
+                } else if (data.updateType === 'delete') {
+                    result = await this.db.delete(condition);
+                }
+                if (result === undefined || result.ok ===undefined || !result.ok) {
+                    throw '更新数据错误';
+                }
             }
+            return true;
+        } catch (error) {
+            console.log(error);
         }
     }
 };
-BillsTemplateDAO.prototype.getNewBillsTemplateID = function (count, callback) {
-    counter.counterDAO.getIDAfterCount(counter.moduleName.template_bills, count, function (err, result) {
-        var highID = result.value.sequence_value;
-        if (!err) {
-            callback(0, '', {lowID: highID - count + 1, highID: highID});
-        } else {
-            callback(1, '获取主键失败', null);
-        }
-    });
-};
 
-module.exports = new BillsTemplateDAO();*/
+export default BillsTemplateModel;

+ 11 - 33
modules/templates/routes/bills_template_router.js

@@ -2,41 +2,19 @@
  * Created by Mai on 2017/4/17.
  */
 
-var express = require('express');
-/*
-var billsTemplateController = require('./../controllers/bills_template_controller');*/
+import Express from "express";
+import baseController from './../../common/base/base_controller.js';
+import billsTemplateController from './../controllers/bills_template_controller';
+
+const router = Express.Router();
+const BaseController = new baseController();
+const BillsTemplateController = new billsTemplateController();
 
 module.exports = function (app) {
-    app.get('/template/bills/:id', function (req, res) {
-        let checkAdmin = function (userAccount) {
-            return true;
-        }
-        if (checkAdmin(req.session.userAccount)) {
-            res.render('maintain/templates/html/bills.html',
-                {userAccount: req.session.userAccount,
-                    userID: req.session.userID});
-        } else {
-            res.redirect('/pm');
-        }
-    });
-
-    app.use('/template/bills/api', function (req, res, next) {
-        let checkAdmin = function (userAccount) {
-            return true;
-        }
-        if (checkAdmin(req.session.sessionUser)) {
-            next();
-        } else {
-            res.json({error: 1, message: '对不起,您无权限操作清单模板。', data: null});
-        }
-    });
-
-/*    var billsTemplateRouter = express.Router();
-
-    billsTemplateRouter.post('/getBillsTemplate', billsTemplateController.getBillsTemplate);
-    billsTemplateRouter.post('/updateBillsTemplate', billsTemplateController.updateBillsTemplate);
-    billsTemplateRouter.post('/getNewBillsTemplateID', billsTemplateController.getNewBillsTemplateID);
-    app.use('/template/bills/api', billsTemplateRouter);*/
+    app.get('/template/bills/:id', BaseController.auth, BaseController.init, BillsTemplateController.index);
+
+    router.post('/updateBillsTemplate', BaseController.auth, BaseController.init, BillsTemplateController.updateBillsTemplate);
+    app.use('/template/bills/api', router);
 }
 
 

+ 33 - 1
modules/users/controllers/compilation_controller.js

@@ -332,9 +332,11 @@ class CompilationController extends BaseController {
      * @return {void}
      */
     async template(request, response) {
+        let billList = {};
         let valuationList = {};
         let valuationData = {};
         let compilationList = [];
+        let billsTemplateData = [];
 
         let selectedCompilation = request.session.selectedCompilation;
         let valuationId = request.params.id;
@@ -345,11 +347,21 @@ class CompilationController extends BaseController {
             // 获取对应的计价规则数据
             [valuationData, valuationList] = await compilationModel.getValuation(selectedCompilation._id, valuationId, section);
             compilationList = await compilationModel.getCompilationList();
+
+            // 获取标准清单
+            let stdBillLibListsModel = new STDBillLibListsModel();
+            billList = await stdBillLibListsModel.getBillList(selectedCompilation._id);
+
+            // 获取清单模板数据
+            let billsTemplateModel = new BillsTemplateModel();
+            billsTemplateData = await billsTemplateModel.getTemplateData(valuationId);
         } catch (error) {
             console.log(error);
         }
 
         let renderData = {
+            billList: JSON.stringify(billList),
+            billsTemplateData: JSON.stringify(billsTemplateData),
             valuationData: valuationData,
             valuationList: valuationList,
             selectedCompilation: selectedCompilation,
@@ -361,6 +373,26 @@ class CompilationController extends BaseController {
         response.render('users/views/compilation/template', renderData);
     }
 
+    /**
+     * 清单模板,更新数据操作
+     * @param request
+     * @param response
+     */
+    async updateBillsTemplate(request, response) {
+        let valuationId = request.params.id;
+        let section = request.params.section;
+        let data = JSON.parse(request.body.data);
+
+        let billsTemplateModel = new BillsTemplateModel();
+        let result = await billsTemplateModel.updateTemplate(valuationId, data);
+
+        if (result) {
+            callback(request, response, 0, '', data);
+        } else {
+            callback(request, response, 1, '更新数据错误', null);
+        }
+    }
+
 }
 
-export default CompilationController;2
+export default CompilationController;

+ 1 - 0
modules/users/routes/compilation_route.js

@@ -23,6 +23,7 @@ module.exports = function (app) {
     router.post('/add-valuation', compilationController.auth, compilationController.init, compilationController.addValuation);
     router.post('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     router.post('/valuation/:section/enable', compilationController.auth, compilationController.init, compilationController.enableSwitch);
+    router.post('/template/:section/:id/update', compilationController.auth, compilationController.init, compilationController.updateBillsTemplate)
 
     app.use("/compilation", router);
 };

+ 5 - 49
web/maintain/templates/html/bills.html

@@ -1,41 +1,3 @@
-<!DOCTYPE html>
-<html>
-<head lang="en">
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-    <meta http-equiv="x-ua-compatible" content="ie=edge">
-    <title>模板清单-Smartcost</title>
-    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
-    <link rel="stylesheet" href="/web/maintain/templates/css/main.css">
-    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
-    <!--SpreadJs-->
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
-    <script>
-        // 这里的变量供页面调用
-        var userAccount = '<%- userAccount %>';
-        var userID = '<%- userID %>';
-    </script>
-</head>
-<body>
-    <div class="header">
-        <nav class="navbar navbar-toggleable-lg navbar-light bg-faded p-0 justify-content-between">
-            <span class="header-logo px-2">Smartcost</span>
-            <div class="float-lg-right navbar-text pt-0">
-                <div class="dropdown d-inline-block">
-                    <button class="btn btn-link btn-sm dropdown-toggle" type="button" data-toggle="dropdown"><%- userAccount %></button>
-                    <div class="dropdown-menu dropdown-menu-right">
-                        <a class="dropdown-item" href="/user/info" target="_blank">账号资料</a>
-                        <a class="dropdown-item" href="/user/buy" target="_blank">产品购买</a>
-                        <a class="dropdown-item" href="/user/set" target="_blank">偏好设置</a>
-                    </div>
-                </div>
-                    <span class="btn btn-link btn-sm new-msg">
-                        <i class="fa fa-envelope-o" aria-hidden="true"></i>&nbsp;2
-                    </span>
-                    <a class="btn btn-link btn-sm" href="/logout">注销</a>
-            </div>
-        </nav>
-    </div>
 <div class="main">
     <div class="content">
         <div class="toolsbar px-1 d-flex justify-content-between">
@@ -82,15 +44,10 @@
         </div>
     </div>
 </div>
-</body>
-<!-- JS. -->
-<script src="/lib/jquery/jquery.min.js"></script>
-<script src="/lib/tether/tether.min.js"></script>
-<script src="/lib/bootstrap/bootstrap.min.js"></script>
-<script src="/web/maintain/templates/js/global.js"></script>
-<!-- SpreadJs -->
-<script type="text/javascript" src="/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
-<script>GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";</script>
+<script>
+    let valuationId = '<%- valuationId%>';
+    let billsTemplateData = '<%- billsTemplateData %>'
+</script>
 <!-- Models -->
 <script type="text/javascript" src="/public/web/id_tree.js"></script>
 <!-- Controller -->
@@ -102,5 +59,4 @@
 <script type="text/javascript" src="/public/web/common_ajax.js"></script>
 <script>
     autoFlashHeight();
-</script>
-</html>
+</script>

+ 252 - 0
web/users/js/template.js

@@ -0,0 +1,252 @@
+/**
+ * Created by Mai on 2017/8/22.
+ */
+
+let TEMPLATE_BILLS_SETTING = {
+    "emptyRows":1,
+    "headRows":1,
+    "headRowHeight":[35],
+    "treeCol": 0,
+    "cols":[{
+        "width":200,
+        "readOnly":null,
+        "head":{
+            "titleNames":["编号"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"code",
+            "vAlign":0,
+            "hAlign":3,
+            "font":"Arail"
+        }
+    }, {
+        "width":300,
+        "readOnly":null,
+        "head":{
+            "titleNames":["名称"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"name",
+            "vAlign":0,
+            "hAlign":3,
+            "font":"Arail"
+        }
+    }, {
+        "width":50,
+        "readOnly":null,
+        "head":{
+            "titleNames":["单位"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"unit",
+            "vAlign":0,
+            "hAlign":1,
+            "font":"Arail"
+        }
+    }, {
+        "width":50,
+        "readOnly":true,
+        "head":{
+            "titleNames":["ID"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"ID",
+            "vAlign":0,
+            "hAlign":1,
+            "font":"Arail"
+        }
+    }, {
+        "width":50,
+        "readOnly":true,
+        "head":{
+            "titleNames":["ParentID"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"ParentID",
+            "vAlign":0,
+            "hAlign":1,
+            "font":"Arail"
+        }
+    }, {
+        "width":50,
+        "readOnly":true,
+        "head":{
+            "titleNames":["NextSiblingID"],
+            "spanCols":[1],
+            "spanRows":[1],
+            "vAlign":[1],
+            "hAlign":[1],
+            "font":["Arial"]
+        },
+        "data":{
+            "field":"NextSiblingID",
+            "vAlign":0,
+            "hAlign":1,
+            "font":"Arail"
+        }
+    }]
+};
+
+$(document).ready(function () {
+    let RefreshBaseActn = function (tree) {
+        let showButton = function (show, btn) {
+            if (show) {
+                btn.show();
+            } else {
+                btn.hide();
+            }
+        };
+        showButton(tree.selected && tree.selected.canUpLevel(), $('#upLevel'));
+        showButton(tree.selected && tree.selected.canDownLevel(), $('#downLevel'));
+        showButton(tree.selected && tree.selected.canUpMove(), $('#upMove'));
+        showButton(tree.selected && tree.selected.canDownMove(), $('#downMove'));
+        showButton(tree.selected ? true : false, $('#delete'));
+    }
+    let RefreshBillsData = function (datas) {
+        datas.forEach(function (data) {
+            let node = tree.findNode(data.data.ID);
+            if (node) {
+                $.extend(true, node.data, data.data);
+            }
+        });
+    };
+
+    let tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
+    let billsSpread = TREE_SHEET_HELPER.createNewSpread($('#billsSpread')[0]);
+    let controller = TREE_SHEET_CONTROLLER.createNew(tree, billsSpread.getActiveSheet(), TEMPLATE_BILLS_SETTING);
+
+    controller.bind('refreshBaseActn', RefreshBaseActn);
+
+    billsSpread.bind(GC.Spread.Sheets.Events.EditEnded, function (sender, info) {
+        var node = controller.tree.items[info.row];
+        var fieldName = controller.setting.cols[info.col].data.field;
+        var data = {type: 'update', data: {ID: node.getID()}};
+        data.data[fieldName] = info.editingText;
+        var updateData = [data];
+        CommonAjax.post(updateUrl, updateData, function (data) {
+            node.data[fieldName] = info.editingText;
+            controller.refreshTreeNode([node], false);
+        }, function () {
+            controller.refreshTreeNode([node], false);
+        });
+    });
+    billsSpread.bind(GC.Spread.Sheets.Events.ClipboardPasted, function (e, info) {
+        console.log("ClipboardPasted");
+        var node, iRow, iCol, curRow, curCol, datas = [], data, fieldName, updateData;
+        for (iRow = 0; iRow < info.cellRange.rowCount; iRow ++) {
+            curRow = info.cellRange.row + iRow;
+            node = controller.tree.items[curRow];
+            if (node) {
+                data = {type: 'update', data: {ID: node.getID()}};
+                for (iCol = 0; iCol < info.cellRange.colCount; iCol++) {
+                    curCol = info.cellRange.col + iCol;
+                    fieldName = controller.setting.cols[curCol].data.field;
+                    data.data[fieldName] = info.sheet.getText(curRow, curCol);
+                }
+                datas.push(data);
+            }
+        };
+        CommonAjax.post(updateUrl, datas, function (data) {
+            RefreshBillsData(data);
+            controller.showTreeData();
+        }, function () {
+            controller.showTreeData();
+        });
+    });
+
+    tree.loadDatas(JSON.parse(billsTemplateData));
+    controller.showTreeData();
+    RefreshBaseActn(tree);
+
+    $('#insert').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = controller.tree.getInsertData(selected.getParentID(), selected.getNextSiblingID());
+        } else {
+            updateData = controller.tree.getInsertData();
+        }
+        if (updateData.updateData.length > 0) {
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.insert();
+                controller.showTreeData();
+            });
+        } else {
+            alert('新增节点失败, 请重试.');
+        }
+    });
+    $('#delete').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = controller.tree.getDeleteData(selected);
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.delete();
+                controller.showTreeData();
+            });
+        }
+    });
+    $('#upLevel').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = selected.getUpLevelData();
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.upLevel();
+                controller.showTreeData();
+            });
+        }
+    });
+    $('#downLevel').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = selected.getDownLevelData();
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.downLevel();
+                controller.showTreeData();
+            });
+        }
+    });
+    $('#upMove').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = selected.getUpMoveData();
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.upMove();
+                controller.showTreeData();
+            });
+        }
+    });
+    $('#downMove').click(function () {
+        var selected = controller.tree.selected, updateData;
+        if (selected) {
+            updateData = selected.getDownMoveData();
+            CommonAjax.post(updateUrl, updateData, function (data) {
+                controller.downMove();
+                controller.showTreeData();
+            });
+        }
+    });
+});

+ 22 - 2
web/users/views/compilation/template.html

@@ -26,7 +26,18 @@
             <legend>清单模板设置<a href="/compilation/valuation/<%= section %>/<%= valuationId %>" class="btn btn-default btn-sm pull-right">返回</a><a href="#" class="btn btn-primary btn-sm pull-right" style="margin-right:5px">保存</a></legend>
             <div class="row">
                 <div class="col-md-8">
-                    <div class="mb-qd-height">
+                    <div class="tools-btn btn-group align-top">
+                        <a href="" class="btn btn-sm"><i class="fa fa-files-o" aria-hidden="true"></i> 复制</a>
+                        <a href="" class="btn btn-sm"><i class="fa fa-scissors" aria-hidden="true"></i> 剪切</a>
+                        <a href="" class="btn btn-sm"><i class="fa fa-clipboard" aria-hidden="true"></i> 粘贴</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="insert"><i class="fa fa-sign-in" aria-hidden="true"></i> 插入</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="delete"><i class="fa fa-remove" aria-hidden="true"></i> 删除</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="upLevel"><i class="fa fa-arrow-left" aria-hidden="true"></i> 升级</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="downLevel"><i class="fa fa-arrow-right" aria-hidden="true"></i> 降级</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="downMove"><i class="fa fa-arrow-down" aria-hidden="true"></i> 下移</a>
+                        <a href="javascript:void(0)" class="btn btn-sm" id="upMove"><i class="fa fa-arrow-up" aria-hidden="true"></i> 上移</a>
+                    </div>
+                    <div class="mb-qd-height" id="billsSpread">
                     </div>
                 </div>
                 <div class="col-md-4">
@@ -38,4 +49,13 @@
             </div>
         </div>
     </div>
-</div>
+</div>
+<script>
+    let billsTemplateData = '<%- billsTemplateData %>';
+    let updateUrl = '/compilation/template/<%= section %>/<%= valuationId %>/update';
+</script>
+<script type="text/javascript" src="/public/web/id_tree.js"></script>
+<script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
+<script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_controller.js"></script>
+<script type="text/javascript" src="/public/web/common_ajax.js"></script>
+<script type="text/javascript" src="/web/users/js/template.js"></script>

+ 1 - 0
web/users/views/layout/layout.html

@@ -7,6 +7,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="renderer" content="webkit">
     <meta name=copyright content="smartcost.com.cn">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/web/users/css/bootstrap.min.css">
     <link rel="stylesheet" href="/web/users/css/style.css">
     <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">