ソースを参照

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionOperation

Conflicts:
	modules/reports/routes/report_router.js
TonyKang 8 年 前
コミット
db2189629a
90 ファイル変更8034 行追加2732 行削除
  1. 3 0
      .babelrc
  2. 1 1
      Dockerfile
  3. 2 1
      config/config.js
  4. 16 0
      config/db/db_manager.js
  5. 77 0
      config/menu.js
  6. 95 0
      crontab/cld_async_data.js
  7. 1 0
      crontab/counter.txt
  8. 48 1
      modules/bills_lib/controllers/bills_lib_controllers.js
  9. 704 755
      modules/bills_lib/models/bills_lib_interfaces.js
  10. 1 1
      modules/bills_lib/models/bills_lib_schemas.js
  11. 59 30
      modules/bills_lib/routes/bills_lib_routes.js
  12. 149 0
      modules/common/base/base_controller.js
  13. 134 0
      modules/common/base/base_model.js
  14. 47 0
      modules/common/fileUtils.js
  15. 212 0
      modules/common/helper/mongoose_helper.js
  16. 11 0
      modules/ration_repository/controllers/ration_controller.js
  17. 10 0
      modules/ration_repository/controllers/repository_glj_controller.js
  18. 5 4
      modules/ration_repository/models/glj_repository.js
  19. 25 0
      modules/ration_repository/models/ration_item.js
  20. 68 32
      modules/ration_repository/routes/ration_rep_routes.js
  21. 18 1
      modules/reports/routes/report_router.js
  22. 22 10
      modules/reports/routes/rpt_tpl_router.js
  23. 45 0
      modules/users/controllers/dashboard_controller.js
  24. 100 0
      modules/users/controllers/login_controller.js
  25. 194 0
      modules/users/controllers/manager_controller.js
  26. 28 0
      modules/users/controllers/notify_controller.js
  27. 27 0
      modules/users/controllers/tool_controller.js
  28. 57 0
      modules/users/controllers/user_controller.js
  29. 0 85
      modules/users/controllers/users_controller.js
  30. 275 0
      modules/users/models/manager_model.js
  31. 64 0
      modules/users/models/schemas/manager.js
  32. 49 0
      modules/users/models/schemas/user.js
  33. 66 0
      modules/users/models/user_model.js
  34. 0 49
      modules/users/models/users.js
  35. 20 0
      modules/users/routes/dashboard_route.js
  36. 23 0
      modules/users/routes/login_route.js
  37. 29 0
      modules/users/routes/manager_route.js
  38. 19 0
      modules/users/routes/notify_route.js
  39. 19 0
      modules/users/routes/tool_route.js
  40. 19 0
      modules/users/routes/user_route.js
  41. 0 37
      modules/users/routes/users_route.js
  42. 17 84
      operation.js
  43. 6 1
      package.json
  44. 1 1
      public/rpt_tpl_def.js
  45. 31 33
      public/web/id_tree.js
  46. 74 3
      public/web/sheet/sheet_common.js
  47. 2 1
      web/maintain/bills_lib/html/main.html
  48. 19 11
      web/maintain/bills_lib/html/neirong.html
  49. 118 46
      web/maintain/bills_lib/html/qingdan.html
  50. 35 19
      web/maintain/bills_lib/html/tezheng.html
  51. 141 21
      web/maintain/bills_lib/scripts/bills_lib_ajax.js
  52. 40 40
      web/maintain/bills_lib/scripts/bills_lib_setting.js
  53. 636 305
      web/maintain/bills_lib/scripts/db_controller.js
  54. 43 17
      web/maintain/bills_lib/scripts/set_sheets.js
  55. 10 2
      web/maintain/ration_repository/dinge.html
  56. 44 3
      web/maintain/ration_repository/gongliao.html
  57. 15 3
      web/maintain/ration_repository/js/ration.js
  58. 2 1
      web/maintain/ration_repository/js/ration_assist.js
  59. 135 11
      web/maintain/ration_repository/js/ration_glj.js
  60. 184 18
      web/maintain/ration_repository/js/repository_glj.js
  61. 6 0
      web/users/css/bootstrap.min.css
  62. 296 0
      web/users/css/style.css
  63. BIN
      web/users/fonts/glyphicons-halflings-regular.eot
  64. 288 0
      web/users/fonts/glyphicons-halflings-regular.svg
  65. BIN
      web/users/fonts/glyphicons-halflings-regular.ttf
  66. BIN
      web/users/fonts/glyphicons-halflings-regular.woff
  67. BIN
      web/users/fonts/glyphicons-halflings-regular.woff2
  68. 49 0
      web/users/js/admin.js
  69. 29 0
      web/users/js/global.js
  70. 657 0
      web/users/js/lib/bootstrap-paginator.js
  71. 7 0
      web/users/js/lib/bootstrap.min.js
  72. 1578 0
      web/users/js/lib/jquery.validate.js
  73. 33 0
      web/users/js/lib/messages_zh.js
  74. 14 0
      web/users/js/lib/validate.extend.js
  75. 79 0
      web/users/js/login.js
  76. 80 0
      web/users/js/manager.js
  77. 0 88
      web/users/login-infoinput.html
  78. 0 296
      web/users/login-welcome.html
  79. 0 132
      web/users/login.html
  80. 0 589
      web/users/project-management.html
  81. 48 0
      web/users/views/dashboard/index.html
  82. 101 0
      web/users/views/layout/layout.html
  83. 87 0
      web/users/views/layout/page.html
  84. 18 0
      web/users/views/layout/second_menu.html
  85. 54 0
      web/users/views/login/index.html
  86. 56 0
      web/users/views/manager/index.html
  87. 36 0
      web/users/views/manager/save.html
  88. 114 0
      web/users/views/notify/index.html
  89. 29 0
      web/users/views/tool/index.html
  90. 80 0
      web/users/views/user/index.html

+ 3 - 0
.babelrc

@@ -0,0 +1,3 @@
+{
+  "presets": ["es2015", "stage-2"]
+}

+ 1 - 1
Dockerfile

@@ -8,6 +8,6 @@ RUN cnpm install
 
 
 EXPOSE 6080
 EXPOSE 6080
 
 
-ENTRYPOINT node operation.js
+ENTRYPOINT babel-node operation.js
 
 
 
 

+ 2 - 1
config/config.js

@@ -17,5 +17,6 @@ module.exports = {
         var me = this;
         var me = this;
         me.current.server = me.prod.server;
         me.current.server = me.prod.server;
         me.current.port = me.prod.port;
         me.current.port = me.prod.port;
-    }
+    },
+    pageSize: 30
 }
 }

+ 16 - 0
config/db/db_manager.js

@@ -45,5 +45,21 @@ module.exports = {
         mg.connect('mongodb://' + config.current.server + ":" + config.current.port + '/' + dbName);
         mg.connect('mongodb://' + config.current.server + ":" + config.current.port + '/' + dbName);
         return mg;
         return mg;
         //*/
         //*/
+    },
+    connect:function () {
+        var config = require("../config.js");
+        var dbURL = 'mongodb://' + config.current.server + ":" + config.current.port + '/scConstruct';
+
+        var db = mg.connect(dbURL, config.options, function(err) {
+            if (err) {
+                console.log('Could not connect to MongoDB!');
+                console.log(err);
+            }
+        });
+        mg.connection.on('error', function(err) {
+            console.log('MongoDB connection error:', err);
+            process.exit(-1);
+        });
+        return mg;
     }
     }
 };
 };

+ 77 - 0
config/menu.js

@@ -0,0 +1,77 @@
+/**
+ * 菜单配置
+ *
+ * @author CaiAoLin
+ * @date 2017/6/5
+ * @version
+ */
+let menuData = {
+    'dashboard': {
+        title: '首页',
+        url: '/dashboard',
+        name: 'dashboard',
+        iconClass: 'glyphicon glyphicon-home'
+    },
+    'user': {
+        title: '用户管理',
+        url: '/user',
+        name: 'user',
+        iconClass: 'glyphicon glyphicon-user',
+        children: {
+            'index' : {
+                title: '最近注册',
+                url: '/user',
+                name: 'index',
+            },
+            'last-login' : {
+                title: '最近登录',
+                url: '/user/last-login',
+                name: 'last-login',
+            }
+        }
+    },
+    'notify': {
+        title: '通知管理',
+        url: '/notify',
+        name: 'notify',
+        iconClass: 'glyphicon glyphicon-bell',
+        children: {
+            'index' : {
+                title: '用户通知',
+                url: '/notify',
+                name: 'index',
+            },
+            'company' : {
+                title: '内部通知',
+                url: '/notify/company',
+                name: 'company',
+            }
+        }
+    },
+    'tool': {
+        title: '工具',
+        url: '/tool',
+        name: 'tool',
+        iconClass: 'glyphicon glyphicon-wrench'
+    },
+    'manager': {
+        title: '后台管理',
+        url: '/manager',
+        name: 'manager',
+        iconClass: 'glyphicon glyphicon-cog',
+        children: {
+            'index' : {
+                title: '账号管理',
+                url: '/manager',
+                name: 'index',
+            },
+            'admin' : {
+                title: '超级管理员',
+                url: '/manager/admin',
+                name: 'admin',
+            }
+        }
+    }
+};
+
+export default menuData;

+ 95 - 0
crontab/cld_async_data.js

@@ -0,0 +1,95 @@
+/**
+ * CLD数据同步计划任务
+ *
+ * @author CaiAoLin
+ * @date 2017/7/26
+ * @version
+ */
+import ManagerModel from "../modules/users/models/manager_model";
+import DBManager from "../config/db/db_manager";
+import config from "../config/config";
+import fs from "fs";
+
+config.setToLocalDb();
+let connect = DBManager.connect();
+let counterFile = "./counter.txt";
+
+let main = async function () {
+    // 读取计数器
+    let id = fs.readFileSync(counterFile, "utf-8");
+    let CLDAsyncUrl = 'http://cld.smartcost.com.cn/api/async-user';
+
+    let managerModel = new ManagerModel();
+    try {
+        // 生成加密token
+        let [encryptToken, time] = managerModel.generateCLDToken();
+        let postData = {
+            time: time,
+            token: encryptToken,
+            last_id: id,
+            app: 'scConstruct'
+        };
+        let postOption = {
+            url: CLDAsyncUrl,
+            form: postData,
+            encoding: 'utf8'
+        };
+        let responseData = await managerModel.CLDRequest(postOption);
+        let userList = responseData;
+        if (userList.length <= 0) {
+            throw {code: 30001, msg: "没有数据"};
+        }
+
+        let usernameList = [];
+        for (let tmp of userList) {
+            usernameList.push(tmp.username);
+        }
+        // 查找对应的数据
+        let condition = {username: {"$in": usernameList}};
+        let managerData = await managerModel.findDataByCondition(condition, null, false, 'username');
+
+        // 准备插入数据库
+        let current = new Date().getTime();
+        let insertData = [];
+        let lastId = 0;
+        for (let tmp of userList) {
+            if (managerData[tmp.username] !== undefined) {
+                continue;
+            }
+            let userTmp = {
+                username: tmp.username,
+                password: '',
+                token: '',
+                create_time: current,
+                office: tmp.office,
+                can_login: 0
+            };
+            insertData.push(userTmp);
+            lastId = tmp.sid;
+        }
+
+        if (insertData.length <= 0) {
+            throw '没有需要操作的数据';
+        }
+        managerModel.setScene('cldInsert');
+        let insertResult = await managerModel.createManager(insertData);
+        if(insertResult.length > 0) {
+            // 成功则更新id
+            fs.writeFileSync(counterFile, lastId, "utf-8");
+        }
+
+    } catch (error) {
+        // 重置起始标识(如果需要循环才开启,开启后后台删除则过一段时间又会插入回数据库)
+        // let code = error.code !== undefined ? error.code : '';
+        // if (code === 30001) {
+        //     fs.writeFileSync(counterFile, 0, "utf-8");
+        // }
+        console.log(error);
+    }
+
+
+    // 用完关闭
+    connect.disconnect();
+};
+
+main();

+ 1 - 0
crontab/counter.txt

@@ -0,0 +1 @@
+0

+ 48 - 1
modules/bills_lib/controllers/bills_lib_controllers.js

@@ -76,6 +76,30 @@ module.exports = {
             callback(req, res, err, message, null);
             callback(req, res, err, message, null);
         });
         });
     },
     },
+    upMove: function(req, res){
+        let data = JSON.parse(req.body.data);
+        billsLibDao.upMove(data, function(err, message){
+            callback(req, res, err, message, null);
+        });
+    },
+    downMove: function (req, res) {
+        let data = JSON.parse(req.body.data);
+        billsLibDao.downMove(data, function (err, message) {
+            callback(req, res, err, message, null);
+        })
+    },
+    upLevel: function (req, res) {
+        let data = JSON.parse(req.body.data);
+        billsLibDao.upLevel(data, function(err, message){
+            callback(req, res, err, message, null);
+        })
+    },
+    downLevel: function (req, res) {
+        let data = JSON.parse(req.body.data);
+        billsLibDao.downLevel(data, function (err, message) {
+            callback(req, res, err, message, null)
+        })
+    },
     updatePNId: function (req, res) {
     updatePNId: function (req, res) {
         let data = JSON.parse(req.body.data);
         let data = JSON.parse(req.body.data);
         billsLibDao.updatePNId(data, function(err, message){
         billsLibDao.updatePNId(data, function(err, message){
@@ -154,6 +178,18 @@ module.exports = {
             callback(req, res, err, message, datas);
             callback(req, res, err, message, datas);
         });
         });
     },
     },
+    edCreateJob: function(req, res){
+        let data = JSON.parse(req.body.data);
+        billsLibDao.edCreateJob(data, function(err, message, id){
+            callback(req, res, err, message, id);
+        })
+    },
+    edUpdateJob: function(req, res){
+        let data = JSON.parse(req.body.data);
+        billsLibDao.edUpdateJob(data, function(err, message, id){
+            callback(req, res, err, message, id);
+        })
+    },
     getItemCharacter: function(req, res){
     getItemCharacter: function(req, res){
         let data = JSON.parse(req.body.data);
         let data = JSON.parse(req.body.data);
         billsLibDao.getItemCharacter(data, function(err, message, items){
         billsLibDao.getItemCharacter(data, function(err, message, items){
@@ -189,7 +225,18 @@ module.exports = {
         billsLibDao.pasteValues(data, function(err, message, datas){
         billsLibDao.pasteValues(data, function(err, message, datas){
             callback(req, res, err, message, datas);
             callback(req, res, err, message, datas);
         });
         });
+    },
+    edCreateItem: function(req, res){
+        let data = JSON.parse(req.body.data);
+        billsLibDao.edCreateItem(data, function(err, message, id){
+            callback(req, res, err, message, id);
+        })
+    },
+    edUpdateItem: function(req, res){
+        let data = JSON.parse(req.body.data);
+        billsLibDao.edUpdateItem(data, function(err, message, id){
+            callback(req, res, err, message, id);
+        })
     }
     }
-
 }
 }
 
 

ファイルの差分が大きいため隠しています
+ 704 - 755
modules/bills_lib/models/bills_lib_interfaces.js


+ 1 - 1
modules/bills_lib/models/bills_lib_schemas.js

@@ -1,7 +1,7 @@
 let mongoose = require('mongoose');
 let mongoose = require('mongoose');
 
 
 let stdBillsLibSchema =mongoose.Schema({
 let stdBillsLibSchema =mongoose.Schema({
-    userId: Number,
+    userId: String,
     billsLibId: Number,
     billsLibId: Number,
     billsLibName: String,
     billsLibName: String,
     createDate: Date,
     createDate: Date,

+ 59 - 30
modules/bills_lib/routes/bills_lib_routes.js

@@ -5,34 +5,63 @@ let express = require("express");
 let billsController = require("./../controllers/bills_lib_controllers");
 let billsController = require("./../controllers/bills_lib_controllers");
 let billsRouter =express.Router();
 let billsRouter =express.Router();
 
 
-billsRouter.post('/getMaxNumber', billsController.getMaxNumber);
-billsRouter.post('/getABillsLib', billsController.getABillsLib);
-billsRouter.post("/getStdBillsLib", billsController.getStdBillsLib);
-billsRouter.post("/createStdBillsLib", billsController.createStdBillsLib);
-billsRouter.post("/deleteStdBillsLib", billsController.deleteStdBillsLib);
-billsRouter.post("/renameStdBillsLib", billsController.renameStdBillsLib);
-billsRouter.post("/getStdBillsLibName", billsController.getStdBillsLibName);
-billsRouter.post("/getCurrentUniqId", billsController.getCurrentUniqId);
-billsRouter.post("/getBills", billsController.getBills);
-billsRouter.post("/createBills", billsController.createBills);
-billsRouter.post("/updatePNId", billsController.updatePNId);
-billsRouter.post("/updateBills", billsController.updateBills);
-billsRouter.post("/updateBillsArr", billsController.updateBillsArr);
-billsRouter.post("/pasteBills", billsController.pasteBills);
-billsRouter.post('/updateRecharge', billsController.updateRecharge);
-billsRouter.post('/pasteRel', billsController.pasteRel);
-billsRouter.post("/deleteBills", billsController.deleteBills);
-billsRouter.post("/getJobContent", billsController.getJobContent);
-billsRouter.post("/createJobContent", billsController.createJobContent);
-billsRouter.post("/updateJobContent", billsController.updateJobContent);
-billsRouter.post("/deleteJobContent", billsController.deleteJobContent);
-billsRouter.post("/pasteJobs", billsController.pasteJobs);
-billsRouter.post("/getItemCharacter", billsController.getItemCharacter);
-billsRouter.post("/createItemCharacter", billsController.createItemCharacter);
-billsRouter.post("/updateItemCharacter", billsController.updateItemCharacter);
-billsRouter.post("/updateValue", billsController.updateValue);
-billsRouter.post("/deleteItemCharacter", billsController.deleteItemCharacter);
-billsRouter.post("/pasteItems", billsController.pasteItems);
-billsRouter.post("/pasteValues", billsController.pasteValues);
+module.exports =function (app) {
+
+    app.get("/stdBillsmain", function(req, res){
+        res.render("maintain/bills_lib/html/main.html",
+            {userAccount: req.session.managerData.username,
+                userID: req.session.managerData.userID});
+    });
+    app.get("/stdBills", function(req, res){
+        res.render("maintain/bills_lib/html/qingdan.html");
+    });
+    app.get('/stdJobs', function(req, res){
+        res.render('maintain/bills_lib/html/neirong.html');
+    });
+    app.get('/stdItems', function(req, res){
+        res.render('maintain/bills_lib/html/tezheng.html');
+    });
+
+    billsRouter.post('/getMaxNumber', billsController.getMaxNumber);
+    billsRouter.post('/getABillsLib', billsController.getABillsLib);
+    billsRouter.post("/getStdBillsLib", billsController.getStdBillsLib);
+    billsRouter.post("/createStdBillsLib", billsController.createStdBillsLib);
+    billsRouter.post("/upMove", billsController.upMove);
+    billsRouter.post("/downMove", billsController.downMove);
+    billsRouter.post("/deleteStdBillsLib", billsController.deleteStdBillsLib);
+    billsRouter.post("/renameStdBillsLib", billsController.renameStdBillsLib);
+    billsRouter.post("/getStdBillsLibName", billsController.getStdBillsLibName);
+    billsRouter.post("/getCurrentUniqId", billsController.getCurrentUniqId);
+    billsRouter.post("/getBills", billsController.getBills);
+    billsRouter.post("/createBills", billsController.createBills);
+    billsRouter.post("/updatePNId", billsController.updatePNId);
+    billsRouter.post("/upLevel", billsController.upLevel);
+    billsRouter.post("/downLevel", billsController.downLevel);
+    billsRouter.post("/updateBills", billsController.updateBills);
+    billsRouter.post("/updateBillsArr", billsController.updateBillsArr);
+    billsRouter.post("/pasteBills", billsController.pasteBills);
+    billsRouter.post('/updateRecharge', billsController.updateRecharge);
+    billsRouter.post('/pasteRel', billsController.pasteRel);
+    billsRouter.post("/deleteBills", billsController.deleteBills);
+    billsRouter.post("/getJobContent", billsController.getJobContent);
+    billsRouter.post("/createJobContent", billsController.createJobContent);
+    billsRouter.post("/updateJobContent", billsController.updateJobContent);
+    billsRouter.post("/deleteJobContent", billsController.deleteJobContent);
+    billsRouter.post("/pasteJobs", billsController.pasteJobs);
+    billsRouter.post("/edCreateJob", billsController.edCreateJob);
+    billsRouter.post("/edUpdateJob", billsController.edUpdateJob);
+    billsRouter.post("/getItemCharacter", billsController.getItemCharacter);
+    billsRouter.post("/createItemCharacter", billsController.createItemCharacter);
+    billsRouter.post("/updateItemCharacter", billsController.updateItemCharacter);
+    billsRouter.post("/updateValue", billsController.updateValue);
+    billsRouter.post("/deleteItemCharacter", billsController.deleteItemCharacter);
+    billsRouter.post("/pasteItems", billsController.pasteItems);
+    billsRouter.post("/pasteValues", billsController.pasteValues);
+    billsRouter.post("/edCreateItem", billsController.edCreateItem);
+    billsRouter.post("/edUpdateItem", billsController.edUpdateItem);
+
+    app.use("/stdBillsEditor", billsRouter);
+
+}
+
 
 
-module.exports = billsRouter;

+ 149 - 0
modules/common/base/base_controller.js

@@ -0,0 +1,149 @@
+/**
+ * 控制器基类
+ *
+ * @author CaiAoLin
+ * @date 2017/6/29
+ * @version
+ */
+import crypto from "crypto";
+import Url from "url";
+import Moment from "moment";
+import menuData from "../../../config/menu";
+
+class BaseController {
+
+    /**
+     * 页面title
+     *
+     * @var string
+     */
+    title = '';
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        if (new.target === BaseController) {
+            throw new Error('BaseController不能实例化,只能继承使用。');
+        }
+    }
+
+    /**
+     * 初始化函数
+     *
+     * @param {object} request
+     * @param {object} response
+     * @param {function} next
+     * @return {void}
+     */
+    init(request, response, next) {
+        // 获取当前控制器和动作名称
+        let urlInfo = Url.parse(request.originalUrl, true);
+        let url = urlInfo.pathname.substr(1);
+        let actionInfo = url.split('/');
+        let controller = 'index';
+        let action = 'index';
+        switch (actionInfo.length) {
+            case 1:
+                controller = actionInfo[0];
+                break;
+            case 2:
+                controller = actionInfo[0];
+                action = actionInfo[1];
+                break;
+            default:
+                controller = actionInfo[0];
+                break;
+        }
+
+        try {
+            // 如果不适超级管理员则判断权限
+            let sessionManager = request.session.managerData;
+            if (sessionManager.superAdmin !== 1) {
+                let currentPermission = sessionManager.permission;
+                // 校验权限
+                currentPermission = currentPermission.split(',');
+                let withoutPermission = ['login', 'dashboard'];
+                // 工具页面整合
+                let toolPermission = ['rationRepository', 'stdBillsmain'];
+                let hasToolPermission = false;
+                if (controller === 'tool') {
+                    for (let tmpPermission of toolPermission) {
+                        if (currentPermission.indexOf(tmpPermission) >= 0) {
+                            hasToolPermission = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (!hasToolPermission && withoutPermission.indexOf(controller) < 0 &&
+                    (currentPermission.length <= 0 || currentPermission.indexOf(controller)) < 0) {
+
+                    throw '没有权限';
+                }
+            }
+
+            // 菜单数据
+            response.locals.menu = menuData;
+            // 二级菜单数据
+            response.locals.secondMenu = menuData[controller] !== undefined && menuData[controller].children !== undefined ?
+                menuData[controller].children : {};
+
+            // url相关数据
+            response.locals.urlQuery = JSON.stringify(urlInfo.query);
+            response.locals.controller = controller;
+            response.locals.action = action;
+
+            // 用户session数据
+            response.locals.manager = sessionManager;
+
+            // moment工具
+            response.locals.moment = Moment;
+        } catch (error) {
+            console.log(error);
+            response.redirect('/dashboard');
+            return;
+        }
+
+        next();
+    }
+
+    /**
+     * 验证方法
+     *
+     * @param {object} request
+     * @param {object} response
+     * @param {function} next
+     * @return {void}
+     */
+    auth(request, response, next) {
+        // 判断session
+        let mangerData = request.session.managerData;
+        try {
+            if (typeof mangerData !== 'object' || Object.keys(mangerData).length < 0) {
+                throw 'err data';
+            }
+
+            if (mangerData.username === undefined || mangerData.loginTime === undefined) {
+                throw 'username empty';
+            }
+            // 校验session
+            let sessionToken = crypto.createHmac('sha1', mangerData.loginTime + '')
+                .update(mangerData.username).digest().toString('base64');
+            if (sessionToken !== mangerData.sessionToken) {
+                throw 'session error';
+            }
+
+        } catch (error) {
+            response.redirect('/login');
+            return;
+        }
+
+        next();
+    }
+
+}
+
+export default BaseController;

+ 134 - 0
modules/common/base/base_model.js

@@ -0,0 +1,134 @@
+/**
+ * 数据模型基类
+ *
+ * @author CaiAoLin
+ * @date 2017/6/22
+ * @version
+ */
+import MongooseHelper from "../helper/mongoose_helper";
+
+class BaseModel {
+
+    /**
+     * mongoose数据模型
+     *
+     * @var {object}
+     */
+    model = null;
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        if (new.target === BaseModel) {
+            throw new Error('BaseModel不能实例化,只能继承使用。');
+        }
+    }
+
+    /**
+     * 初始化函数
+     *
+     * @return {void}
+     */
+    init() {
+        if (this.model === null) {
+            throw new Error('子类数据有误');
+        }
+
+        this.db = new MongooseHelper();
+        this.db.model = this.model;
+    }
+
+    /**
+     * 根据id查找对应数据
+     *
+     * @param {Object} condition
+     * @param {Object} fields
+     * @param {boolean} singleData
+     * @param {String} indexBy
+     * @return {Promise}
+     */
+    async findDataByCondition(condition, fields = null, singleData = true, indexBy = null) {
+        let result = [];
+        if (Object.keys(condition).length <= 0) {
+            return result;
+        }
+
+        result = singleData ? await this.db.findOne(condition, fields) : await this.db.find(condition, fields);
+
+        if (indexBy !== null && !singleData && result.length > 0) {
+            let tmpResult = {};
+            for(let tmp of result) {
+                tmpResult[tmp[indexBy]] = tmp;
+            }
+            result = tmpResult;
+        }
+        return result;
+    }
+
+    /**
+     * 根据条件返回数据数量
+     *
+     * @param {object} condition
+     * @return {Promise}
+     */
+    async count(condition = null) {
+        let total = 0;
+        try {
+            total = await this.db.count(condition);
+        } catch (error) {
+            total = 0;
+        }
+        return total;
+    }
+
+    /**
+     * 根据id删除
+     *
+     * @param {Number|String} id
+     * @param {boolean} isString 设置是否为_id
+     * @return {Promise}
+     */
+    async deleteById(id, isString = false) {
+        let result = false;
+        if (!isString) {
+            id = parseInt(id);
+            if (isNaN(id) || id <= 0) {
+                return false;
+            }
+        }
+
+        let condition = !isString ? {id: id} : {_id: id};
+        try {
+            let deleteResult = await this.db.delete(condition);
+            result = deleteResult.result.ok === 1;
+        } catch (error) {
+            console.log(error);
+            result = false;
+        }
+
+        return result;
+    }
+
+    /**
+     * 更新数据
+     *
+     * @param {Number} id
+     * @param {Object} updateData
+     * @return {Promise}
+     */
+    async updateById(id, updateData) {
+        if (Object.keys(updateData).length <= 0) {
+            return false;
+        }
+        let condition = typeof id === 'number' ? {id: id} : {_id: id};
+        let result = await this.db.update(condition, updateData);
+
+        return result.ok !== undefined && result.ok === 1;
+    }
+
+}
+
+export default BaseModel;

+ 47 - 0
modules/common/fileUtils.js

@@ -0,0 +1,47 @@
+'use strict';
+
+/**
+ * Module dependencies.
+ */
+var _ = require('lodash'),
+	glob = require('glob');
+
+
+/**
+ * Get files by glob patterns
+ */
+module.exports.getGlobbedFiles = function(globPatterns, removeRoot) {
+	// For context switching
+	var _this = this;
+
+	// URL paths regex
+	var urlRegex = new RegExp('^(?:[a-z]+:)?\/\/', 'i');
+
+	// The output array
+	var output = [];
+
+	// If glob pattern is array so we use each pattern in a recursive way, otherwise we use glob
+	if (_.isArray(globPatterns)) {
+		globPatterns.forEach(function(globPattern) {
+			output = _.union(output, _this.getGlobbedFiles(globPattern, removeRoot));
+		});
+	} else if (_.isString(globPatterns)) {
+		if (urlRegex.test(globPatterns)) {
+			output.push(globPatterns);
+		} else {
+			glob(globPatterns, {
+				sync: true
+			}, function(err, files) {
+				if (removeRoot) {
+					files = files.map(function(file) {
+						return file.replace(removeRoot, '');
+					});
+				}
+
+				output = _.union(output, files);
+			});
+		}
+	}
+
+	return output;
+};

+ 212 - 0
modules/common/helper/mongoose_helper.js

@@ -0,0 +1,212 @@
+/**
+ * mongodb Helper
+ *
+ * @author caiaolin
+ * @date 2017/5/22.
+ */
+import mongoose from "mongoose";
+
+class MongooseHelper {
+
+    /**
+     * mongoose连接对象
+     *
+     * @var {object}
+     */
+    connect = null;
+
+    /**
+     * mongoose数据模型
+     *
+     * @var {object}
+     */
+    model = null;
+
+    /**
+     * 查找单一数据
+     *
+     * @param {object} conditions
+     * @param {object} fields
+     * @return {Promise}
+     */
+    findOne(conditions, fields = null) {
+        let self = this;
+        return new Promise(function (resolve, reject) {
+            self.model.findOne(conditions, fields, function (error, data) {
+                if (error) {
+                    reject(null);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 查找数据
+     *
+     * @param {object} conditions
+     * @param {object} fields
+     * @param {object} option
+     * @return {Promise}
+     */
+    find(conditions, fields = null, option = null) {
+        let self = this;
+        let limit = 0;
+        let skip = 0;
+        if (Object.keys(option).length > 0) {
+            limit = option.pageSize !== undefined ? option.pageSize : limit;
+            skip = option.offset !== undefined ? option.offset : skip;
+        }
+        return new Promise(function (resolve, reject) {
+            self.model.find(conditions, fields, option, function (error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            }).skip(skip).limit(limit);
+        });
+    }
+
+    /**
+     * 关联查找数据
+     *
+     * @param {object} conditions
+     * @param {object} fields
+     * @param {String|Object} populate
+     * @return {Promise}
+     */
+    findWithPopulate(conditions, fields = null, populate = '') {
+        let self = this;
+        return new Promise(function (resolve, reject) {
+            self.model.find(conditions, fields).populate(populate).exec(function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 查找且更新(原子操作)
+     *
+     * @param {object} update
+     * @param {object} condition
+     * @param {object} options
+     * @return {Promise}
+     */
+    findAndModify(condition, update, options) {
+        let self = this;
+        return new Promise(function (resolve, reject) {
+            self.model.findOneAndUpdate(condition, update, options, function(error, data) {
+                    if (error) {
+                        reject(error);
+                    } else {
+                        resolve(data);
+                    }
+                });
+        });
+    }
+
+    /**
+     * 新增操作
+     *
+     * @param {object} data
+     * @return {Promise}
+     */
+    create(data) {
+        let self = this;
+        return new Promise(function (resolve, reject) {
+            self.model.create(data, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 统计数据数量
+     *
+     * @param {Object} condition
+     * @return {Promise}
+     */
+    count(condition) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            self.model.count(condition, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param {Object} condition
+     * @return {Promise}
+     */
+    delete(condition) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            condition = self._convertId(condition);
+            self.model.remove(condition, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 更新数据
+     *
+     * @param {Object} condition
+     * @param {Object} updateData
+     * @return {Promise}
+     */
+    update(condition, updateData) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            condition = self._convertId(condition);
+            self.model.update(condition, {$set: updateData}, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * id转换为objectId
+     *
+     * @param {object} condition
+     * @return {object}
+     */
+    _convertId(condition) {
+        // 对于ID的处理
+        if (condition === null || condition._id === undefined) {
+            return condition;
+        }
+        let result = mongoose.Types.ObjectId(condition._id);
+        condition._id = result;
+
+        return condition;
+    }
+
+}
+
+export default MongooseHelper;

+ 11 - 0
modules/ration_repository/controllers/ration_controller.js

@@ -43,5 +43,16 @@ module.exports = {
                 }
                 }
             });
             });
         }
         }
+    },
+    updateRationBasePrc: function (req, res) {
+        let data = JSON.parse(req.body.data);
+        rationItem.updateRationBasePrc(data, function (err, message, rst) {
+            if(err){
+                callback(req, res, err, message, null);
+            }
+            else{
+                callback(req, res, err, message, rst);
+            }
+        })
     }
     }
 }
 }

+ 10 - 0
modules/ration_repository/controllers/repository_glj_controller.js

@@ -2,11 +2,21 @@
  * Created by Tony on 2017/5/5.
  * Created by Tony on 2017/5/5.
  */
  */
 var gljRepository = require("../models/glj_repository");
 var gljRepository = require("../models/glj_repository");
+let stdgljutil = require("../../../public/cache/std_glj_type_util");
 
 
 var callback = function(req,res,err,message, data){
 var callback = function(req,res,err,message, data){
     res.json({error: err, message: message, data: data});
     res.json({error: err, message: message, data: data});
 }
 }
 module.exports ={
 module.exports ={
+    getGljDistType: function (req, res) {
+        let gljDistTypeCache = stdgljutil.getStdGljTypeCacheObj().toArray();
+        if(gljDistTypeCache.length >0 ){
+            callback(req, res, null, '', gljDistTypeCache);
+        }
+        else {
+            callback(req, res, 1, 'Error', null);
+        }
+    },
     getGljTree: function(req,res){
     getGljTree: function(req,res){
         var rationLibId = req.body.rationLibId;
         var rationLibId = req.body.rationLibId;
         gljRepository.getGljTypes(rationLibId,function(err,data){
         gljRepository.getGljTypes(rationLibId,function(err,data){

+ 5 - 4
modules/ration_repository/models/glj_repository.js

@@ -9,7 +9,7 @@ var db = dbm.getCfgConnection("scConstruct");
 var async = require("async");
 var async = require("async");
 var Schema = mongoose.Schema;
 var Schema = mongoose.Schema;
 
 
-var gljTypeSchema = mongoose.Schema({
+var gljClassSchema = mongoose.Schema({
     repositoryId: Number,
     repositoryId: Number,
     ID: Number,
     ID: Number,
     ParentID: Number,
     ParentID: Number,
@@ -26,11 +26,12 @@ var gljSchema = mongoose.Schema({
     name: String,
     name: String,
     specs: String,
     specs: String,
     unit: String,
     unit: String,
+    shortName: String,
     basePrice: Number,
     basePrice: Number,
-    gljType: Number, //这个是UI显示上的详细分类,对应gljTypeSchema
-    gljDistType: String  //人工,材料,机械
+    gljClass: Number, //这个是UI显示上的详细分类,对应gljTypeSchema
+    gljType: Number  //人工,材料,机械
 });
 });
-var gljTypeModel = db.model("std_ration_lib_glj_type",gljTypeSchema, "std_ration_lib_glj_type");
+var gljTypeModel = db.model("std_ration_lib_glj_type",gljClassSchema, "std_ration_lib_glj_type");
 var gljItemModel = db.model("std_ration_lib_glj_list",gljSchema, "std_ration_lib_glj_list");
 var gljItemModel = db.model("std_ration_lib_glj_list",gljSchema, "std_ration_lib_glj_list");
 var repositoryMap = require('./repository_map');
 var repositoryMap = require('./repository_map');
 var counter = require('../../../public/counter/counter');
 var counter = require('../../../public/counter/counter');

+ 25 - 0
modules/ration_repository/models/ration_item.js

@@ -30,6 +30,9 @@ var rationItemSchema = mongoose.Schema({
     code: String,
     code: String,
     name: String,
     name: String,
     unit: String,
     unit: String,
+    labourPrice: Number,
+    materialPrice: Number,
+    machinePrice: Number,
     basePrice: Number,
     basePrice: Number,
     sectionId: Number,
     sectionId: Number,
     rationRepId: Number,
     rationRepId: Number,
@@ -177,5 +180,27 @@ rationItemDAO.prototype.updateRationItems = function(rationLibId, sectionId, ite
     });
     });
 };
 };
 
 
+rationItemDAO.prototype.updateRationBasePrc = function (data, callback) {
+    let gljId = data.gljId, basePrice = data.basePrice;
+    rationItemModel.find({'rationGljList.gljId': gljId}, function (err, reslut) {
+        if(err){
+
+        }
+        else{
+            async.each(reslut, function (rationItem, cb) {
+                let rationBasePrc = rationItem.basePrice,
+                    gljList = rationItem.gljList, gljPrcObj;
+                for(let i=0; i< gljList.length; i++){
+                    if(gljList[i].gljId === gljId){
+                        gljPrcObj = gljList[i];
+                        break;
+                    }
+                }
+
+            });
+        }
+    });
+};
+
 module.exports = new rationItemDAO()
 module.exports = new rationItemDAO()
 
 

+ 68 - 32
modules/ration_repository/routes/ration_rep_routes.js

@@ -12,35 +12,71 @@ var repositoryGljController = require("../controllers/repository_glj_controller"
 var coeListController = require("../controllers/coe_controller");
 var coeListController = require("../controllers/coe_controller");
 var searchController = require('../controllers/search_controller');
 var searchController = require('../controllers/search_controller');
 
 
-apiRouter.post("/getRationDisplayNames",rationRepositoryController.getDisPlayRationLibs);
-apiRouter.post("/editRationLibs",rationRepositoryController.updateRationRepositoryName);
-apiRouter.post("/addRationRepository",rationRepositoryController.addRationRepository);
-apiRouter.post("/deleteRationLibs",rationRepositoryController.deleteRationLib);
-apiRouter.post("/getRealLibName",rationRepositoryController.getRealLibName);
-apiRouter.post("/getLibIDByName",rationRepositoryController.getLibIDByName);
-
-apiRouter.post("/getRationTree",rationChapterTreeController.getRationChapterTree);
-apiRouter.post("/createNewNode",rationChapterTreeController.createNewNode);
-apiRouter.post("/updateNodes",rationChapterTreeController.updateNodes);
-apiRouter.post("/deleteNodes",rationChapterTreeController.deleteNodes);
-
-apiRouter.post("/getRationItems",rationController.getRationItemsBySection);
-apiRouter.post("/mixUpdateRationItems",rationController.mixUpdateRationItems);
-
-apiRouter.post("/createNewGljTypeNode",repositoryGljController.createNewGljTypeNode);
-apiRouter.post("/updateGljNodes",repositoryGljController.updateGljNodes);
-apiRouter.post("/deleteGljNodes",repositoryGljController.deleteGljNodes);
-apiRouter.post("/getGljTree",repositoryGljController.getGljTree);
-apiRouter.post("/getGljItems",repositoryGljController.getGljItems);
-apiRouter.post("/mixUpdateGljItems",repositoryGljController.mixUpdateGljItems);
-apiRouter.post("/getGljItemsByIds",repositoryGljController.getGljItemsByIds);
-apiRouter.post("/getGljItemsByCodes",repositoryGljController.getGljItemsByCodes);
-
-apiRouter.post("/getCoeList",coeListController.getCoeList);
-apiRouter.post("/saveCoeList",coeListController.saveCoeList);
-apiRouter.post("/getCoeItemsByIDs",coeListController.getCoeItemsByIDs);
-
-apiRouter.post('/getRationItem', searchController.getRationItem);
-apiRouter.post('/findRation', searchController.findRation);
-
-module.exports = apiRouter;
+
+module.exports =  function (app) {
+
+    app.get('/rationRepository/main', function(req, res) {
+        res.render('maintain/ration_repository/main.html',
+            {
+                userAccount: req.session.userAccount,
+                userID: req.session.userID
+            });
+    });
+    app.get('/rationRepository/ration', function(req, res) {
+        res.render('maintain/ration_repository/dinge.html',
+            {
+                userAccount: req.session.userAccount,
+                userID: req.session.userID
+            });
+    });
+    app.get('/rationRepository/lmm', function(req, res) {
+        res.render('maintain/ration_repository/gongliao.html',
+            {
+                userAccount: req.session.userAccount,
+                userID: req.session.userID
+            });
+    });
+
+    app.get('/rationRepository/coeList', function(req, res) {
+        res.render('maintain/ration_repository/fuzhu.html',
+            {
+                userAccount: req.session.userAccount,
+                userID: req.session.userID
+            });
+    });
+
+    apiRouter.post("/getRationDisplayNames",rationRepositoryController.getDisPlayRationLibs);
+    apiRouter.post("/editRationLibs",rationRepositoryController.updateRationRepositoryName);
+    apiRouter.post("/addRationRepository",rationRepositoryController.addRationRepository);
+    apiRouter.post("/deleteRationLibs",rationRepositoryController.deleteRationLib);
+    apiRouter.post("/getRealLibName",rationRepositoryController.getRealLibName);
+    apiRouter.post("/getLibIDByName",rationRepositoryController.getLibIDByName);
+
+    apiRouter.post("/getRationTree",rationChapterTreeController.getRationChapterTree);
+    apiRouter.post("/createNewNode",rationChapterTreeController.createNewNode);
+    apiRouter.post("/updateNodes",rationChapterTreeController.updateNodes);
+    apiRouter.post("/deleteNodes",rationChapterTreeController.deleteNodes);
+
+    apiRouter.post("/getRationItems",rationController.getRationItemsBySection);
+    apiRouter.post("/mixUpdateRationItems",rationController.mixUpdateRationItems);
+    apiRouter.post("/updateRationBasePrc",rationController.updateRationBasePrc);
+
+    apiRouter.post("/createNewGljTypeNode",repositoryGljController.createNewGljTypeNode);
+    apiRouter.post("/updateGljNodes",repositoryGljController.updateGljNodes);
+    apiRouter.post("/deleteGljNodes",repositoryGljController.deleteGljNodes);
+    apiRouter.post("/getGljDistType",repositoryGljController.getGljDistType);
+    apiRouter.post("/getGljTree",repositoryGljController.getGljTree);
+    apiRouter.post("/getGljItems",repositoryGljController.getGljItems);
+    apiRouter.post("/mixUpdateGljItems",repositoryGljController.mixUpdateGljItems);
+    apiRouter.post("/getGljItemsByIds",repositoryGljController.getGljItemsByIds);
+    apiRouter.post("/getGljItemsByCodes",repositoryGljController.getGljItemsByCodes);
+
+    apiRouter.post("/getCoeList",coeListController.getCoeList);
+    apiRouter.post("/saveCoeList",coeListController.saveCoeList);
+    apiRouter.post("/getCoeItemsByIDs",coeListController.getCoeItemsByIDs);
+
+    apiRouter.post('/getRationItem', searchController.getRationItem);
+    apiRouter.post('/findRation', searchController.findRation);
+
+    app.use("/rationRepository/api",apiRouter);
+}

+ 18 - 1
modules/reports/routes/report_router.js

@@ -6,7 +6,24 @@ let express = require('express');
 let rptRouter = express.Router();
 let rptRouter = express.Router();
 let reportController = require('./../controllers/rpt_controller');
 let reportController = require('./../controllers/rpt_controller');
 
 
+<<<<<<< HEAD
 rptRouter.post('/getReport', reportController.getReportAllPages);
 rptRouter.post('/getReport', reportController.getReportAllPages);
 rptRouter.get('/getExcel/:id/:size/:rptName/:isOneSheet', reportController.getExcel);
 rptRouter.get('/getExcel/:id/:size/:rptName/:isOneSheet', reportController.getExcel);
+=======
+module.exports =function (app) {
+>>>>>>> 54307e7bc954a6c634a9960dab54b0f42578bc0f
 
 
-module.exports = rptRouter;
+    app.get('/report',  function(req, res) {
+        if (!req.session.userAccount) {
+            res.redirect('/login');
+        }
+        else {
+            res.render('maintain/report/rpt_test.html',
+                {userAccount: req.session.userAccount,
+                    userID: req.session.userID});
+        }
+    });
+    rptRouter.post('/getReport', reportController.getReportAllPages);
+    rptRouter.get('/getExcel/:id/:size/:rptName', reportController.getExcel);
+    app.use("/report_api", rptRouter);
+}

+ 22 - 10
modules/reports/routes/rpt_tpl_router.js

@@ -3,15 +3,27 @@ let rptTplRouter = express.Router();
 let reportTplController = require('./../controllers/rpt_tpl_controller');
 let reportTplController = require('./../controllers/rpt_tpl_controller');
 let reportCfgController = require('./../controllers/rpt_cfg_controller');
 let reportCfgController = require('./../controllers/rpt_cfg_controller');
 
 
-rptTplRouter.post('/createTplTreeNode', reportTplController.createTplTreeNode);
-rptTplRouter.post('/getRptTplTree', reportTplController.getRptTplTree);
-rptTplRouter.post('/updateRptTplNodes', reportTplController.updateTreeNodes);
-rptTplRouter.post('/deleteRptTplNodes', reportTplController.deleteRptTplNodes);
-rptTplRouter.post('/createDftRptTpl', reportTplController.createDftRptTpl);
-rptTplRouter.post('/getRefRptTpl', reportTplController.getRefRptTpl);
-rptTplRouter.post('/updateRptTpl', reportTplController.updateRptTpl);
+module.exports = function (app) {
+    app.get('/rpt_tpl',  function(req, res) {
+        if (!req.session.userAccount) {
+            res.redirect('/login');
+        }
+        else {
+            res.render('maintain/report/rpt_tpl_main.html',
+                {userAccount: req.session.userAccount,
+                    userID: req.session.userID});
+        }
+    });
 
 
-rptTplRouter.post('/getUserRptCfg', reportCfgController.getReportUserCfg);
-rptTplRouter.post('/getMappingFields', reportCfgController.getAllMappingFields);
+    rptTplRouter.post('/createTplTreeNode', reportTplController.createTplTreeNode);
+    rptTplRouter.post('/getRptTplTree', reportTplController.getRptTplTree);
+    rptTplRouter.post('/updateRptTplNodes', reportTplController.updateTreeNodes);
+    rptTplRouter.post('/deleteRptTplNodes', reportTplController.deleteRptTplNodes);
+    rptTplRouter.post('/createDftRptTpl', reportTplController.createDftRptTpl);
+    rptTplRouter.post('/getRefRptTpl', reportTplController.getRefRptTpl);
+    rptTplRouter.post('/updateRptTpl', reportTplController.updateRptTpl);
 
 
-module.exports = rptTplRouter;
+    rptTplRouter.post('/getUserRptCfg', reportCfgController.getReportUserCfg);
+    rptTplRouter.post('/getMappingFields', reportCfgController.getAllMappingFields);
+    app.use("/report_tpl_api", rptTplRouter);
+}

+ 45 - 0
modules/users/controllers/dashboard_controller.js

@@ -0,0 +1,45 @@
+/**
+ * 控制面板相关控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/6/2
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+
+class DashboardController extends BaseController {
+
+    /**
+     * 一级菜单显示
+     *
+     * @var {string}
+     */
+    static parentTitle = '后台管理';
+
+    /**
+     * 一级菜单
+     *
+     * @var {string}
+     */
+    static parentIndex = 'manager';
+
+
+    /**
+     * 控制面板首页
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    index(request, response) {
+        let renderData = {
+            parentTitle: DashboardController.parentTitle,
+            parentIndex: DashboardController.parentIndex,
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/dashboard/index', renderData);
+    }
+
+}
+
+export default DashboardController;

+ 100 - 0
modules/users/controllers/login_controller.js

@@ -0,0 +1,100 @@
+/**
+ * 登录页面控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/6/1
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+import ManagerModel from "../models/manager_model";
+import crypto from "crypto";
+
+class LoginController extends BaseController {
+
+    /**
+     * 登录页面
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void|Mixed}
+     */
+    index(request, response) {
+        let renderData = {
+            layout: false,
+        };
+        let managerSessionData = request.session.managerData;
+        if (managerSessionData !== undefined) {
+            return response.redirect("/dashboard");
+        }
+        response.render('users/views/login/index', renderData);
+    }
+
+    /**
+     * 登录操作
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {string}
+     */
+    async login(request, response) {
+        let username = request.body.username;
+        let password = request.body.password;
+        let managerModel = new ManagerModel();
+
+        let responseData = {
+            error: 0,
+            msg: ''
+        };
+        try {
+            let managerData = await managerModel.validLogin(username, password);
+
+            // 成功后写入session
+            let currentTime = new Date().getTime();
+            let sessionToken = crypto.createHmac('sha1', currentTime + '').update(managerData.username)
+                .digest().toString('base64');
+            let managerSession = {
+                username: managerData.username,
+                loginTime: currentTime,
+                sessionToken: sessionToken,
+                userID: managerData.id,
+                permission: managerData.permission === undefined ? '' : managerData.permission,
+                superAdmin: managerData.super_admin
+            };
+            request.session.managerData = managerSession;
+
+            // 更新登录信息
+            let ip = request.connection.remoteAddress;
+            ip = ip.split(':');
+            ip = ip[3] === undefined ? '' : ip[3];
+            let updateData = {
+                login_ip: ip,
+                last_login: new Date().getTime()
+            };
+            let updateResult = managerModel.updateById(managerData._id, updateData);
+            if (!updateResult) {
+                throw '更新登录信息失败!';
+            }
+        } catch (error) {
+            responseData.error = error.code;
+            responseData.msg = error.err;
+        }
+
+        response.json(responseData);
+    }
+
+    /**
+     * 退出操作
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    logout(request, response) {
+        // 清空session
+        request.session.destroy();
+        response.redirect('/login');
+    }
+
+}
+
+export default LoginController;

+ 194 - 0
modules/users/controllers/manager_controller.js

@@ -0,0 +1,194 @@
+/**
+ * 后台用户管理控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/6/2
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+import ManagerModel from "../models/manager_model";
+import Config from "../../../config/config";
+
+class ManagerController extends BaseController {
+
+    /**
+     *  账号管理(管理员列表)
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async index(request, response) {
+        let pageData = {};
+        let managerList = [];
+        try {
+            // 查找管理员用户列表
+            let managerModel = new ManagerModel();
+            let total = await managerModel.count();
+
+            // 分页数据
+            let page = request.query.page === undefined ? 1 : request.query.page;
+            pageData = {
+                current: page,
+                total: parseInt(total / Config.pageSize),
+                queryData: response.locals.urlQuery
+            };
+
+            // 获取管理员列表
+            managerList = await managerModel.getList(null, page);
+
+            // 整理数据
+            if (managerList.length > 0) {
+                for (let tmp in managerList) {
+                    let permission = managerList[tmp].permission;
+                    permission = permission.split(',');
+
+                    if (permission.length <= 0) {
+                        continue;
+                    }
+
+                    let permissionString = [];
+                    for (let name of permission) {
+                        if (managerModel.permission[name] === undefined) {
+                            continue;
+                        }
+                        permissionString.push(managerModel.permission[name]);
+                    }
+                    permissionString = permissionString.join(',');
+                    managerList[tmp].permissionStr = permissionString;
+                }
+            }
+        } catch (error) {
+
+        }
+
+        let renderData = {
+            managerList: managerList,
+            pages: pageData,
+            layout: 'users/views/layout/layout',
+        };
+        response.render('users/views/manager/index', renderData);
+    }
+
+    /**
+     * 保存管理员
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async modify(request, response) {
+        let permission = request.body.permission;
+        let canLogin = request.body.login;
+        let id = request.params.id;
+
+        let responseData = {
+            err: 0,
+            msg: ""
+        };
+        try {
+            if (id === '' || id === undefined) {
+                throw 'id有误';
+            }
+            let managerModel = new ManagerModel();
+            let result = await managerModel.updateById(id, {permission: permission, can_login: canLogin});
+
+            if (!result) {
+                throw '修改失败';
+            }
+
+        } catch (error) {
+            responseData.err = 1;
+            responseData.msg = error;
+        }
+
+        response.json(responseData);
+    }
+
+    /**
+     * 删除管理员
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async delete(request, response) {
+        let id = request.params.id;
+        let managerModel = new ManagerModel();
+        let result = await managerModel.deleteById(id, true);
+
+        // 删除成功
+        if (result) {
+
+        }
+        response.redirect(request.headers.referer);
+    }
+
+    /**
+     * 超级管理员修改
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async admin(request, response) {
+        let adminData = {};
+        try {
+            // 查找对应超级管理员数据
+            let managerModel = new ManagerModel();
+            adminData = await managerModel.findDataByCondition({username: 'admin'});
+
+        } catch (error) {
+            console.log(error);
+        }
+
+        let renderData = {
+            adminData: adminData,
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/manager/save', renderData);
+    }
+
+    /**
+     * 超级管理员修改提交
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return
+     */
+    async adminSubmit(request, response) {
+        let newPassword = request.body.newPassword.toString();
+        let password = request.body.password.toString();
+        let managerModel = new ManagerModel();
+        let responseData = {
+            err: 0,
+            msg: ''
+        };
+        try {
+            if (!newPassword || !password) {
+                throw '内容有误';
+            }
+            // 更改密码操作
+            managerModel.setScene('changPassword');
+            let result = await managerModel.changePassword('admin', password, newPassword);
+            if (!result) {
+                throw '更新错误';
+            }
+        } catch (error) {
+            console.log(error);
+            responseData.err = 40002;
+            responseData.msg = error;
+        }
+
+        response.json(responseData);
+    }
+
+    async create(request, response) {
+        let managerModel = new ManagerModel();
+        let result = managerModel.changePassword('admin', 'admin123', 'admin123');
+        // let result = await managerModel.createManager();
+        response.end('success');
+    }
+}
+
+export default ManagerController;

+ 28 - 0
modules/users/controllers/notify_controller.js

@@ -0,0 +1,28 @@
+/**
+ * 通知管理控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/6/7
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+
+class NotifyController extends BaseController {
+
+    /**
+     * 用户通知页面
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    index(request, response) {
+        let renderData = {
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/notify/index', renderData);
+    }
+
+}
+
+export default NotifyController;

+ 27 - 0
modules/users/controllers/tool_controller.js

@@ -0,0 +1,27 @@
+/**
+ * 工具页面控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/7/21
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+
+class ToolController extends BaseController {
+
+    /**
+     *  工具首页
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    index(request, response) {
+        let renderData = {
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/tool/index', renderData);
+    }
+
+}
+export default ToolController;

+ 57 - 0
modules/users/controllers/user_controller.js

@@ -0,0 +1,57 @@
+/**
+ * 用户管理控制器
+ *
+ * @author CaiAoLin
+ * @date 2017/6/7
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+import UserModel from "../models/user_model";
+import Config from "../../../config/config";
+
+class UserController extends BaseController {
+
+    /**
+     * 最近注册列表(最近登录前台用户列表)
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async lastRegister(request, response) {
+        let userModel = new UserModel();
+        let total = 0;
+        let pageData = {};
+        let userList = [];
+        try {
+            // 获取用户总数
+            total = await userModel.count();
+
+            // 分页数据
+            let page = request.query.page === undefined ? 1 : request.query.page;
+            pageData = {
+                current: page,
+                total: parseInt(total / Config.pageSize),
+                queryData: response.locals.urlQuery
+            };
+
+            // 获取用户列表
+            userList = await userModel.getList(null, page, Config.pageSize);
+        } catch (error) {
+            console.log(error);
+        }
+
+        // 渲染数据
+        let renderData = {
+            userList: userList,
+            pages: pageData,
+            total: total,
+            model: userModel,
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/user/index', renderData);
+    }
+
+}
+
+export default UserController;

+ 0 - 85
modules/users/controllers/users_controller.js

@@ -1,85 +0,0 @@
-var ut = require('../models/users');
-var rq = require('request');
-var online = true;
-
-module.exports = {
-    userLogin: function (req, res) {
-        var account = req.body.account;
-        var pw = req.body.pw;
-
-        if (online) {
-            rq.post(
-                {
-                    url: 'http://sso.smartcost.com.cn/api/jzlogin',
-                    form: {username: account, userpasswd: pw},
-                    encoding: 'utf8'
-                },
-                function (err, response, userData) {
-                    if (response.statusCode !== 200) {
-                        res.json({state: false, error: '通行证验证失败!出错代号:' + response.statusCode});
-                    } else {
-                        switch (userData) {
-                            case '-2':
-                                res.json({state: false, error: '密码错误!'});
-                                break;
-                            case '-22':
-                                res.json({state: false, error: '输入的邮箱/手机无效!'});
-                                break;
-                            default:
-                                userData = JSON.parse(userData);
-                                req.session.userID = userData[0].id;
-                                req.session.userAccount = userData[0].username;
-                                req.session.userEmail = userData[0].useremail;
-                                req.session.userMobile = userData[0].mobile;
-                                res.json({state: true, data: userData});
-                        }
-
-                    }
-                }
-            );
-        }
-        else {
-            ut.findUser(account, pw, function (err, userData) {
-                if (err) {
-                    res.json({state: false, error: err});
-                }
-                else {
-                    req.session.userID = userData[0].profile.id;
-                    req.session.userName = userData[0].profile.userName;
-                    req.session.userAccount = userData[0].profile.userAccount;
-                    req.session.userEmail = userData[0].profile.useRemail;
-                    req.session.userMobile = userData[0].profile.Mobile;
-                    res.json({state: true, data: userData});
-                }
-                ;
-            })
-        }
-    },
-
-    userReg: function (req, res) {
-        var account = req.body.account;
-        var pw = req.body.pw;
-        var name = req.body.name;
-
-        ut.checkAccount(account, function (userData) {
-            if (!userData) {  // 找不到用户,则注册
-                ut.addUser(account, pw, name, function (err) {
-                    if (err) {
-                        res.json({state: false, error: '“注册失败,原因:' + err});
-                    }
-                    else {
-                        res.json({state: true});
-                    }
-                });
-            }
-            else {  // 找到用户,则提示
-                res.json({state: false, error: '“' + account + '”已存在!'});
-            }
-            ;
-        })
-    }
-
-}
-
-
-

+ 275 - 0
modules/users/models/manager_model.js

@@ -0,0 +1,275 @@
+/**
+ * 后台管理员数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/6/1
+ * @version
+ */
+import BaseModel from "../../common/base/base_model";
+import ManagerSchema from "./schemas/manager";
+import crypto from "crypto";
+import Request from "request";
+
+class ManagerModel extends BaseModel {
+
+    /**
+     * 超级用户用户名
+     *
+     * @var {String}
+     */
+    adminUsername = 'admin';
+
+    /**
+     * 用户权限
+     *
+     * @var
+     */
+    permission = {
+        'manager': '用户管理',
+        'notify': '通知管理',
+        'stdBillsmain': '清单规则编辑器',
+        'rationRepository': '定额编辑器',
+        'report': '报表模板',
+    };
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = ManagerSchema;
+        parent.init();
+    }
+
+    /**
+     * 设置场景
+     *
+     * @param {string} scene
+     * @return {void}
+     */
+    setScene(scene = '') {
+        switch (scene) {
+            // 更改密码验证规则
+            case 'changePassword':
+                this.model.schema.path('password').required(true);
+                break;
+            // CLD新增
+            case 'cldInsert':
+                this.model.schema.path('username').required(true);
+                this.model.schema.path('create_time').required(true);
+                this.model.schema.path('office').required(true);
+                break;
+        }
+    }
+
+    /**
+     * 获取列表
+     *
+     * @param {object} condition
+     * @param {number} page
+     * @return {Promise}
+     */
+    getList(condition = null, page = 1) {
+        page = parseInt(page);
+        page = page <= 1 ? 1 : page;
+        let option = {page: page};
+        return this.db.find(condition, null, option);
+    }
+
+    /**
+     * 用户密码加密
+     *
+     * @param {string} token
+     * @param {string} password
+     * @return {string}
+     */
+    encryptPassword(token, password) {
+        let encryptPassword = crypto.createHmac('sha1', token).update(password)
+            .digest().toString('base64');
+        return encryptPassword;
+    }
+
+    /**
+     * 更改密码
+     *
+     * @param {string} username
+     * @param {string} password
+     * @param {string} newPassword
+     * @throws {string}
+     * @return {Promise}
+     */
+    async changePassword(username, password, newPassword) {
+
+        // 查找对应用户
+        let managerData = await this.findDataByCondition({username: username});
+        if (managerData.length <= 0) {
+            return false;
+        }
+
+        // 验证旧密码
+        let encryptPassword = this.encryptPassword(managerData.token, password);
+        if (encryptPassword !== managerData.password) {
+            throw '用户名或密码错误';
+        }
+
+        // 加密新密码
+        let encryptNewPassword = this.encryptPassword(managerData.token, newPassword);
+        let result = await this.db.update({username: username}, {password: encryptNewPassword});
+
+        return result.ok === 1;
+    }
+
+    /**
+     * 登录信息校验
+     *
+     * @param {String} username
+     * @param {String} password
+     * @return {Promise}
+     */
+    async validLogin(username, password) {
+        let managerData = await this.findDataByCondition({username: username});
+
+        // 没有找到对应数据
+        if (managerData === null || managerData._id === undefined) {
+            throw {code: 44001, err: '用户名或密码错误'};
+        }
+
+        // 是否禁止登录
+        if (managerData.can_login !== 1) {
+            throw {code: 44002, err: '用户名不存在'};
+        }
+
+        // 如果不是超级管理员登录则走CLD接口登录流程
+        if (username !== this.adminUsername) {
+            let CLDLoginInfo = await this.CLDLogin(username, password, managerData);
+            managerData = CLDLoginInfo;
+        } else {
+            // 加密密码
+            let encryptPassword = this.encryptPassword(managerData.token, password);
+            if (encryptPassword !== managerData.password) {
+                throw {code: 44001, err: '用户名或密码错误'};
+            }
+        }
+
+        return managerData;
+    }
+
+
+    /**
+     * CLD登录
+     *
+     * @param {String} username
+     * @param {String} password
+     * @param {Object} managerData
+     * @return {Promise}
+     */
+    async CLDLogin(username, password, managerData) {
+        let result = managerData;
+        if (username === '' || password === '') {
+            throw {code: 44001, err: '用户名或密码错误'};
+        }
+
+        let CLDUrl = 'http://cld.smartcost.com.cn/api/auth';
+        // 生成加密token
+        let [encryptToken, postTime] = this.generateCLDToken();
+        let postData = {
+            username: username,
+            password: password,
+            time: postTime,
+            token: encryptToken,
+            app: 'scConstruct'
+        };
+
+        let postOption = {
+            url: CLDUrl,
+            form: postData,
+            encoding: 'utf8'
+        };
+        let responseData = await this.CLDRequest(postOption);
+        // 登录成功后,存在此用户则直接返回
+        if (managerData) {
+            return result;
+        }
+
+        // 不存在则新增
+        this.setScene('cldInsert');
+        let current = new Date().getTime();
+        let insertData = {
+            username: username,
+            password: '',
+            token: '',
+            create_time: current,
+            last_login: current,
+            office: responseData.office,
+            can_login: 0
+        };
+        result = this.db.create(insertData);
+
+        return result;
+    }
+
+    /**
+     * CLD请求
+     *
+     * @param {Object} postOption
+     * @return {Promise}
+     */
+    CLDRequest(postOption) {
+        return new Promise(function(resolve, reject) {
+            // 发起请求
+            Request.post(postOption, function(error, response, body) {
+                if (error || response.statusCode !== 200) {
+                    console.log(response.statusCode + ':' + error);
+                    reject({code: 44002, err: '接口请求出错'});
+                    return;
+                }
+
+                body = JSON.parse(body);
+
+                // 如果接口返回错误
+                if (body.err !== 0) {
+                    reject({code: body.err, err: '接口返回错误'});
+                    return;
+                }
+
+                resolve(body.data);
+            });
+        });
+    }
+
+    /**
+     * 生成CLD Token
+     *
+     * @return {Array}
+     */
+    generateCLDToken() {
+        // 加密内容
+        let token = 'sc@ConS!tru@ct*88';
+        let currentTime = new Date().getTime();
+        currentTime = parseFloat(currentTime / 1000).toFixed(0);
+
+        let encryptToken = this.encryptPassword(token, (token + currentTime));
+
+        return [encryptToken, currentTime];
+    }
+
+    /**
+     * 新增管理员
+     *
+     * @param {Object} data
+     * @return {Promise}
+     */
+    async createManager(data) {
+        if (Object.keys(data).length <= 0) {
+            throw '数据格式错误';
+        }
+        let result = await this.db.create(data);
+
+        return result;
+    }
+
+}
+
+export default ManagerModel;

+ 64 - 0
modules/users/models/schemas/manager.js

@@ -0,0 +1,64 @@
+/**
+ * 后台管理用户数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/7/20
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'manager';
+let modelSchema = {
+    // 用户名
+    username: {
+        type: String,
+        index: true
+    },
+    // 密码
+    password: String,
+    // token 10位随机字符串(用于加密)
+    token: String,
+    // 最后登录时间
+    last_login: {
+        type: Number,
+        default: 0
+    },
+    // 创建时间
+    create_time: {
+        type: Number,
+        default: 0
+    },
+    // 最后登录ip
+    login_ip: {
+        type: String,
+        default: ''
+    },
+    // 登录用户电脑信息
+    login_info: {
+        type: String,
+        default: ''
+    },
+    // 是否可以登录 0为禁止登录
+    can_login: {
+        type: Number,
+        default: 1
+    },
+    // 权限
+    permission: {
+        type: String,
+        default: ''
+    },
+    // 办事处
+    office: {
+        type: Number,
+        default: 0
+    },
+    // 超级管理员 1为超级管理员
+    super_admin: {
+        type: Number,
+        default: 0
+    }
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 49 - 0
modules/users/models/schemas/user.js

@@ -0,0 +1,49 @@
+/**
+ * 用户数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/7/20
+ * @version
+ */
+
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'users';
+let modelSchema = {
+    // 用户名
+    username: String,
+    // 电子邮件
+    email: String,
+    // 手机号码
+    mobile: String,
+    // 真实姓名
+    real_name: String,
+    // 公司
+    company: String,
+    // 省份
+    province: Number,
+    // 公司类型
+    company_type: {
+        type: Number,
+        default: -1
+    },
+    // 公司规模
+    company_scale: {
+        type: Number,
+        default: -1
+    },
+    // 最后登录时间
+    last_login: {
+        type: Number,
+        default: 0
+    },
+    // 创建时间
+    create_time: {
+        type: Number,
+        default: 0
+    },
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};
+

+ 66 - 0
modules/users/models/user_model.js

@@ -0,0 +1,66 @@
+/**
+ * 前台用户相关数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/6/12
+ * @version
+ */
+import BaseModel from "../../common/base/base_model";
+import UserSchema from "./schemas/user";
+
+class UserModel extends BaseModel {
+
+    /**
+     * 企业所在地区
+     *
+     * @var {object}
+     */
+    province = ['广东省', '北京市'];
+
+    /**
+     * 企业类型
+     *
+     * @var
+     */
+    companyType = ['设计', '施工'];
+
+    /**
+     * 企业规模
+     *
+     * @var
+     */
+    companyScale = ['1-20', '20-50', '50-100', '100+'];
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = UserSchema;
+        parent.init();
+    }
+
+    /**
+     * 获取列表
+     *
+     * @param {object} condition
+     * @param {number} page
+     * @param {Number} pageSize
+     * @return {promise}
+     */
+    async getList(condition = null, page = 1, pageSize = 30) {
+        page = parseInt(page);
+        page = page <= 1 ? 1 : page;
+        let option = {pageSize: pageSize, offset: parseInt((page - 1) * pageSize)};
+
+        let userList = await this.db.find(condition, null, option);
+        userList = userList.length > 0 ? userList : [];
+
+        return userList;
+    }
+
+}
+
+export default UserModel;

+ 0 - 49
modules/users/models/users.js

@@ -1,49 +0,0 @@
-//*/
-var mongoose = require("mongoose");
-
-var dbm = require("../../../config/db/db_manager");
-var umDB = dbm.getCfgConnection("usersManages");
-var usersSchema = new mongoose.Schema({ account: String, pw: String, name: String });
-var usersModel = umDB.model('users', usersSchema);
-/*/
-var umDB = require('./umDB');
-var usersSchema = new umDB.mongoose.Schema({ account: String, pw: String, name: String });
-var usersModel = umDB.mongoose.model('users', usersSchema);
-//*/
-
-var usersData = function(){};
-
-usersData.prototype.findUser = function(account, pw, controllerFun){
-    usersModel.find({"account": account, "pw": pw}, function(err, data){
-        if(data.length){
-            controllerFun(0, data[0]);
-        }
-        else{
-            controllerFun('用户名或密码错误!', 0);
-        }
-    })
-};
-
-usersData.prototype.checkAccount = function(account, controllerFun){
-    usersModel.find({"account": account}, function(err, data){
-        if(data.length){
-            controllerFun(data[0]);
-        }
-        else{
-            controllerFun(0);
-        }
-    })
-};
-
-usersData.prototype.addUser = function(account, pw, name, controllerFun){
-    var user = new usersModel({account: account, pw: pw, name: name});
-    user.save(function (err) {
-        if (err) {
-            controllerFun(err);
-        } else {
-            controllerFun(0);
-        }
-    });
-};
-
-module.exports = new usersData();

+ 20 - 0
modules/users/routes/dashboard_route.js

@@ -0,0 +1,20 @@
+/**
+ * 控制面板路由分发
+ *
+ * @author CaiAoLin
+ * @date 2017/6/2
+ * @version
+ */
+import Express from "express";
+import DashboardController from "../controllers/dashboard_controller"
+
+const router = Express.Router();
+let dashboardController = new DashboardController();
+
+module.exports =function (app) {
+
+    // action定义区域
+    router.get('/', dashboardController.auth, dashboardController.init, dashboardController.index);
+
+    app.use("/dashboard", router);
+};

+ 23 - 0
modules/users/routes/login_route.js

@@ -0,0 +1,23 @@
+/**
+ * 登录相关路由
+ *
+ * @author CaiAoLin
+ * @date 2017/6/1
+ * @version
+ */
+import Express from "express";
+import LoginController from "../controllers/login_controller";
+
+const router = Express.Router();
+const loginController = new LoginController();
+
+module.exports =function (app) {
+
+    // action定义区域
+    router.get('/', loginController.index);
+    router.post('/login', loginController.login);
+    router.get('/logout', loginController.logout);
+
+    app.use("/login", router);
+    app.use("/", router);
+};

+ 29 - 0
modules/users/routes/manager_route.js

@@ -0,0 +1,29 @@
+/**
+ * 账号管理路由分发
+ *
+ * @author CaiAoLin
+ * @date 2017/6/2
+ * @version
+ */
+import Express from "express";
+import ManagerController from "../controllers/manager_controller";
+
+const router = Express.Router();
+const managerController = new ManagerController();
+
+module.exports =function (app) {
+
+    // 管理员列表action
+    router.get('/', managerController.auth, managerController.init, managerController.index);
+    // 修改管理员
+    router.post('/modify/:id', managerController.auth, managerController.init, managerController.modify);
+    // 删除管理员
+    router.get('/delete/:id',managerController.auth,  managerController.init, managerController.delete);
+    // 超级管理员action
+    router.get('/admin', managerController.auth, managerController.init, managerController.admin);
+    router.post('/admin', managerController.auth, managerController.init, managerController.adminSubmit);
+
+    router.get('/create', managerController.create);
+
+    app.use("/manager", router);
+};

+ 19 - 0
modules/users/routes/notify_route.js

@@ -0,0 +1,19 @@
+/**
+ * 通知相关路由
+ *
+ * @author CaiAoLin
+ * @date 2017/6/7
+ * @version
+ */
+import Express from "express";
+import NotifyController from "../controllers/notify_controller";
+
+const router = Express.Router();
+const notifyController = new NotifyController();
+
+module.exports =function (app) {
+    // action定义区域
+    router.get('/', notifyController.auth, notifyController.init, notifyController.index);
+
+    app.use("/notify", router);
+};

+ 19 - 0
modules/users/routes/tool_route.js

@@ -0,0 +1,19 @@
+/**
+ * 工具路由
+ *
+ * @author CaiAoLin
+ * @date 2017/7/21
+ * @version
+ */
+import Express from "express";
+import ToolController from "../controllers/tool_controller";
+
+const router = Express.Router();
+const toolController = new ToolController();
+
+module.exports =function (app) {
+    // action定义区域
+    router.get('/', toolController.auth, toolController.init, toolController.index);
+
+    app.use("/tool", router);
+};

+ 19 - 0
modules/users/routes/user_route.js

@@ -0,0 +1,19 @@
+/**
+ * 用户管理相关路由
+ *
+ * @author CaiAoLin
+ * @date 2017/6/7
+ * @version
+ */
+import Express from "express";
+import UserController from "../controllers/user_controller";
+
+const router = Express.Router();
+const userController = new UserController();
+
+module.exports =function (app) {
+    // action定义区域
+    router.get('/', userController.auth, userController.init, userController.lastRegister);
+
+    app.use("/user", router);
+};

+ 0 - 37
modules/users/routes/users_route.js

@@ -1,37 +0,0 @@
-var express = require('express');
-var path = require('path');
-var router = express.Router();
-var uc = require('../controllers/users_controller');
-
-var htmlPath = path.join(__dirname,'../../../','web/users/');
-
-router.get('/', function(req, res) {
-    if(!req.session.userAccount){
-        res.redirect('/login');
-    }
-    else{
-        res.redirect('/pm');
-    }
-});
-
-router.get('/login', function(req, res) {
-  res.render('users/login', {});
-});
-
-router.post('/login', uc.userLogin);
-
-router.get('/reg', function(req, res, next) {
-  res.render('reg',{});
-});
-
-router.post('/reg', uc.userReg);
-
-router.get("/logout",function(req,res){
-    delete req.session.userID;
-    delete req.session.userAccount;
-    delete req.session.userEmail;
-    delete req.session.userMobile;
-    res.redirect("/");
-});
-
-module.exports = router;

+ 17 - 84
operation.js

@@ -5,10 +5,13 @@ config.setToQaDb();
 //config.setupCache();
 //config.setupCache();
 let cfgCacheUtil = require("./config/cacheCfg");
 let cfgCacheUtil = require("./config/cacheCfg");
 cfgCacheUtil.setupDftCache();
 cfgCacheUtil.setupDftCache();
+let dbm = require("./config/db/db_manager");
 
 
 let path = require('path');
 let path = require('path');
 let session = require('express-session');
 let session = require('express-session');
 let DBStore = require('connect-mongo')(session);
 let DBStore = require('connect-mongo')(session);
+let fileUtils = require("./modules/common/fileUtils");
+let partials = require("express-partials");
 
 
 let URL = require('url');
 let URL = require('url');
 let fs = require('fs');
 let fs = require('fs');
@@ -16,11 +19,18 @@ let fs = require('fs');
 let app = express();
 let app = express();
 let _rootDir = __dirname;
 let _rootDir = __dirname;
 
 
+dbm.connect();
+
 app.use(express.static(_rootDir));
 app.use(express.static(_rootDir));
 
 
 app.set('views', path.join(__dirname, 'web'));
 app.set('views', path.join(__dirname, 'web'));
 app.engine('.html', require('ejs').__express);
 app.engine('.html', require('ejs').__express);
 app.set('view engine', 'html');
 app.set('view engine', 'html');
+app.set('view options', {
+    // defaultLayout: 'users/views/layout/layout'
+    defaultLayout: false
+});
+app.use(partials());
 
 
 let bodyParser = require('body-parser');
 let bodyParser = require('body-parser');
 app.use(bodyParser.urlencoded({extended: false}));
 app.use(bodyParser.urlencoded({extended: false}));
@@ -31,6 +41,7 @@ app.use(session({
     secret: 'session users secret',
     secret: 'session users secret',
     cookie: {maxAge: 1000*60*30},
     cookie: {maxAge: 1000*60*30},
     resave: false,
     resave: false,
+    rolling: true,
     saveUninitialized: true
     saveUninitialized: true
     //*
     //*
     ,store: new DBStore({
     ,store: new DBStore({
@@ -40,8 +51,8 @@ app.use(session({
 }));
 }));
 
 
 app.use(function (req, res, next) {
 app.use(function (req, res, next) {
-    let url = req.originalUrl, referer;
-    if (!/^\/login/.test(req.originalUrl) && !req.session.userAccount) {
+    let referer = '';
+    if (!/^\/login/.test(req.originalUrl) && !req.session.managerData) {
         if (/\/api/.test(req.originalUrl)) {
         if (/\/api/.test(req.originalUrl)) {
             referer = URL.parse(req.headers.referer);
             referer = URL.parse(req.headers.referer);
             return res.redirect('/login' + '?referer=' + referer.path);
             return res.redirect('/login' + '?referer=' + referer.path);
@@ -52,88 +63,10 @@ app.use(function (req, res, next) {
     next();
     next();
 });
 });
 
 
-app.use('/', require('./modules/users/routes/users_route'));
-
-let rpt_Router = require("./modules/reports/routes/report_router");
-app.get('/report',  function(req, res) {
-    if (!req.session.userAccount) {
-        res.redirect('/login');
-    }
-    else {
-        res.render('maintain/report/rpt_test.html',
-            {userAccount: req.session.userAccount,
-                userID: req.session.userID});
-    }
-});
-app.use("/report_api", rpt_Router);
-
-let rptTpl_Router = require("./modules/reports/routes/rpt_tpl_router");
-app.get('/rpt_tpl',  function(req, res) {
-    if (!req.session.userAccount) {
-        res.redirect('/login');
-    }
-    else {
-        res.render('maintain/report/rpt_tpl_main.html',
-            {userAccount: req.session.userAccount,
-                userID: req.session.userID});
-    }
-});
-app.use("/report_tpl_api", rptTpl_Router);
-
-let rationRepository_Router = require("./modules/ration_repository/routes/ration_rep_routes");
-app.get('/rationRepository/main', function(req, res) {
-    res.render('maintain/ration_repository/main.html',
-        {
-            userAccount: req.session.userAccount,
-            userID: req.session.userID
-        });
-});
-app.get('/rationRepository/ration', function(req, res) {
-    res.render('maintain/ration_repository/dinge.html',
-        {
-            userAccount: req.session.userAccount,
-            userID: req.session.userID
-        });
-});
-app.get('/rationRepository/lmm', function(req, res) {
-    res.render('maintain/ration_repository/gongliao.html',
-        {
-            userAccount: req.session.userAccount,
-            userID: req.session.userID
-        });
-});
-
-app.get('/rationRepository/coeList', function(req, res) {
-    res.render('maintain/ration_repository/fuzhu.html',
-        {
-            userAccount: req.session.userAccount,
-            userID: req.session.userID
-        });
-});
-
-app.use("/rationRepository/api",rationRepository_Router);
-
-app.get("/stdBillsmain", function(req, res){
-    if(!req.session.userAccount){
-        res.redirect('/login');
-    }
-    else {
-        res.render("maintain/bills_lib/html/main.html",
-            {userAccount: req.session.userAccount,
-                userID: req.session.userID});
-    }
-});
-app.get("/stdBills", function(req, res){
-    res.render("maintain/bills_lib/html/qingdan.html");
-});
-app.get('/stdJobs', function(req, res){
-    res.render('maintain/bills_lib/html/neirong.html');
-});
-app.get('/stdItems', function(req, res){
-    res.render('maintain/bills_lib/html/tezheng.html');
-});
-let billsLibRouter = require("./modules/bills_lib/routes/bills_lib_routes");
-app.use("/stdBillsEditor", billsLibRouter);
+//加载路由文件
+fileUtils.getGlobbedFiles('./modules/**/routes/*.js').forEach(function(modelPath) {
+    require(path.resolve(modelPath))(app);
+})
 
 
 app.use(function(req, res, next) {
 app.use(function(req, res, next) {
     res.status(404).send('404 Error');
     res.status(404).send('404 Error');

+ 6 - 1
package.json

@@ -4,7 +4,10 @@
   "description": "Smart Soft - Construct Cost",
   "description": "Smart Soft - Construct Cost",
   "devDependencies": {
   "devDependencies": {
     "body-parser": "^1.13.2",
     "body-parser": "^1.13.2",
+    "babel-preset-es2015": "^6.24.1",
+    "babel-preset-stage-2": "^6.24.1",
     "express": "^4.13.1",
     "express": "^4.13.1",
+    "express-partials": "^0.3.0",
     "mongoose": "^4.8.5",
     "mongoose": "^4.8.5",
     "async": "^2.1.5",
     "async": "^2.1.5",
     "connect-mongo": "^1.3.2",
     "connect-mongo": "^1.3.2",
@@ -12,8 +15,10 @@
     "debug": "~2.6.0",
     "debug": "~2.6.0",
     "ejs": "~2.5.5",
     "ejs": "~2.5.5",
     "express-session": "^1.15.1",
     "express-session": "^1.15.1",
+    "moment": "^2.18.1",
     "request": "^2.79.0",
     "request": "^2.79.0",
-    "tape": "^4.6.3"
+    "tape": "^4.6.3",
+    "glob": "~4.0.5"
   },
   },
   "dependencies": {
   "dependencies": {
     "bluebird": "^3.5.0",
     "bluebird": "^3.5.0",

+ 1 - 1
public/rpt_tpl_def.js

@@ -5,7 +5,7 @@
 const fs = require('fs');
 const fs = require('fs');
 var rptTplDef = null;
 var rptTplDef = null;
 
 
-getTreeNodeUtil = function() {
+var getTreeNodeUtil = function() {
     if (!(rptTplDef)) {
     if (!(rptTplDef)) {
         var data = fs.readFileSync(__dirname + '/web/rpt_tpl_def.js', 'utf8', 'r');
         var data = fs.readFileSync(__dirname + '/web/rpt_tpl_def.js', 'utf8', 'r');
         eval(data + ' ; rptTplDef = RT;');
         eval(data + ' ; rptTplDef = RT;');

+ 31 - 33
public/web/id_tree.js

@@ -73,10 +73,8 @@ var idTree = {
                 var next = (pre && iIndex + count - 1 < children.length) ? children[iIndex + count] : null;
                 var next = (pre && iIndex + count - 1 < children.length) ? children[iIndex + count] : null;
                 if (pre) {
                 if (pre) {
                     pre.setNextSibling(next);
                     pre.setNextSibling(next);
-                    //pre.nextSibling = next;
-                }
-                if (next) {
-                    next.preSibling = pre;
+                } else if (next) {
+                    next.preSibling = null;
                 }
                 }
                 if (arguments.length === 4) {
                 if (arguments.length === 4) {
                     children.splice(iIndex, count);
                     children.splice(iIndex, count);
@@ -98,10 +96,8 @@ var idTree = {
                 }
                 }
                 if (pre) {
                 if (pre) {
                     pre.setNextSibling(nodes[0]);
                     pre.setNextSibling(nodes[0]);
-                }
-                nodes[0].preSibling = pre;
-                if (next) {
-                    next.preSibling = nodes[nodes.length - 1];
+                } else {
+                    nodes[0].preSibling = null;
                 }
                 }
                 nodes[nodes.length - 1].setNextSibling(next);
                 nodes[nodes.length - 1].setNextSibling(next);
                 for (i = 0; i < nodes.length; i++) {
                 for (i = 0; i < nodes.length; i++) {
@@ -170,6 +166,9 @@ var idTree = {
         };
         };
         Node.prototype.setNextSibling = function (nextSibling) {
         Node.prototype.setNextSibling = function (nextSibling) {
             this.nextSibling = nextSibling;
             this.nextSibling = nextSibling;
+            if (nextSibling) {
+                nextSibling.preSibling = this;
+            }
             if (this.tree.setting.autoUpdate) {
             if (this.tree.setting.autoUpdate) {
                 this.data[this.tree.setting.nid] = this.getNextSiblingID();
                 this.data[this.tree.setting.nid] = this.getNextSiblingID();
             }
             }
@@ -212,8 +211,8 @@ var idTree = {
             }
             }
             return iCount;
             return iCount;
             /*return (node.children.length === 0) ? 0 : node.children.reduce(function (x, y) {
             /*return (node.children.length === 0) ? 0 : node.children.reduce(function (x, y) {
-                return x.posterityCount() + y.posterityCount();
-            }) + node.children.count;*/
+             return x.posterityCount() + y.posterityCount();
+             }) + node.children.count;*/
         };
         };
 
 
         Node.prototype.setExpanded = function (expanded) {
         Node.prototype.setExpanded = function (expanded) {
@@ -227,8 +226,8 @@ var idTree = {
             setNodesVisible(this.children, expanded);
             setNodesVisible(this.children, expanded);
         };
         };
         /*Node.prototype.vis = function () {
         /*Node.prototype.vis = function () {
-            return this.parent ? this.parent.vis() && this.parent.expanded() : true;
-        };*/
+         return this.parent ? this.parent.vis() && this.parent.expanded() : true;
+         };*/
         Node.prototype.serialNo = function () {
         Node.prototype.serialNo = function () {
             return this.tree.items.indexOf(this);
             return this.tree.items.indexOf(this);
         };
         };
@@ -250,7 +249,7 @@ var idTree = {
             if (nextSibling) {
             if (nextSibling) {
                 nextSibling.preSibling = preSibling;
                 nextSibling.preSibling = preSibling;
             }
             }
-            this.children.splice(this.children.re)
+            this.children.splice(node.siblingIndex, 1);
         };
         };
 
 
         Node.prototype.canUpLevel = function () {
         Node.prototype.canUpLevel = function () {
@@ -336,10 +335,10 @@ var idTree = {
             if (this.canUpMove()) {
             if (this.canUpMove()) {
                 if (orgPre.preSibling) {
                 if (orgPre.preSibling) {
                     orgPre.preSibling.setNextSibling(this);
                     orgPre.preSibling.setNextSibling(this);
+                } else {
+                    this.preSibling = null;
                 }
                 }
                 orgPre.setNextSibling(this.nextSibling);
                 orgPre.setNextSibling(this.nextSibling);
-                this.preSibling = orgPre.preSibling;
-                orgPre.preSibling = this;
                 this.setNextSibling(orgPre);
                 this.setNextSibling(orgPre);
                 belongArray.splice(iIndex, 1);
                 belongArray.splice(iIndex, 1);
                 belongArray.splice(iIndex - 1, 0, this);
                 belongArray.splice(iIndex - 1, 0, this);
@@ -369,11 +368,11 @@ var idTree = {
             if (this.canDownMove()) {
             if (this.canDownMove()) {
                 if (this.preSibling) {
                 if (this.preSibling) {
                     this.preSibling.setNextSibling(orgNext);
                     this.preSibling.setNextSibling(orgNext);
+                } else if (orgNext) {
+                    orgNext.preSibling = null;
                 }
                 }
-                orgNext.preSibling = this.preSibling;
                 this.setNextSibling(orgNext.nextSibling);
                 this.setNextSibling(orgNext.nextSibling);
                 orgNext.setNextSibling(this);
                 orgNext.setNextSibling(this);
-                this.preSibling = orgNext;
                 belongArray.splice(iIndex, 1);
                 belongArray.splice(iIndex, 1);
                 belongArray.splice(iIndex + 1, 0, this);
                 belongArray.splice(iIndex + 1, 0, this);
                 tools.sortTreeItems(this.tree);
                 tools.sortTreeItems(this.tree);
@@ -433,10 +432,10 @@ var idTree = {
                 }
                 }
             }
             }
             /*if (this.maxID >= this.rangeNodeID() || this.rangeNodeID === -1) {
             /*if (this.maxID >= this.rangeNodeID() || this.rangeNodeID === -1) {
-                return -1;
-            } else {
-                return this.maxNodeID() + 1;
-            }*/
+             return -1;
+             } else {
+             return this.maxNodeID() + 1;
+             }*/
         };
         };
 
 
         Tree.prototype.clearNodes = function () {
         Tree.prototype.clearNodes = function () {
@@ -571,9 +570,8 @@ var idTree = {
                 //delete this.nodes[this.prefix + node.getID()];
                 //delete this.nodes[this.prefix + node.getID()];
                 if (node.preSibling) {
                 if (node.preSibling) {
                     node.preSibling.setNextSibling(node.nextSibling);
                     node.preSibling.setNextSibling(node.nextSibling);
-                }
-                if (node.nextSibling) {
-                    node.nextSibling.preSibling = node.preSibling;
+                } else if (node.nextSibling) {
+                    node.nextSibling.preSibling = null;
                 }
                 }
                 if (node.parent) {
                 if (node.parent) {
                     node.parent.children.splice(node.siblingIndex(), 1);
                     node.parent.children.splice(node.siblingIndex(), 1);
@@ -605,15 +603,15 @@ var idTree = {
         };
         };
 
 
         /*Tree.prototype.editedData = function (field, id, newText) {
         /*Tree.prototype.editedData = function (field, id, newText) {
-            var node = this.findNode(id), result = {allow: false, nodes: []};
-            if (this.event[this.eventType.editedData]) {
-                return this.event[this.eventType.editedData](field, node.data);
-            } else {
-                node.data[field] = newText;
-                result.allow = true;
-                return result;
-            }
-        };*/
+         var node = this.findNode(id), result = {allow: false, nodes: []};
+         if (this.event[this.eventType.editedData]) {
+         return this.event[this.eventType.editedData](field, node.data);
+         } else {
+         node.data[field] = newText;
+         result.allow = true;
+         return result;
+         }
+         };*/
 
 
         Tree.prototype.bind = function (eventName, eventFun) {
         Tree.prototype.bind = function (eventName, eventFun) {
             this.event[eventName] = eventFun;
             this.event[eventName] = eventFun;

+ 74 - 3
public/web/sheet/sheet_common.js

@@ -87,10 +87,11 @@ var sheetCommonObj = {
             area.vAlign(GC.Spread.Sheets.VerticalAlign.center);
             area.vAlign(GC.Spread.Sheets.VerticalAlign.center);
         }
         }
     },
     },
-    showData: function(sheet, setting, data) {
+    showData: function(sheet, setting, data, distTypeTree) {
         var me = this, ch = GC.Spread.Sheets.SheetArea.viewport;
         var me = this, ch = GC.Spread.Sheets.SheetArea.viewport;
         sheet.suspendPaint();
         sheet.suspendPaint();
         sheet.suspendEvent();
         sheet.suspendEvent();
+        sheet.setRowCount(data.length + 5);
         for (var col = 0; col < setting.header.length; col++) {
         for (var col = 0; col < setting.header.length; col++) {
             var hAlign = "left", vAlign = "center";
             var hAlign = "left", vAlign = "center";
             if (setting.header[col].hAlign) {
             if (setting.header[col].hAlign) {
@@ -108,7 +109,13 @@ var sheetCommonObj = {
             }
             }
             for (var row = 0; row < data.length; row++) {
             for (var row = 0; row < data.length; row++) {
                 //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);
                 //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);
-                sheet.setValue(row, col, data[row][setting.header[col].dataCode], ch);
+                if(setting.header[col].dataCode === 'gljType' && data[row].gljType){
+                    let distTypeVal =  distTypeTree.distTypes[distTypeTree.prefix + data[row].gljType].data.fullName;
+                    sheet.setValue(row, col, distTypeVal, ch);
+                }
+                else {
+                    sheet.setValue(row, col, data[row][setting.header[col].dataCode], ch);
+                }
             }
             }
         }
         }
         sheet.resumeEvent();
         sheet.resumeEvent();
@@ -141,7 +148,58 @@ var sheetCommonObj = {
         }
         }
         return rst;
         return rst;
     },
     },
-    combineRowData: function(sheet, setting, row) {
+    combineRowData: function(sheet, setting, row, repositoryGljObj) {
+        var rst = {};
+        let comboBoxCellType = sheet.getCellType(row, 5);
+        let items = comboBoxCellType.items();
+        for (var col = 0; col < setting.header.length; col++) {
+            if(setting.header[col].dataCode === 'gljType'){
+                items.forEach(function(item){
+                    if(sheet.getValue(row, col) === item.text){
+                        rst[setting.header[col].dataCode] = item.value;
+                        rst.shortName = repositoryGljObj.distTypeTree.distTypes[repositoryGljObj.distTypeTree.prefix + item.value].data.shortName;
+                    }
+                });
+            }
+           else if (setting.header[col].dataCode === 'code'){
+                if(repositoryGljObj){
+                    let gljList = repositoryGljObj.gljList,
+                        orgCode = repositoryGljObj.orgCode,
+                        isExist = false;
+                        for(let i=0; i< gljList.length; i++){
+                            if(gljList[i].code === sheet.getValue(row, col) && sheet.getValue(row, col)!== orgCode){
+                                $('#alertText').text("输入的编号已存在,请重新输入!");
+                                $('#codeAlertBtn').click();
+                                sheet.options.isProtected = true;
+                                $('#codAleConfBtn').click(function () {
+                                    sheet.options.isProtected = false;
+                                    sheet.setValue(row, 0, orgCode);
+                                    sheet.setActiveCell(row, 0);
+                                });
+                                $('#codAleClose').click(function () {
+                                    sheet.options.isProtected = false;
+                                    sheet.setValue(row, 0, orgCode);
+                                    sheet.setActiveCell(row, 0);
+                                });
+                                // sheet.setValue(row, col, orgCode);
+                                isExist = true
+                            }
+                        }
+                    if(!isExist){
+                        rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+                    }
+                }
+                else{
+                    rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+                }
+            }
+            else{
+                rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+            }
+        }
+        return rst;
+    },
+    combineRationRowData: function(sheet, setting, row) {
         var rst = {};
         var rst = {};
         for (var col = 0; col < setting.header.length; col++) {
         for (var col = 0; col < setting.header.length; col++) {
             rst[setting.header[col].dataCode] = sheet.getValue(row, col);
             rst[setting.header[col].dataCode] = sheet.getValue(row, col);
@@ -154,6 +212,19 @@ var sheetCommonObj = {
     unShieldAllCells: function(sheet) {
     unShieldAllCells: function(sheet) {
         sheet.options.isProtected = false;
         sheet.options.isProtected = false;
     },
     },
+    lockCodeCells: function (sheet, rowCount) {
+        let sheetRowCount = sheet.getRowCount();
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        let style = new GC.Spread.Sheets.Style();
+        style.locked = true;
+        sheet.setStyle(-1, 0, style);
+        for(let i =rowCount -1; i<sheetRowCount; i++){
+            sheet.setStyle(i, -1, style);
+        }
+        sheet.options.isProtected = true;
+    },
     lockCells: function(sheet, setting){
     lockCells: function(sheet, setting){
         if (setting && setting.view.lockColumns && setting.view.lockColumns.length > 0) {
         if (setting && setting.view.lockColumns && setting.view.lockColumns.length > 0) {
             sheet.options.isProtected = true;
             sheet.options.isProtected = true;

+ 2 - 1
web/maintain/bills_lib/html/main.html

@@ -130,7 +130,8 @@
 </script>
 </script>
 <script>
 <script>
     let userId = '<%= userID %>';
     let userId = '<%= userID %>';
-    let userAccount = '<%= userAccount %>';
+    console.log(`userID: ${userId}`);
+    //let userAccount = '<%= userAccount %>';
     mainAjax.getStdBillsLib(userId);
     mainAjax.getStdBillsLib(userId);
     $(document).ready(function(){
     $(document).ready(function(){
         //main 增删改
         //main 增删改

+ 19 - 11
web/maintain/bills_lib/html/neirong.html

@@ -11,7 +11,7 @@
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <!--spread-->
     <!--spread-->
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013white.10.0.1.css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css">
     <!--zTree-->
     <!--zTree-->
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
 </head>
 </head>
@@ -196,7 +196,7 @@
             buildAllJobs(spreadAllJobs, totalJobsSetting);
             buildAllJobs(spreadAllJobs, totalJobsSetting);
         });
         });
         function buildAllJobs(spreadAllJobs, setting){
         function buildAllJobs(spreadAllJobs, setting){
-            setSheet.initSheet(spreadAllJobs, setting);
+            setSheet.initSheet(spreadAllJobs, setting, false);
             myKey.downKey(spreadAllJobs);
             myKey.downKey(spreadAllJobs);
             myKey.enterKey(spreadAllJobs);
             myKey.enterKey(spreadAllJobs);
             TREE_SHEET_HELPER.loadSheetHeader(setting, spreadAllJobs.getActiveSheet());
             TREE_SHEET_HELPER.loadSheetHeader(setting, spreadAllJobs.getActiveSheet());
@@ -261,37 +261,45 @@
                         }
                         }
                     }
                     }
                 }
                 }
-                for(let i=0; i< pasteDatas.length; i++){
+                let uniqPasteDatas = tools.uniqObjArr(pasteDatas);
+                tools.resetRowIdx(uniqPasteDatas, orgRow);
+                for(let i=0; i< uniqPasteDatas.length; i++){
                     let crossedData;
                     let crossedData;
                     let flag = true;
                     let flag = true;
                     sheetJobsDatas.forEach(function(orgData){
                     sheetJobsDatas.forEach(function(orgData){
-                        if(pasteDatas[i].rowIdx === orgData.rowIdx && pasteDatas[i].colIdx === orgData.colIdx){
+                        if(uniqPasteDatas[i].rowIdx === orgData.rowIdx && uniqPasteDatas[i].colIdx === orgData.colIdx){
                             flag = false;
                             flag = false;
                             crossedData = {
                             crossedData = {
                                 billsLibId: billsLibId,
                                 billsLibId: billsLibId,
-                                rowIdx: pasteDatas[i].rowIdx,
-                                colIdx: pasteDatas[i].colIdx,
-                                field: pasteDatas[i].field,
+                                rowIdx: uniqPasteDatas[i].rowIdx,
+                                colIdx: uniqPasteDatas[i].colIdx,
+                                field: uniqPasteDatas[i].field,
                                 orgId: orgData.id,
                                 orgId: orgData.id,
-                                data: pasteDatas[i].data,
+                                data: uniqPasteDatas[i].data,
                                 type: 'Update'
                                 type: 'Update'
                             }
                             }
                         }
                         }
                     });
                     });
                     if(flag){
                     if(flag){
-                        uncrossedDatas.push(pasteDatas[i]);
+                        uncrossedDatas.push(uniqPasteDatas[i]);
                     }
                     }
                     else{
                     else{
                         crossedDatas.push(crossedData);
                         crossedDatas.push(crossedData);
                     }
                     }
                 }
                 }
+                console.log(`uncD`);
+                console.log(uncrossedDatas);
+                console.log(`cD`);
+                console.log(crossedDatas);
                 let encapDatas = tools.encapTotalJobsDatas(sheet, totalJobs, uncrossedDatas, crossedDatas);
                 let encapDatas = tools.encapTotalJobsDatas(sheet, totalJobs, uncrossedDatas, crossedDatas);
-                if(encapDatas.updateDatas.length > 0 || encapDatas.createDatas.length > 0){
+                console.log(`encapD`);
+                console.log(encapDatas);
+                if(encapDatas.updateDatas.length > 0 || encapDatas.createDatas.length >0){
                     jobsAjax.pasteJobs(encapDatas, function(datas){
                     jobsAjax.pasteJobs(encapDatas, function(datas){
                         pasteController.pasteJobsFront(sheet, totalJobs,datas);
                         pasteController.pasteJobsFront(sheet, totalJobs,datas);
                     });
                     });
                 }
                 }
-                if(uncrossedDatas.length > 0 || crossedDatas.length > 0) {
+                else{
                     tools.reshowData(sheet, totalJobs.jobsArr, totalJobsSetting, true);
                     tools.reshowData(sheet, totalJobs.jobsArr, totalJobsSetting, true);
                 }
                 }
             });
             });

+ 118 - 46
web/maintain/bills_lib/html/qingdan.html

@@ -10,7 +10,7 @@
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <!--spread-->
     <!--spread-->
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013white.10.0.1.css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css">
 </head>
 </head>
 
 
 <body>
 <body>
@@ -237,6 +237,7 @@
     let billsLibId = getQueryString("billsLibId");
     let billsLibId = getQueryString("billsLibId");
     let sheetDatas;
     let sheetDatas;
     let sheetItemsDatas;
     let sheetItemsDatas;
+    let sheetBillsDatas;
     tools.redirect(billsLibId, 'stdBillsmain');
     tools.redirect(billsLibId, 'stdBillsmain');
     let jobsSpread = new GC.Spread.Sheets.Workbook($("#spreadJobs")[0], {sheetCount: 1});
     let jobsSpread = new GC.Spread.Sheets.Workbook($("#spreadJobs")[0], {sheetCount: 1});
     let itemsSpread = new GC.Spread.Sheets.Workbook($("#spreadItems")[0], {sheetCount: 1});
     let itemsSpread = new GC.Spread.Sheets.Workbook($("#spreadItems")[0], {sheetCount: 1});
@@ -256,39 +257,63 @@
     });
     });
 
 
     function nodeOpration(controller, totalJobs, totalItems){
     function nodeOpration(controller, totalJobs, totalItems){
-        dbController.editData(controller, controller.sheet);
-        $('#insert').click(function(){
-            dbController.insert(controller);
-            tools.clearData(jobsSpread.getActiveSheet());
-            tools.clearData(itemsSpread.getActiveSheet());
+        let btnInsert = $('#insert');
+        let btnDelete = $('#delete');
+        let btnUpLevel = $('#upLevel');
+        let btnDownLevel = $('#downLevel');
+        let btnUpMove = $('#upMove');
+        let btnDownMove = $('#downMove');
+        dbController.editData(controller);
+        btnInsert.click(function(){
+            if(!btnInsert.attr('focusOnBills')){
+                dbController.insert(controller, btnInsert);
+                tools.clearData(jobsSpread.getActiveSheet());
+                tools.clearData(itemsSpread.getActiveSheet());
+            }
         });
         });
-        $('#delete').click(function(){
-            dbController.delete(controller, totalJobs, totalItems);
+        btnDelete.click(function(){
+            if(!btnDelete.attr('focusOnBills')){
+                dbController.delete(controller, btnDelete, totalJobs, totalItems);
+            }
+            //controller.delete();
         });
         });
-        $('#upLevel').click(function(){
-            dbController.upLevel(controller);
+        btnUpLevel.click(function(){
+            if(!btnUpLevel.attr('focusOnBills')){
+                dbController.upLevel(controller, btnUpLevel);
+            }
+            //controller.upLevel();
         });
         });
-        $('#downLevel').click(function(){
-           dbController.downLevel(controller);
+        btnDownLevel.click(function(){
+            if(!btnDownLevel.attr('focusOnBills')){
+                dbController.downLevel(controller, btnDownLevel);
+            }
+            //controller.downLevel();
         });
         });
-        $('#upMove').click(function(){
-            dbController.upMove(controller);
+        btnUpMove.click(function(){
+            if(!btnUpMove.attr('focusOnBills')){
+                dbController.upMove(controller, btnUpMove);
+            }
+            if(btnUpMove.attr('focusOnJobs')){
+            }
+            //controller.upMove();
         });
         });
-        $('#downMove').click(function(){
-            dbController.downMove(controller);
+        btnDownMove.click(function(){
+            if(!btnDownMove.attr('focusOnBills')){
+                dbController.downMove(controller, btnDownMove);
+            }
+            //controller.downMove();
         });
         });
     }
     }
 
 
 
 
     function showBillsSheet(datas, jobsSheet, itemsSheet, setting) {
     function showBillsSheet(datas, jobsSheet, itemsSheet, setting) {
         let billsSpread = new GC.Spread.Sheets.Workbook($('#spreadBills')[0], {sheetCount: 1});
         let billsSpread = new GC.Spread.Sheets.Workbook($('#spreadBills')[0], {sheetCount: 1});
-        setSheet.initSheet(billsSpread, setting);
+        setSheet.initSheet(billsSpread, setting, true);
         myKey.delKey(billsSpread);
         myKey.delKey(billsSpread);
         billsTree.loadDatas(datas);
         billsTree.loadDatas(datas);
-        //粘贴事件
-        bindPasteBills(billsSpread.getActiveSheet(), setting);
         let controller = TREE_SHEET_CONTROLLER.createNew(billsTree.tree, billsSpread.getActiveSheet(), setting);
         let controller = TREE_SHEET_CONTROLLER.createNew(billsTree.tree, billsSpread.getActiveSheet(), setting);
         controller.showTreeData();
         controller.showTreeData();
+        setSheet.formatter(billsSpread.getActiveSheet());
         //setTagId
         //setTagId
         setTagID(controller, setting);
         setTagID(controller, setting);
         if (!controller.tree.selected && controller.tree.findNode(controller.sheet.getTag(0, 0, GC.Spread.Sheets.SheetArea.viewport))) {
         if (!controller.tree.selected && controller.tree.findNode(controller.sheet.getTag(0, 0, GC.Spread.Sheets.SheetArea.viewport))) {
@@ -297,6 +322,8 @@
         //刷新节点可进行操作的按钮
         //刷新节点可进行操作的按钮
         refreshBtn(controller);
         refreshBtn(controller);
         controller.setTreeSelected(controller.tree.findNode(controller.sheet.getTag(0, 0)));
         controller.setTreeSelected(controller.tree.findNode(controller.sheet.getTag(0, 0)));
+        //粘贴事件
+        bindPasteBills(controller, billsSpread.getActiveSheet(), setting);
         //补注内容改变
         //补注内容改变
         rechargeChange(controller);
         rechargeChange(controller);
         //jobs
         //jobs
@@ -328,10 +355,15 @@
     function refreshBtn(controller){
     function refreshBtn(controller){
         controller.bind('refreshBaseActn', function (tree) {
         controller.bind('refreshBaseActn', function (tree) {
             let showButton = function (show, btn) {
             let showButton = function (show, btn) {
+                tools.btnAction($('#insert'), 'focusOnBills');
                 if (show) {
                 if (show) {
-                    btn.show();
+                    //btn.show();
+                    btn.css("opacity", "");
+                    btn.removeClass("disabled");
                 } else {
                 } else {
-                    btn.hide();
+                    //btn.hide();
+                    btn.css("opacity", "0.2");
+                    btn.addClass("disabled");
                 }
                 }
             };
             };
             showButton(tree.selected && tree.selected.canUpLevel(), $('#upLevel'));
             showButton(tree.selected && tree.selected.canUpLevel(), $('#upLevel'));
@@ -352,6 +384,13 @@
     }
     }
 
 
     function jobOperation(controller, jobsSheet, callback){
     function jobOperation(controller, jobsSheet, callback){
+        //add
+        /*jobsSheet.bind(GC.Spread.Sheets.Events.CellClick, function (sender, args) {
+            controller.setTreeSelected(null);
+            tools.btnClose($('#insert'), 'focusOnBills');
+            tools.btnAction($('#upMove'), 'focusOnJobs');
+        });*/
+        //add
         mainAjax.getMaxNumber(billsLibId, 'jobs', function(result){
         mainAjax.getMaxNumber(billsLibId, 'jobs', function(result){
             if(result.length === 0){
             if(result.length === 0){
                 maxJobsNumber = 0;
                 maxJobsNumber = 0;
@@ -374,6 +413,12 @@
     }
     }
 
 
     function itemOperation(controller, itemsSheet, callback){
     function itemOperation(controller, itemsSheet, callback){
+        //add
+        /*itemsSheet.bind(GC.Spread.Sheets.Events.CellClick, function(sender, args){
+            controller.setTreeSelected(null);
+            tools.btnClose($('#insert'), 'focusOnBills');
+        });*/
+        //add
         mainAjax.getMaxNumber(billsLibId, 'items', function(result){
         mainAjax.getMaxNumber(billsLibId, 'items', function(result){
             if(result.length === 0){
             if(result.length === 0){
                 maxItemsNumber = 0;
                 maxItemsNumber = 0;
@@ -400,9 +445,9 @@
         if(controller.tree.selected){
         if(controller.tree.selected){
             let arr = controller.tree.selected[classify];
             let arr = controller.tree.selected[classify];
             let recharge = controller.tree.selected.data.recharge;
             let recharge = controller.tree.selected.data.recharge;
-            setSheet.setMaxRowCount(sheet, arr);
+            let prefix = classify === 'jobs' ? 'job' : 'item';
             if(arr.length > 0){
             if(arr.length > 0){
-                tools.reshowData(sheet, arr, setting, true);
+                tools.orderReshowData(sheet, arr, setting, prefix,true);
             }
             }
             if(recharge){
             if(recharge){
                 $('#exampleTextarea').val(recharge);
                 $('#exampleTextarea').val(recharge);
@@ -420,17 +465,19 @@
                     let jobs = controller.tree.selected.jobs;
                     let jobs = controller.tree.selected.jobs;
                     setSheet.setMaxRowCount(sheet, jobs);
                     setSheet.setMaxRowCount(sheet, jobs);
                     if(jobs.length > 0){
                     if(jobs.length > 0){
-                        tools.reshowData(sheet, jobs, setting, false);
+                        tools.orderReshowData(sheet, jobs, setting, 'job', true);
                         orgJobData = sheet.getValue(0, 0);
                         orgJobData = sheet.getValue(0, 0);
                     }
                     }
+                    sheetDatas = tools.getsheetDatas(sheet, 'jobs');
                 }
                 }
                 if(field === 'items'){
                 if(field === 'items'){
                     let items = controller.tree.selected.items;
                     let items = controller.tree.selected.items;
                     setSheet.setMaxRowCount(sheet, items);
                     setSheet.setMaxRowCount(sheet, items);
                     if(items.length > 0){
                     if(items.length > 0){
-                        tools.reshowData(sheet, items, setting, false);
+                        tools.orderReshowData(sheet, items, setting, 'item', true);
                         orgItemData = sheet.getValue(0, 0);
                         orgItemData = sheet.getValue(0, 0);
                     }
                     }
+                    sheetItemsDatas = tools.getsheetDatas(sheet, 'items');
                 }
                 }
             }
             }
             else {
             else {
@@ -440,31 +487,46 @@
         });
         });
     }
     }
 
 
-    function bindPasteBills(sheet, setting){
+    function bindPasteBills(controller, sheet, setting){
+        sheetBillsDatas = tools.getsheetDatas(sheet, 'bills', controller);
         sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, function(sender, args){
         sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, function(sender, args){
             let datas = [], field;
             let datas = [], field;
             let orgRow = args.cellRange.row, orgCol = args.cellRange.col, rowCount = args.cellRange.rowCount, colCount = args.cellRange.colCount;
             let orgRow = args.cellRange.row, orgCol = args.cellRange.col, rowCount = args.cellRange.rowCount, colCount = args.cellRange.colCount;
             let maxRow = orgRow + rowCount - 1, maxCol = orgCol + colCount -1;
             let maxRow = orgRow + rowCount - 1, maxCol = orgCol + colCount -1;
-            for(var i=orgRow; i<= maxRow; i++){
-                let id =  sheet.getTag(i, 0, GC.Spread.Sheets.SheetArea.viewport);
-                if(id){
-                    let pasteJson = {billsLibId: billsLibId, ID: id, code: null, name: null, unit: null, ruleText: null};
-                    let colLen = sheet.getColumnCount(GC.Spread.Sheets.SheetArea.viewport);
-                    for(var j=0; j<colLen; j++){
+            let markRow = orgRow, colLen = sheet.getColumnCount(GC.Spread.Sheets.SheetArea.viewport);
+            let validDatas = tools.getValidDatas(sheet, setting, args);
+            for(let i =orgRow, j=0; i<= maxRow; i++, j++){
+                let id = sheet.getTag(i, 0);
+                if(id && j< validDatas.length){
+                    validDatas[j].ID = id;
+                    for(let k =orgCol; k<= maxCol; k++){
                         setting.cols.forEach(function(col, colIdx){
                         setting.cols.forEach(function(col, colIdx){
-                            if(colIdx === j){
-                                field = col.data.field;
+                            if(colIdx === k){
+                                if(validDatas[j][col.data.field]){
+                                    sheet.setValue(i, k, validDatas[j][col.data.field]);
+                                    sheetBillsDatas.datasIdx['rowIdx'+ i][col.data.field] = validDatas[j][col.data.field];
+                                }
+                                else {
+                                    sheet.setValue(i, k, '');
+                                    sheetBillsDatas.datasIdx['rowIdx'+ i][col.data.field] = '';
+                                }
                             }
                             }
                         });
                         });
-                        pasteJson[field] = sheet.getValue(i, j);
                     }
                     }
-                    datas.push(pasteJson);
+                }
+                else if(i < controller.tree.items.length && j>= validDatas.length){
+                    //reshow orgDatas
+                    sheet.setValue(i, 0, sheetBillsDatas.datasIdx['rowIdx'+ i].code + '');
+                    sheet.setValue(i, 1, sheetBillsDatas.datasIdx['rowIdx'+ i].name);
+                    sheet.setValue(i, 2, sheetBillsDatas.datasIdx['rowIdx'+ i].unit);
+                    sheet.setValue(i, 3, sheetBillsDatas.datasIdx['rowIdx'+ i].ruleText);
                 }
                 }
                 else {
                 else {
                     sheet.clear(i, 0, 1, sheet.getColumnCount(), GC.Spread.Sheets.SheetArea.viewport,GC.Spread.Sheets.StorageType.data);
                     sheet.clear(i, 0, 1, sheet.getColumnCount(), GC.Spread.Sheets.SheetArea.viewport,GC.Spread.Sheets.StorageType.data);
                 }
                 }
             }
             }
-            billsAjax.pasteBills(datas);
+            billsAjax.pasteBills(billsLibId, validDatas);
+            setSheet.setMaxRowCount(sheet, sheetBillsDatas);
         });
         });
     }
     }
     function bindPasteRel(sheet, controller, totalJobs, setting){
     function bindPasteRel(sheet, controller, totalJobs, setting){
@@ -484,20 +546,24 @@
                     }
                     }
                 }
                 }
                 let uniqPasteArr = tools.uniqArr(pasteArr);
                 let uniqPasteArr = tools.uniqArr(pasteArr);
+                let serialNoUn = tools.getSerialNo(controller.tree.selected.jobs) - 1;
                 for(let i =orgRow, j=0; i<=uniqPasteArr.length+orgRow-1; i++, j++ ){
                 for(let i =orgRow, j=0; i<=uniqPasteArr.length+orgRow-1; i++, j++ ){
                     let flag = true;
                     let flag = true;
                     let crossedData;
                     let crossedData;
                     sheetDatas.forEach(function(rowData){
                     sheetDatas.forEach(function(rowData){
                         if(rowData.rowIdx === i && rowData.data !== uniqPasteArr[j]){
                         if(rowData.rowIdx === i && rowData.data !== uniqPasteArr[j]){
                             flag = false;
                             flag = false;
+                            let serialNo = tools.getObj(controller.tree.selected.jobs, rowData.id, 'job');
                             crossedData = {
                             crossedData = {
                                 orgId: rowData.id,
                                 orgId: rowData.id,
-                                newData: uniqPasteArr[j]
+                                newData: uniqPasteArr[j],
+                                serialNo: serialNo
                             };
                             };
                         }
                         }
                     });
                     });
                     if(flag){
                     if(flag){
-                        uncrossedDatas.push(uniqPasteArr[j]);
+                        serialNoUn++;
+                        uncrossedDatas.push({data: uniqPasteArr[j], serialNo: serialNoUn});
                     }
                     }
                     else {
                     else {
                         crossedDatas.push(crossedData);
                         crossedDatas.push(crossedData);
@@ -510,7 +576,7 @@
                     });
                     });
                 }
                 }
                 else {
                 else {
-                    tools.reshowData(sheet, controller.tree.selected.jobs, setting, true);
+                    tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);
                 }
                 }
             }
             }
             else {
             else {
@@ -535,20 +601,26 @@
                     }
                     }
                 }
                 }
                 let uniqPasteArr = tools.uniqArr(pasteArr);
                 let uniqPasteArr = tools.uniqArr(pasteArr);
+                let serialNoUn = tools.getSerialNo(controller.tree.selected.items) - 1;
                 for(let i =orgRow, j=0; i<=uniqPasteArr.length+orgRow-1; i++, j++ ){
                 for(let i =orgRow, j=0; i<=uniqPasteArr.length+orgRow-1; i++, j++ ){
                     let flag = true;
                     let flag = true;
                     let crossedData;
                     let crossedData;
                     sheetItemsDatas.forEach(function(rowData){
                     sheetItemsDatas.forEach(function(rowData){
                         if(rowData.rowIdx === i && rowData.data !== uniqPasteArr[j]){
                         if(rowData.rowIdx === i && rowData.data !== uniqPasteArr[j]){
                             flag = false;
                             flag = false;
+                            let serialNo = tools.getObj(controller.tree.selected.items, rowData.id, 'item');
                             crossedData = {
                             crossedData = {
                                 orgId: rowData.id,
                                 orgId: rowData.id,
-                                newData: uniqPasteArr[j]
+                                newData: uniqPasteArr[j],
+                                serialNo: serialNo
                             };
                             };
                         }
                         }
                     });
                     });
                     if(flag){
                     if(flag){
-                        uncrossedDatas.push(uniqPasteArr[j]);
+                        //let serialNo = tools.getSerialNo(controller.tree.selected.items);
+                        serialNoUn ++;
+                        console.log(serialNoUn);
+                        uncrossedDatas.push({data: uniqPasteArr[j], serialNo: serialNoUn});
                     }
                     }
                     else {
                     else {
                         crossedDatas.push(crossedData);
                         crossedDatas.push(crossedData);
@@ -560,8 +632,8 @@
                         pasteController.frontItemsRelOperator(sheet, setting, controller, totalItems, datas);
                         pasteController.frontItemsRelOperator(sheet, setting, controller, totalItems, datas);
                     });
                     });
                 }
                 }
-                if(uncrossedDatas.length > 0 || crossedDatas.length > 0) {
-                    tools.reshowData(sheet, controller.tree.selected.items, setting, true);
+                else{
+                    tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
                 }
                 }
             }
             }
             else {
             else {
@@ -572,7 +644,7 @@
 
 
 
 
     function buildJobs(jobsSpread, setting){
     function buildJobs(jobsSpread, setting){
-        setSheet.initSheet(jobsSpread, setting);
+        setSheet.initSheet(jobsSpread, setting, false);
        // setSheet.setMaxRowCount(jobsSpread.getActiveSheet(), 10);
        // setSheet.setMaxRowCount(jobsSpread.getActiveSheet(), 10);
         myKey.downKey(jobsSpread);
         myKey.downKey(jobsSpread);
         myKey.enterKey(jobsSpread);
         myKey.enterKey(jobsSpread);
@@ -580,7 +652,7 @@
     }
     }
 
 
     function buildItems(itemsSpread, setting){
     function buildItems(itemsSpread, setting){
-        setSheet.initSheet(itemsSpread, setting);
+        setSheet.initSheet(itemsSpread, setting, false);
        // setSheet.setMaxRowCount(itemsSpread.getActiveSheet(), 10);
        // setSheet.setMaxRowCount(itemsSpread.getActiveSheet(), 10);
         myKey.downKey(itemsSpread);
         myKey.downKey(itemsSpread);
         myKey.enterKey(itemsSpread);
         myKey.enterKey(itemsSpread);

+ 35 - 19
web/maintain/bills_lib/html/tezheng.html

@@ -11,7 +11,7 @@
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <!--spread-->
     <!--spread-->
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013white.10.0.1.css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css">
     <!--zTree-->
     <!--zTree-->
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
 </head>
 </head>
@@ -203,7 +203,7 @@
             buildEigenvalue(spreadVal, eigenValueSetting);
             buildEigenvalue(spreadVal, eigenValueSetting);
   		});
   		});
         function buildAllItems(spread, setting){
         function buildAllItems(spread, setting){
-            setSheet.initSheet(spread, setting);
+            setSheet.initSheet(spread, setting, false);
             myKey.downKey(spread);
             myKey.downKey(spread);
             myKey.enterKey(spread);
             myKey.enterKey(spread);
             TREE_SHEET_HELPER.loadSheetHeader(setting, spread.getActiveSheet());
             TREE_SHEET_HELPER.loadSheetHeader(setting, spread.getActiveSheet());
@@ -238,7 +238,7 @@
         }
         }
 
 
         function buildEigenvalue(spread, setting){
         function buildEigenvalue(spread, setting){
-            setSheet.initSheet(spread, setting);
+            setSheet.initSheet(spread, setting, false);
             setSheet.setMaxRowCount(spread.getActiveSheet(), 10);
             setSheet.setMaxRowCount(spread.getActiveSheet(), 10);
            // setSheet.setEditCol(spread.getActiveSheet(), 1);
            // setSheet.setEditCol(spread.getActiveSheet(), 1);
             myKey.downKey(spread);
             myKey.downKey(spread);
@@ -281,6 +281,7 @@
             if(selectedId){
             if(selectedId){
                 let valueArr = valueController.getValues(totalItems, selectedId);
                 let valueArr = valueController.getValues(totalItems, selectedId);
                 if(valueArr.length > 0){
                 if(valueArr.length > 0){
+                    setSheet.setMaxRowCount(sheet, valueArr);
                     tools.reshowValue(sheet, valueArr, setting, true);
                     tools.reshowValue(sheet, valueArr, setting, true);
                 }
                 }
             }
             }
@@ -309,25 +310,27 @@
                         }
                         }
                     }
                     }
                 }
                 }
-                for(let i=0; i< pasteDatas.length; i++){
+                let uniqPasteDatas = tools.uniqObjArr(pasteDatas);
+                tools.resetRowIdx(uniqPasteDatas, orgRow);
+                for(let i=0; i< uniqPasteDatas.length; i++){
                     let crossedData;
                     let crossedData;
                     let flag = true;
                     let flag = true;
                     totalItemsDatas.forEach(function(orgData){
                     totalItemsDatas.forEach(function(orgData){
-                        if(pasteDatas[i].rowIdx === orgData.rowIdx && pasteDatas[i].colIdx === orgData.colIdx){
+                        if(uniqPasteDatas[i].rowIdx === orgData.rowIdx && uniqPasteDatas[i].colIdx === orgData.colIdx){
                             flag = false;
                             flag = false;
                             crossedData = {
                             crossedData = {
                                 billsLibId: billsLibId,
                                 billsLibId: billsLibId,
-                                rowIdx: pasteDatas[i].rowIdx,
-                                colIdx: pasteDatas[i].colIdx,
-                                field: pasteDatas[i].field,
+                                rowIdx: uniqPasteDatas[i].rowIdx,
+                                colIdx: uniqPasteDatas[i].colIdx,
+                                field: uniqPasteDatas[i].field,
                                 orgId: orgData.id,
                                 orgId: orgData.id,
-                                data: pasteDatas[i].data,
+                                data: uniqPasteDatas[i].data,
                                 type: 'Update'
                                 type: 'Update'
                             }
                             }
                         }
                         }
                     });
                     });
                     if(flag){
                     if(flag){
-                        uncrossedDatas.push(pasteDatas[i]);
+                        uncrossedDatas.push(uniqPasteDatas[i]);
                     }
                     }
                     else{
                     else{
                         crossedDatas.push(crossedData);
                         crossedDatas.push(crossedData);
@@ -368,25 +371,30 @@
                         }
                         }
                     }
                     }
                 }
                 }
-                for(let i=0; i< pasteDatas.length; i++){
+                console.log(`pasteDatas`);
+                console.log(pasteDatas);
+                let uniqDatas = tools.uniqObjArr(pasteDatas);
+                console.log(`uniqDatas`);
+                console.log(uniqDatas);
+                for(let i=0; i< uniqDatas.length; i++){
                     let crossedData;
                     let crossedData;
                     let flag = true;
                     let flag = true;
                     valueDatas.forEach(function(orgData){
                     valueDatas.forEach(function(orgData){
-                        if(pasteDatas[i].rowIdx === orgData.rowIdx && pasteDatas[i].colIdx === orgData.colIdx){
+                        if(uniqDatas[i].rowIdx === orgData.rowIdx && uniqDatas[i].colIdx === orgData.colIdx){
                             flag = false;
                             flag = false;
                             crossedData = {
                             crossedData = {
                                 billsLibId: billsLibId,
                                 billsLibId: billsLibId,
-                                rowIdx: pasteDatas[i].rowIdx,
-                                colIdx: pasteDatas[i].colIdx,
-                                field: pasteDatas[i].field,
+                                rowIdx: uniqDatas[i].rowIdx,
+                                colIdx: uniqDatas[i].colIdx,
+                                field: uniqDatas[i].field,
                                 orgId: orgData.id,
                                 orgId: orgData.id,
-                                data: pasteDatas[i].data,
+                                data: uniqDatas[i].data,
                                 type: 'Update'
                                 type: 'Update'
                             }
                             }
                         }
                         }
                     });
                     });
                     if(flag){
                     if(flag){
-                        uncrossedDatas.push(pasteDatas[i]);
+                        uncrossedDatas.push(uniqDatas[i]);
                     }
                     }
                     else{
                     else{
                         crossedDatas.push(crossedData);
                         crossedDatas.push(crossedData);
@@ -395,11 +403,19 @@
                 let encapDatas = tools.encapValues(sheet, totalItems, uncrossedDatas, crossedDatas);
                 let encapDatas = tools.encapValues(sheet, totalItems, uncrossedDatas, crossedDatas);
                 if(encapDatas.updateDatas.length > 0 || encapDatas.createDatas.length > 0){
                 if(encapDatas.updateDatas.length > 0 || encapDatas.createDatas.length > 0){
                     itemsAjax.pasteValues(encapDatas, function(datas){
                     itemsAjax.pasteValues(encapDatas, function(datas){
+                        console.log(datas);
+                        console.log(`enterCb`);
                         pasteController.pasteValueFront(sheet, totalItems, datas);
                         pasteController.pasteValueFront(sheet, totalItems, datas);
                     });
                     });
                 }
                 }
-                if(uncrossedDatas.length >0 || crossedDatas.length > 0){
-                    tools.reshowValue(sheet, valuesArr, eigenValueSetting, true);
+                else{
+                    let valuesArr = valueController.getValues(totalItems, selectedId);
+                    if(valuesArr.length > 0){
+                        tools.reshowValue(sheet, valuesArr, eigenValueSetting, true);
+                    }
+                    else {
+                        tools.clearData(sheet);
+                    }
                 }
                 }
             });
             });
         }
         }

+ 141 - 21
web/maintain/bills_lib/scripts/bills_lib_ajax.js

@@ -156,11 +156,11 @@ var billsAjax = {
             }
             }
         });
         });
     },
     },
-    createBills: function(billsLibId, newId, pid, nid, callback){
+    createBills: function(billsLibId, newId, pid, nid, updatePreData, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/createBills',
             url: 'stdBillsEditor/createBills',
-            data: {data: JSON.stringify({billsLibId: billsLibId, newId: newId, ParentID: pid, NextSiblingID: nid})},
+            data: {data: JSON.stringify({billsLibId: billsLibId, newId: newId, ParentID: pid, NextSiblingID: nid, updatePreData: updatePreData})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
                 if(!result.error){
                 if(!result.error){
@@ -171,31 +171,89 @@ var billsAjax = {
             }
             }
         });
         });
     },
     },
-
-    updatePNId: function(billsLibId, updateData){
+    upMove: function(billsLibId, updateDatas, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/upMove',
+            data: {data: JSON.stringify({billsLibId: billsLibId, updateDatas: updateDatas})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback();
+                }
+            }
+        });
+    },
+    downMove: function (billsLibId, updateDatas, callback) {
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/downMove',
+            data: {data: JSON.stringify({billsLibId: billsLibId, updateDatas: updateDatas})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback();
+                }
+            }
+        })
+    },
+    updatePNId: function(billsLibId, updateData, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/updatePNId',
             url: 'stdBillsEditor/updatePNId',
             data: {data: JSON.stringify({billsLibId: billsLibId, updateData: updateData})},
             data: {data: JSON.stringify({billsLibId: billsLibId, updateData: updateData})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
-                if(!result.error){
-                    console.log(`更新成功!`);
+                console.log(`entersFuc`);
+                if(!result.error && callback){
+                    console.log(`enterSc`);
+                    callback();
                 }
                 }
                 else {
                 else {
                     //提示窗口:更新失败
                     //提示窗口:更新失败
                 }
                 }
+            },
+            error: function(){
+                console.log(`error`);
             }
             }
         });
         });
     },
     },
-    deleteBills: function(billsLibId, deleteIds, callback){
+    upLevel: function(billsLibId, updateDatas, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/upLevel',
+            data: {data: JSON.stringify({billsLibId: billsLibId, updateDatas: updateDatas})},
+            dataType: 'json',
+            success: function (result) {
+                console.log(`ssc`);
+                if(!result.error && callback){
+                    callback();
+                }
+            }
+        })
+    },
+    downLevel: function (billsLibId, updateDatas, callback) {
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/downLevel',
+            data: {data: JSON.stringify({billsLibId: billsLibId, updateDatas: updateDatas})},
+            dataType: 'json',
+            success: function (result) {
+                if(!result.error && callback){
+                    callback();
+                }
+            }
+        })
+    },
+    deleteBills: function(billsLibId, deleteIds, updateNode, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/deleteBills',
             url: 'stdBillsEditor/deleteBills',
-            data: {data: JSON.stringify({billsLibId: billsLibId, deleteIds: deleteIds})},
+            data: {data: JSON.stringify({billsLibId: billsLibId, deleteIds: deleteIds, updateNode: updateNode})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
                 if(!result.error){
                 if(!result.error){
+                    console.log(result.message);
                     if(callback){
                     if(callback){
                         callback();
                         callback();
                     }
                     }
@@ -215,32 +273,35 @@ var billsAjax = {
             }
             }
         });
         });
     },
     },
-    updateBillsArr: function(billsLibId, updateId, orgId, newId, type, classify){
+    updateBillsArr: function(billsLibId, updateId, orgId, newId, type, classify, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/updateBillsArr',
             url: 'stdBillsEditor/updateBillsArr',
             data: {data: JSON.stringify({billsLibId: billsLibId, updateId: updateId, orgId: orgId, newId: newId, type: type, classify: classify})},
             data: {data: JSON.stringify({billsLibId: billsLibId, updateId: updateId, orgId: orgId, newId: newId, type: type, classify: classify})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
+                if(!result.error && callback){
+                    callback();
+                }
             }
             }
         });
         });
     },
     },
-    pasteBills: function(datas){
+    pasteBills: function(billsLibId, datas){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/pasteBills',
             url: 'stdBillsEditor/pasteBills',
-            data: {data: JSON.stringify({datas: datas})},
+            data: {data: JSON.stringify({billsLibId: billsLibId, datas: datas})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
 
 
             }
             }
         });
         });
     },
     },
-    updateRecharge: function(billsLibId, updateIds, data){
+    updateRecharge: function(billsLibId, updateId, data){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/updateRecharge',
             url: 'stdBillsEditor/updateRecharge',
-            data: {data: JSON.stringify({billsLibId: billsLibId, updateIds: updateIds, data: data})},
+            data: {data: JSON.stringify({billsLibId: billsLibId, updateId: updateId, data: data})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
 
 
@@ -289,14 +350,16 @@ var jobsAjax = {
             }
             }
         });
         });
     },
     },
-    createJobContent: function(billsLibId, data, serialNo, id){
+    createJobContent: function(billsLibId, data, serialNo, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/createJobContent',
             url: 'stdBillsEditor/createJobContent',
-            data: {data: JSON.stringify({billsLibId: billsLibId, data: data, serialNo: serialNo, id: id })},
+            data: {data: JSON.stringify({billsLibId: billsLibId, data: data, serialNo: serialNo})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
-
+                if(!result.error && callback){
+                    callback(result.data);
+                }
             }
             }
         });
         });
     },
     },
@@ -335,8 +398,34 @@ var jobsAjax = {
             }
             }
 
 
         });
         });
+    },
+    edCreateJob: function(billsLibId, billsId, data, code, serialNo, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/edCreateJob',
+            data: {data: JSON.stringify({billsLibId: billsLibId, billsId:billsId, data: data, code: code, serialNo: serialNo})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback(result.data);
+                }
+            }
+        });
+    },
+    edUpdateJob: function(billsLibId, billsId, content, code, orgJobId, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/edUpdateJob',
+            data: {data: JSON.stringify({billsLibId: billsLibId, billsId:billsId, content: content, code: code, orgJobId: orgJobId})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback(result.data);
+                }
+            }
+        });
     }
     }
-}
+};
 
 
 var itemsAjax = {
 var itemsAjax = {
     getItemCharacter: function(billsLibId, callback){
     getItemCharacter: function(billsLibId, callback){
@@ -354,13 +443,16 @@ var itemsAjax = {
             }
             }
         });
         });
     },
     },
-    createItemCharacter: function(billsLibId,  data, serialNo, id){
+    createItemCharacter: function(billsLibId,  data, code, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/createItemCharacter',
             url: 'stdBillsEditor/createItemCharacter',
-            data: {data: JSON.stringify({billsLibId: billsLibId, data: data, serialNo: serialNo, id: id})},
+            data: {data: JSON.stringify({billsLibId: billsLibId, data: data, code: code})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
+                if(!result.error && callback){
+                    callback(result.data);
+                }
             }
             }
         });
         });
     },
     },
@@ -397,14 +489,16 @@ var itemsAjax = {
             }
             }
         });
         });
     },
     },
-    pasteItems: function(pasteDatas){
+    pasteItems: function(pasteDatas, callback){
         $.ajax({
         $.ajax({
             type: 'post',
             type: 'post',
             url: 'stdBillsEditor/pasteItems',
             url: 'stdBillsEditor/pasteItems',
             data: {data: JSON.stringify({pasteDatas: pasteDatas})},
             data: {data: JSON.stringify({pasteDatas: pasteDatas})},
             dataType: 'json',
             dataType: 'json',
             success: function(result){
             success: function(result){
-
+                if(!result.error && callback){
+                    callback(result.data);
+                }
             }
             }
 
 
         });
         });
@@ -421,6 +515,32 @@ var itemsAjax = {
                 }
                 }
             }
             }
         });
         });
+    },
+    edCreateItem: function(billsLibId, billsId, data, code, serialNo, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/edCreateItem',
+            data: {data: JSON.stringify({billsLibId: billsLibId, billsId:billsId, data: data, code: code, serialNo: serialNo})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback(result.data);
+                }
+            }
+        });
+    },
+    edUpdateItem: function(billsLibId, billsId, content, code, orgItemId, callback){
+        $.ajax({
+            type: 'post',
+            url: 'stdBillsEditor/edUpdateItem',
+            data: {data: JSON.stringify({billsLibId: billsLibId, billsId:billsId, content: content, code: code, orgItemId: orgItemId})},
+            dataType: 'json',
+            success: function(result){
+                if(!result.error && callback){
+                    callback(result.data);
+                }
+            }
+        });
     }
     }
 }
 }
 
 

+ 40 - 40
web/maintain/bills_lib/scripts/bills_lib_setting.js

@@ -10,13 +10,13 @@ var billsLibSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 160
             width: 160
         },
         },
@@ -27,13 +27,13 @@ var billsLibSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'name',
                 field: 'name',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 300
             width: 300
         },
         },
@@ -44,13 +44,13 @@ var billsLibSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'unit',
                 field: 'unit',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 160
             width: 160
         },
         },
@@ -61,19 +61,19 @@ var billsLibSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: ' Arial'
             },
             },
             data: {
             data: {
                 field: 'ruleText',
                 field: 'ruleText',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 420
             width: 420
         }
         }
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 };
 };
@@ -87,13 +87,13 @@ var jobsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 100
             width: 100
         },
         },
@@ -104,19 +104,19 @@ var jobsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'content',
                 field: 'content',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 210
             width: 210
         },
         },
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 };
 };
@@ -130,13 +130,13 @@ var itemsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 100
             width: 100
         },
         },
@@ -147,19 +147,19 @@ var itemsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'content',
                 field: 'content',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 210
             width: 210
         },
         },
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 };
 };
@@ -173,13 +173,13 @@ var totalJobsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 200
             width: 200
         },
         },
@@ -190,19 +190,19 @@ var totalJobsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'content',
                 field: 'content',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 850
             width: 850
         },
         },
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 };
 };
@@ -216,13 +216,13 @@ var totalItemsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 200
             width: 200
         },
         },
@@ -233,19 +233,19 @@ var totalItemsSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'content',
                 field: 'content',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 850
             width: 850
         },
         },
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 };
 };
@@ -259,13 +259,13 @@ var eigenValueSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'code',
                 field: 'code',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 200
             width: 200
         },
         },
@@ -276,19 +276,19 @@ var eigenValueSetting = {
                 spanRows: [2],
                 spanRows: [2],
                 vAlign: [1, 1],
                 vAlign: [1, 1],
                 hAlign: [1, 1],
                 hAlign: [1, 1],
-                font: '16px Arial'
+                font: 'Arial'
             },
             },
             data: {
             data: {
                 field: 'value',
                 field: 'value',
                 vAlign: 1,
                 vAlign: 1,
                 hAlign: 0,
                 hAlign: 0,
-                font: '14px Arial'
+                font: 'Arial'
             },
             },
             width: 480
             width: 480
         },
         },
     ],
     ],
-    headRows: 2,
-    headRowHeight: [20, 30, 30],
+    headRows: 1,
+    headRowHeight: [47],
     emptyRows: 3,
     emptyRows: 3,
     treeCol: 0
     treeCol: 0
 }
 }

ファイルの差分が大きいため隠しています
+ 636 - 305
web/maintain/bills_lib/scripts/db_controller.js


+ 43 - 17
web/maintain/bills_lib/scripts/set_sheets.js

@@ -2,16 +2,17 @@
  * Created by vian on 2017/3/16.
  * Created by vian on 2017/3/16.
  */
  */
 var setSheet = {
 var setSheet = {
-    initSheet: function(spread, setting){
+    initSheet: function(spread, setting, isExtendPaste){
         var spreadNS = GC.Spread.Sheets, sheet = spread.getActiveSheet();
         var spreadNS = GC.Spread.Sheets, sheet = spread.getActiveSheet();
         sheet.suspendPaint();
         sheet.suspendPaint();
         spread.options.showHorizontalScrollbar = false;
         spread.options.showHorizontalScrollbar = false;
         spread.options.showVerticalScrollbar =false;
         spread.options.showVerticalScrollbar =false;
         spread.options.tabStripVisible = false;
         spread.options.tabStripVisible = false;
         spread.options.scrollbarMaxAlign = true;
         spread.options.scrollbarMaxAlign = true;
-        spread.options.allowExtendPasteRange = true;
+        spread.options.allowCopyPasteExcelStyle = false;
+        spread.options.allowExtendPasteRange = isExtendPaste? true : false;
         sheet.showRowOutline(false);
         sheet.showRowOutline(false);
-        sheet.defaults.rowHeight = 30;
+       // sheet.defaults.rowHeight = 30;
         setting.cols.forEach(function(col, colIdx){
         setting.cols.forEach(function(col, colIdx){
             sheet.getRange(-1,colIdx,-1,1, GC.Spread.Sheets.SheetArea.viewport).hAlign(GC.Spread.Sheets.HorizontalAlign.left);
             sheet.getRange(-1,colIdx,-1,1, GC.Spread.Sheets.SheetArea.viewport).hAlign(GC.Spread.Sheets.HorizontalAlign.left);
             sheet.getRange(-1,colIdx,-1,1, GC.Spread.Sheets.SheetArea.viewport).vAlign(GC.Spread.Sheets.VerticalAlign.center);
             sheet.getRange(-1,colIdx,-1,1, GC.Spread.Sheets.SheetArea.viewport).vAlign(GC.Spread.Sheets.VerticalAlign.center);
@@ -26,15 +27,18 @@ var setSheet = {
         sheet.options.isProtected = true;
         sheet.options.isProtected = true;
     },
     },
     setMaxRowCount: function(sheet, arr){
     setMaxRowCount: function(sheet, arr){
-        let rowCount;
         let arrL = arr.length;
         let arrL = arr.length;
-        if(arrL <10){
+        let rowCount = arrL + 10;
+        /*if(arrL <10){
             rowCount = 10;
             rowCount = 10;
         }
         }
         else {
         else {
             rowCount = arrL + 3;
             rowCount = arrL + 3;
-        }
+        }*/
         sheet.setRowCount(rowCount, GC.Spread.Sheets.SheetArea.viewport);
         sheet.setRowCount(rowCount, GC.Spread.Sheets.SheetArea.viewport);
+    },
+    formatter: function(sheet){
+        sheet.setFormatter(-1, 0, "@", GC.Spread.Sheets.SheetArea.viewport);
     }
     }
 }
 }
 
 
@@ -112,20 +116,29 @@ var myKey = {
             spread.commandManager().register('myDelete', function(){
             spread.commandManager().register('myDelete', function(){
                 spread.suspendEvent();
                 spread.suspendEvent();
                 var ids = tools.delIds(sheet);
                 var ids = tools.delIds(sheet);
-                tools.deleteELes(controller.tree.selected[classify], ids, function(result){
+                let classifyStr = classify === 'jobs' ? 'job' : 'item';
+                tools.deleteELes(controller.tree.selected[classify], ids, classifyStr);
                     //deleteFrontData
                     //deleteFrontData
-                    tools.reshowData(sheet, controller.tree.selected[classify], setting, true);
+                    //tools.reshowData(sheet, controller.tree.selected[classify], setting, true);
                     //deleteDB
                     //deleteDB
-                    billsAjax.updateBillsArr(billsLibId, controller.tree.selected.getID(), ids, null, 'delete', classify);
-                    if(result.length > 0){
+                    billsAjax.updateBillsArr(billsLibId, controller.tree.selected.getID(), ids, null, 'delete', classify, function(){
+                        tools.orderReshowData(sheet, controller.tree.selected[classify], setting, classifyStr, true);
+                    });
+                    /*if(result.length > 0){
                         if(classify === 'jobs'){
                         if(classify === 'jobs'){
-                            result.forEach(function(id){
-                                if(totalObj.findJob(id)){
+                            /!*result.forEach(function(id){
+                                controller.tree.selected.jobs.forEach(function(obj){
+                                    if(id === obj.job.data.id){
+                                        controller.tree.selected.jobs.splice(obj);
+                                    }
+                                });
+                                /!*if(totalObj.findJob(id)){
                                     totalObj.jobsArr.splice(totalObj.jobsArr.indexOf(totalObj.findJob(id)), 1);
                                     totalObj.jobsArr.splice(totalObj.jobsArr.indexOf(totalObj.findJob(id)), 1);
                                     delete  totalObj.jobs[totalObj.prefix + id];
                                     delete  totalObj.jobs[totalObj.prefix + id];
-                                }
-                            });
-                            jobsAjax.deleteJobContent(result);
+                                }*!/
+                            });*!/
+                            //jobsAjax.deleteJobContent(billsLibId, result);
+                            tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);
                         }
                         }
                         else {
                         else {
                             result.forEach(function(id){
                             result.forEach(function(id){
@@ -136,8 +149,7 @@ var myKey = {
                             });
                             });
                             itemsAjax.deleteItemCharacter(result);
                             itemsAjax.deleteItemCharacter(result);
                         }
                         }
-                    }
-                });
+                    }*/
                 spread.resumeEvent();
                 spread.resumeEvent();
             });
             });
             spread.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
             spread.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
@@ -159,6 +171,13 @@ var myKey = {
                         var job = totalJobs.findJob(id);
                         var job = totalJobs.findJob(id);
                         totalJobs.jobsArr.splice(totalJobs.jobsArr.indexOf(job), 1);
                         totalJobs.jobsArr.splice(totalJobs.jobsArr.indexOf(job), 1);
                     });
                     });
+                    function myCompareCode(a, b){
+                        let valA = a.data.code,
+                            valB = b.data.code;
+                        return valB- valA;
+                    }
+                    totalJobs.jobsArr.sort(myCompareCode);
+                    maxJobsNumber = totalJobs.jobsArr[0].data.code;
                     tools.reshowData(sheet, totalJobs.jobsArr, setting, true);
                     tools.reshowData(sheet, totalJobs.jobsArr, setting, true);
                     jobsAjax.deleteJobContent(billsLibId, ids);
                     jobsAjax.deleteJobContent(billsLibId, ids);
                     billsAjax.updateBillsArr(billsLibId, billsIds, ids, null, 'deleteAll', 'jobs');
                     billsAjax.updateBillsArr(billsLibId, billsIds, ids, null, 'deleteAll', 'jobs');
@@ -179,6 +198,13 @@ var myKey = {
                         var item = totalItems.findItem(id);
                         var item = totalItems.findItem(id);
                         totalItems.itemsArr.splice(totalItems.itemsArr.indexOf(item), 1);
                         totalItems.itemsArr.splice(totalItems.itemsArr.indexOf(item), 1);
                     });
                     });
+                    function myCompareCode(a, b){
+                        let valA = a.data.code,
+                            valB = b.data.code;
+                        return valB- valA;
+                    }
+                    totalItems.itemsArr.sort(myCompareCode);
+                    maxItemsNumber = totalItems.itemsArr[0].data.code;
                     tools.reshowData(sheet, totalItems.itemsArr, setting, true);
                     tools.reshowData(sheet, totalItems.itemsArr, setting, true);
                     itemsAjax.deleteItemCharacter(billsLibId, ids);
                     itemsAjax.deleteItemCharacter(billsLibId, ids);
                     billsAjax.updateBillsArr(billsLibId, billsIds, ids, null, 'deleteAll', 'items');
                     billsAjax.updateBillsArr(billsLibId, billsIds, ids, null, 'deleteAll', 'items');

+ 10 - 2
web/maintain/ration_repository/dinge.html

@@ -12,7 +12,7 @@
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <!--zTree-->
     <!--zTree-->
   	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
   	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.10.0.1.css" type="text/css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
 
 
 </head>
 </head>
 
 
@@ -47,7 +47,7 @@
                       <div class="tab-bar">
                       <div class="tab-bar">
                           <a onclick="zTreeOprObj.addRootNode()" class="btn btn-secondary btn-sm">增加根节点</a>
                           <a onclick="zTreeOprObj.addRootNode()" class="btn btn-secondary btn-sm">增加根节点</a>
                       </div>
                       </div>
-                    <div class="tab-content">
+                    <div class="tab-content" style="width: 100%; height: 100%; overflow: auto">
                       <ul id="rationChapterTree" class="ztree"></ul>
                       <ul id="rationChapterTree" class="ztree"></ul>
                     </div>
                     </div>
                   </div>
                   </div>
@@ -501,6 +501,14 @@
                 }
                 }
             };
             };
             $(document).ready(function(){
             $(document).ready(function(){
+                /*function round(v,e){
+                    var t=1;
+                    for(;e>0;t*=10,e--);
+                    for(;e<0;t/=10,e++);
+                    return Math.round(v*t)/t;
+                }
+                let a = 10.003, b = 20;
+                console.log(a+b);*/
                 pageOprObj.initPage();
                 pageOprObj.initPage();
                 rationOprObj.buildSheet($("#rationItemsSheet")[0]);
                 rationOprObj.buildSheet($("#rationItemsSheet")[0]);
                 sheetCommonObj.shieldAllCells(rationOprObj.workBook.getSheet(0), rationOprObj.setting);
                 sheetCommonObj.shieldAllCells(rationOprObj.workBook.getSheet(0), rationOprObj.setting);

+ 44 - 3
web/maintain/ration_repository/gongliao.html

@@ -9,7 +9,7 @@
     <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
     <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
     <link rel="stylesheet" href="/web/maintain/ration_repository/css/main.css">
     <link rel="stylesheet" href="/web/maintain/ration_repository/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
-    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.10.0.1.css" type="text/css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
     <!--zTree-->
     <!--zTree-->
   	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
   	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
 </head>
 </head>
@@ -41,7 +41,7 @@
         <div class="content">
         <div class="content">
             <div class="container-fluid">
             <div class="container-fluid">
                 <div class="row">
                 <div class="row">
-                    <div class="main-side col-lg-3 p-0">
+                    <div class="main-side col-lg-3 p-0" style="width: 100%; height: 100%; overflow-y: auto">
                         <ul id="repositoryTree" class="ztree"></ul>
                         <ul id="repositoryTree" class="ztree"></ul>
                     </div>
                     </div>
                     <div class="main-content col-lg-9 p-0">
                     <div class="main-content col-lg-9 p-0">
@@ -167,6 +167,47 @@
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
+    <button id="gljAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#gljAlert" style="display: none"></button>
+    <button id="codeAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#codeAlert" style="display: none"></button>
+    <div class="modal fade" id="gljAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="gdid" value="123">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">取消确认</h5>
+                    <button type="button" id="gljAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger">还有值未输入,确认是否取消新增工料机?</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" id="aleCanceBtn" data-dismiss="modal">取消</button>
+                    <a href="javascript: void(0);" id="aleConfBtn" class="btn btn-danger" data-dismiss="modal">确认</a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="modal fade" id="codeAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="codedid" value="123">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">警告</h5>
+                    <button type="button" id="codAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger" id="alertText">输入的编号已存在,请重新输入!</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-danger" id="codAleConfBtn" data-dismiss="modal">确认</button>
+                </div>
+            </div>
+        </div>
+    </div>
     <!-- JS. -->
     <!-- JS. -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
@@ -175,7 +216,7 @@
     <!-- zTree -->
     <!-- zTree -->
     <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
     <script 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>GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";</script>
-  	<script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
   	<script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
   	<script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.exedit.js"></script>
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.exedit.js"></script>
     <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
     <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>

+ 15 - 3
web/maintain/ration_repository/js/ration.js

@@ -20,6 +20,9 @@ var rationOprObj = {
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
             {headerName:"名称",headerWidth:300,dataCode:"name", dataType: "String"},
             {headerName:"名称",headerWidth:300,dataCode:"name", dataType: "String"},
             {headerName:"单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center"},
             {headerName:"单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center"},
+            {headerName:"人工费",headerWidth:120,dataCode:"labourPrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
+            {headerName:"材料费",headerWidth:120,dataCode:"materialPrice", dataType: "Number", formatter: "0.00",  hAlign: "right"},
+            {headerName:"机械费",headerWidth:120,dataCode:"machinePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
             {headerName:"基价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
             {headerName:"基价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
             {headerName:"显示名称(以%s表示参数)",headerWidth:350,dataCode:"caption", dataType: "String"},
             {headerName:"显示名称(以%s表示参数)",headerWidth:350,dataCode:"caption", dataType: "String"},
             {headerName:"取费专业",headerWidth:120,dataCode:"feeType", dataType: "Number", hAlign: "center"}
             {headerName:"取费专业",headerWidth:120,dataCode:"feeType", dataType: "Number", hAlign: "center"}
@@ -58,6 +61,8 @@ var rationOprObj = {
 
 
         if(!(args.sheetArea === GC.Spread.Sheets.SheetArea.colHeader || args.sheetArea === GC.Spread.Sheets.SheetArea.corner)){
         if(!(args.sheetArea === GC.Spread.Sheets.SheetArea.colHeader || args.sheetArea === GC.Spread.Sheets.SheetArea.corner)){
             var cacheSection = me.getCache();
             var cacheSection = me.getCache();
+            console.log(`cache`);
+            console.log(cacheSection);
             if (cacheSection && args.row < cacheSection.length) {
             if (cacheSection && args.row < cacheSection.length) {
                 rationGLJOprObj.getGljItems(cacheSection[args.row]);
                 rationGLJOprObj.getGljItems(cacheSection[args.row]);
                 rationCoeOprObj.getCoeItems(cacheSection[args.row]);
                 rationCoeOprObj.getCoeItems(cacheSection[args.row]);
@@ -119,7 +124,8 @@ var rationOprObj = {
             var cacheSection = me.getCache();
             var cacheSection = me.getCache();
             if (cacheSection) {
             if (cacheSection) {
                 for (var i = 0; i < args.rowCount; i++) {
                 for (var i = 0; i < args.rowCount; i++) {
-                    var hasUpdate = false, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row + i),
+                    //var hasUpdate = false, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row + i),
+                    var hasUpdate = false, rObj = sheetCommonObj.combineRationRowData(me.workBook.getSheet(0), me.setting, args.row + i),
                         isEmpty = sheetCommonObj.chkIfEmpty(rObj, me.setting);
                         isEmpty = sheetCommonObj.chkIfEmpty(rObj, me.setting);
                     for (var j = 0; j < cacheSection.length; j++) {
                     for (var j = 0; j < cacheSection.length; j++) {
                         if (cacheSection[j][me.setting.header[0].dataCode] == rObj[me.setting.header[0].dataCode]) {
                         if (cacheSection[j][me.setting.header[0].dataCode] == rObj[me.setting.header[0].dataCode]) {
@@ -146,8 +152,11 @@ var rationOprObj = {
     },
     },
     onCellEditStart: function(sender, args) {
     onCellEditStart: function(sender, args) {
         var me = rationOprObj;
         var me = rationOprObj;
-        var rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row);
+        //var rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row);
+        var rObj = sheetCommonObj.combineRationRowData(me.workBook.getSheet(0), me.setting, args.row);
         me.currentEditingRation = rObj;
         me.currentEditingRation = rObj;
+        console.log(`currentEditingRation`);
+        console.log(me.currentEditingRation);
         var cacheSection = me.getCache();
         var cacheSection = me.getCache();
         if (cacheSection) {
         if (cacheSection) {
             for (var j = 0; j < cacheSection.length; j++) {
             for (var j = 0; j < cacheSection.length; j++) {
@@ -159,8 +168,11 @@ var rationOprObj = {
         }
         }
     },
     },
     onCellEditEnd: function(sender, args) {
     onCellEditEnd: function(sender, args) {
-        var me = rationOprObj, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row),
+        //var me = rationOprObj, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row),
+        var me = rationOprObj, rObj = sheetCommonObj.combineRationRowData(me.workBook.getSheet(0), me.setting, args.row),
             updateArr = [], addArr = [];
             updateArr = [], addArr = [];
+        console.log(`editEnd`);
+        console.log(rObj);
         if (me.currentEditingRation["ID"]) {
         if (me.currentEditingRation["ID"]) {
             rObj["ID"] = me.currentEditingRation["ID"];
             rObj["ID"] = me.currentEditingRation["ID"];
             updateArr.push(rObj);
             updateArr.push(rObj);

+ 2 - 1
web/maintain/ration_repository/js/ration_assist.js

@@ -65,7 +65,8 @@ var rationAssistOprObj = {
         var me = rationAssistOprObj;
         var me = rationAssistOprObj;
         if (!me.ration) {return;};
         if (!me.ration) {return;};
         var assList = me.ration.rationAssList;
         var assList = me.ration.rationAssList;
-        var assObj = sheetCommonObj.combineRowData(me.sheet, me.setting, args.row);
+        //var assObj = sheetCommonObj.combineRowData(me.sheet, me.setting, args.row);
+        var assObj = sheetCommonObj.combineRationRowData(me.sheet, me.setting, args.row);
         // 新增
         // 新增
         if ((assList == undefined) || (assList && args.row >= assList.length)) {
         if ((assList == undefined) || (assList && args.row >= assList.length)) {
             if (assObj.decimal == undefined || assObj.decimal == null){assObj.decimal = '0';};
             if (assObj.decimal == undefined || assObj.decimal == null){assObj.decimal = '0';};

+ 135 - 11
web/maintain/ration_repository/js/ration_glj.js

@@ -4,30 +4,87 @@
 var rationGLJOprObj = {
 var rationGLJOprObj = {
     sheet: null,
     sheet: null,
     currentRationItem: null,
     currentRationItem: null,
+    distTypeTree: null,
     cache: {},
     cache: {},
     setting: {
     setting: {
         header:[
         header:[
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
             {headerName:"名称",headerWidth:400,dataCode:"name", dataType: "String"},
             {headerName:"名称",headerWidth:400,dataCode:"name", dataType: "String"},
             {headerName:"单位",headerWidth:160,dataCode:"unit", dataType: "String"},
             {headerName:"单位",headerWidth:160,dataCode:"unit", dataType: "String"},
-            {headerName:"单位基价",headerWidth:160, dataCode:"basePrice", dataType: "Number", precision: 2},
-            {headerName:"定额消耗",headerWidth:160, dataCode:"consumeAmt", dataType: "Number", precision: 3},
-            {headerName:"类型",headerWidth:160,dataCode:"gljDistType", dataType: "String"}
+            {headerName:"基价单位",headerWidth:160, dataCode:"basePrice", dataType: "Number", formatter:"0.00",  precision: 2},
+            {headerName:"定额消耗",headerWidth:160, dataCode:"consumeAmt", dataType: "Number", formatter: "0.000", precision: 3},
+            {headerName:"类型",headerWidth:160,dataCode:"gljType", dataType: "String"}
         ],
         ],
         view:{
         view:{
             comboBox:[],
             comboBox:[],
             lockColumns:[1,2,3,5,6]
             lockColumns:[1,2,3,5,6]
         }
         }
     },
     },
+    getDistTypeTree: function (gljDistType) {
+        let me = this;
+        let distType;
+        let distTypeTree = {
+            prefix : 'gljDistType',
+            distTypes: {},
+            comboDatas: [],
+            distTypesArr: []
+        };
+        gljDistType.forEach(function (typeData) {
+            let typeObj = {
+                data: typeData,
+                children: [],
+                parent: null
+            }
+            distTypeTree.distTypes[distTypeTree.prefix + typeData.ID] = typeObj;
+            distTypeTree.distTypesArr.push(typeObj);
+        });
+        gljDistType.forEach(function (typeData) {
+            distType = distTypeTree.distTypes[distTypeTree.prefix + typeData.ID];
+            let parent = distTypeTree.distTypes[distTypeTree.prefix + typeData.ParentID];
+            if(parent){
+                distType.parent = parent;
+                parent.children.push(distType);
+            }
+        });
+        distTypeTree.distTypesArr.forEach(function (distTypeObj) {
+            if(distTypeObj.children.length === 0 && distTypeObj.data.fullName !== '普通机械' &&distTypeObj.data.fullName !== '机械组成物'
+                && distTypeObj.data.fullName !== '机上人工'){
+                distTypeTree.comboDatas.push({text: distTypeObj.data.fullName, value: distTypeObj.data.ID});
+            }
+            if(distTypeObj.data.fullName === '机械'){
+                distTypeTree.comboDatas.push({text: distTypeObj.data.fullName, value: distTypeObj.data.ID});
+            }
+        });
+        //me.distTypeTree = distTypeTree;
+        return distTypeTree;
+        //return distTypeTree.comboDatas;
+    },
+    getGljDistType: function (callback) {
+        let me = this;
+        $.ajax({
+            type: 'post',
+            url: "api/getGljDistType",
+            dataType: 'json',
+            success: function (result) {
+                if(!result.error && callback){
+                    me.distTypeTree = me.getDistTypeTree(result.data);
+                    console.log(`me.distTypeTree`);
+                    console.log(me.distTypeTree);
+                    callback();
+                }
+            }
+        })
+    },
     buildSheet: function(sheet) {
     buildSheet: function(sheet) {
         var me = this;
         var me = this;
         me.sheet = sheet;
         me.sheet = sheet;
-        sheetCommonObj.initSheet(me.sheet, me.setting, 30);
-
-        me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
-        me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
-        me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
-        me.sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
+        me.getGljDistType(function () {
+            sheetCommonObj.initSheet(me.sheet, me.setting, 30);
+            me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
+            me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
+            me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
+            me.sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
+        });
     },
     },
     onRangeChanged: function(sender, args) {
     onRangeChanged: function(sender, args) {
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
@@ -156,11 +213,78 @@ var rationGLJOprObj = {
         })
         })
     },
     },
 
 
+    rationCal: function () {
+        let me = this;
+        let price = {gljType1: [], gljType2: [], gljType3: []}, rst = {labourPrice: 0, materialPrice: 0, machinePrice: 0}, rationBasePrc = 0;
+        function round(v,e){
+            var t=1;
+            for(;e>0;t*=10,e--);
+            for(;e<0;t/=10,e++);
+            return Math.round(v*t)/t;
+        }
+        if(me.currentRationItem && me.cache['_GLJ_' + me.currentRationItem.ID]){
+            let cacheArr = me.cache['_GLJ_' + me.currentRationItem.ID];
+            cacheArr.forEach(function (gljData) {
+                if(gljData.gljType && gljData.basePrice && gljData.consumeAmt){
+                    let parent = me.distTypeTree.distTypes[me.distTypeTree.prefix + gljData.gljType].parent;
+                    if(parent && parent.data.ID <= 3){
+                        price['gljType' + parent.data.ID].push(round( gljData.basePrice * gljData.consumeAmt, 3));//取三位
+                    }
+                    if(!parent && gljData.gljType <= 3){
+                        price['gljType' + gljData.gljType].push(round( gljData.basePrice * gljData.consumeAmt, 3));//取三位
+                    }
+                }
+            });
+            if(price.gljType1.length > 0){
+                let labourPrice = 0;
+                price.gljType1.forEach(function (singlePrc) {
+                    labourPrice += singlePrc;
+                });
+                let roundPrice = round(labourPrice, 2);
+                rst.labourPrice = roundPrice;
+                rationBasePrc += roundPrice;
+            }
+            if(price.gljType2.length > 0){
+                let materialPrice = 0;
+                price.gljType2.forEach(function (singlePrc) {
+                    materialPrice += singlePrc;
+                });
+                let roundPrice = round(materialPrice, 2);
+                rst.materialPrice = roundPrice;
+                rationBasePrc += roundPrice;
+            }
+            if(price.gljType3.length > 0){
+                let machinePrice = 0;
+                price.gljType3.forEach(function (singlePrc) {
+                    machinePrice += singlePrc;
+                });
+                let roundPrice = round(machinePrice, 2);
+                rst.machinePrice = roundPrice;
+                rationBasePrc += roundPrice;
+            }
+            rst.rationBasePrc = rationBasePrc;
+        }
+        return rst;
+    },
+    getRationUpPrice: function () {
+
+    },
+
     updateRationItem: function() {
     updateRationItem: function() {
         var me = this, updateArr = [];
         var me = this, updateArr = [];
         if (me.currentRationItem) {
         if (me.currentRationItem) {
             me.currentRationItem.rationGljList = me.buildRationItemGlj();
             me.currentRationItem.rationGljList = me.buildRationItemGlj();
+            //recalculate ration basePrice
+            let price = me.rationCal();
+            me.currentRationItem.labourPrice = price.labourPrice;
+            me.currentRationItem.materialPrice = price.materialPrice;
+            me.currentRationItem.machinePrice = price.machinePrice;
+            me.currentRationItem.basePrice = price.rationBasePrc;
             updateArr.push(me.currentRationItem);
             updateArr.push(me.currentRationItem);
+            console.log(`me.cache`);
+            console.log(me.cache['_GLJ_' + me.currentRationItem.ID]);
+            console.log(`updateArr`);
+            console.log(updateArr);
             rationOprObj.mixUpdateRequest(updateArr, [], []);
             rationOprObj.mixUpdateRequest(updateArr, [], []);
         }
         }
     },
     },
@@ -185,7 +309,7 @@ var rationGLJOprObj = {
         rst.specs = repGlj.specs;
         rst.specs = repGlj.specs;
         rst.unit = repGlj.unit;
         rst.unit = repGlj.unit;
         rst.basePrice = repGlj.basePrice;
         rst.basePrice = repGlj.basePrice;
-        rst.gljDistType = repGlj.gljDistType;
+        rst.gljType = repGlj.gljType;
         return rst;
         return rst;
     },
     },
     getGljItems: function(rationItem) {
     getGljItems: function(rationItem) {
@@ -232,7 +356,7 @@ var rationGLJOprObj = {
     showGljItems: function(rationID) {
     showGljItems: function(rationID) {
         var me = this;
         var me = this;
         if (me.cache["_GLJ_" + rationID]) {
         if (me.cache["_GLJ_" + rationID]) {
-            sheetCommonObj.showData(me.sheet, me.setting, me.cache["_GLJ_" + rationID]);
+            sheetCommonObj.showData(me.sheet, me.setting, me.cache["_GLJ_" + rationID], me.distTypeTree);
         }
         }
     }
     }
 }
 }

+ 184 - 18
web/maintain/ration_repository/js/repository_glj.js

@@ -20,15 +20,17 @@ var pageOprObj = {
             html = html.replace("XXX定额库", rationLibName);
             html = html.replace("XXX定额库", rationLibName);
             $("#rationname")[0].outerHTML = html;
             $("#rationname")[0].outerHTML = html;
             me.rationLibName = rationLibName;
             me.rationLibName = rationLibName;
-            repositoryGljObj.currentRepositoryId = parseInt(rationLibId);
-            repositoryGljObj.getGljTree(rationLibId);
             repositoryGljObj.buildSheet(container);
             repositoryGljObj.buildSheet(container);
-            repositoryGljObj.getGljItems(rationLibId);
-            sheetCommonObj.shieldAllCells(repositoryGljObj.workBook.getSheet(0), repositoryGljObj.setting);
+            repositoryGljObj.getGljDistType(function () {
+                repositoryGljObj.currentRepositoryId = parseInt(rationLibId);
+                repositoryGljObj.getGljTree(rationLibId);
+                repositoryGljObj.getGljItems(rationLibId);
+                sheetCommonObj.shieldAllCells(repositoryGljObj.workBook.getSheet(0), repositoryGljObj.setting);
+            });
         }
         }
     }
     }
 }
 }
-repositoryGljObj = {
+ repositoryGljObj = {
     treeObj : null,
     treeObj : null,
     workBook: null,
     workBook: null,
     gljCurTypeId: -1,
     gljCurTypeId: -1,
@@ -36,6 +38,7 @@ repositoryGljObj = {
     currentCache: null,
     currentCache: null,
     parentNodeIds: {},
     parentNodeIds: {},
     gljList: [],
     gljList: [],
+    distTypeTree: null,//add
     setting: {
     setting: {
         header:[
         header:[
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
             {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
@@ -43,7 +46,7 @@ repositoryGljObj = {
             {headerName:"规格",headerWidth:260,dataCode:"specs", dataType: "String", hAlign: "left", vAlign: "center"},
             {headerName:"规格",headerWidth:260,dataCode:"specs", dataType: "String", hAlign: "left", vAlign: "center"},
             {headerName:"单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
             {headerName:"单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
             {headerName:"基价单价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
             {headerName:"基价单价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
-            {headerName:"类型",headerWidth:120,dataCode:"gljDistType", dataType: "String", hAlign: "center", vAlign: "center"}
+            {headerName:"类型",headerWidth:120,dataCode:"gljType", dataType: "String", hAlign: "center", vAlign: "center"}
         ],
         ],
         view:{
         view:{
             comboBox:[
             comboBox:[
@@ -53,6 +56,62 @@ repositoryGljObj = {
             ]
             ]
         }
         }
     },
     },
+    getComboData: function (gljDistType) {
+        let me = this;
+        let distType;
+        let distTypeTree = {
+            prefix : 'gljType',
+            distTypes: {},
+            comboDatas: [],
+            distTypesArr: []
+        };
+        gljDistType.forEach(function (typeData) {
+            let typeObj = {
+                data: typeData,
+                children: [],
+                parent: null
+            }
+            distTypeTree.distTypes[distTypeTree.prefix + typeData.ID] = typeObj;
+            distTypeTree.distTypesArr.push(typeObj);
+        });
+        gljDistType.forEach(function (typeData) {
+            distType = distTypeTree.distTypes[distTypeTree.prefix + typeData.ID];
+            let parent = distTypeTree.distTypes[distTypeTree.prefix + typeData.ParentID];
+            if(parent){
+                distType.parent = parent;
+                parent.children.push(distType);
+            }
+        });
+        distTypeTree.distTypesArr.forEach(function (distTypeObj) {
+            if(distTypeObj.children.length === 0 && distTypeObj.data.fullName !== '普通机械' &&distTypeObj.data.fullName !== '机械组成物'
+            && distTypeObj.data.fullName !== '机上人工'){
+                distTypeTree.comboDatas.push({text: distTypeObj.data.fullName, value: distTypeObj.data.ID});
+            }
+            if(distTypeObj.data.fullName === '机械'){
+                distTypeTree.comboDatas.push({text: distTypeObj.data.fullName, value: distTypeObj.data.ID});
+            }
+        });
+        //me.distTypeTree = distTypeTree;
+        return distTypeTree;
+        //return distTypeTree.comboDatas;
+    },
+    getGljDistType: function (callback) {
+        let me = this;
+        $.ajax({
+            type: 'post',
+            url: "api/getGljDistType",
+            dataType: 'json',
+            success: function (result) {
+                if(!result.error && callback){
+                    me.distTypeTree = me.getComboData(result.data);
+                    let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
+                    combo.items(me.distTypeTree.comboDatas).editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);
+                    me.workBook.getSheet(0).getCell(-1, 5, GC.Spread.Sheets.SheetArea.viewport).cellType(combo).value(me.distTypeTree.comboDatas[0].text);
+                    callback();
+                }
+            }
+        })
+    },
     getGljTree: function(rationLibId) {
     getGljTree: function(rationLibId) {
         var me = this;
         var me = this;
         $.ajax({
         $.ajax({
@@ -89,6 +148,7 @@ repositoryGljObj = {
             success:function(result){
             success:function(result){
                 if(!result.error) {
                 if(!result.error) {
                     me.gljList = result.data;
                     me.gljList = result.data;
+                    me.workBook.getSheet(0).setRowCount(result.data.length);
                     me.sortGlj();
                     me.sortGlj();
                     me.showGljItems(result.data, me.gljCurTypeId);
                     me.showGljItems(result.data, me.gljCurTypeId);
                 }
                 }
@@ -104,52 +164,144 @@ repositoryGljObj = {
             var cacheSection = [];
             var cacheSection = [];
             var pArr = me.parentNodeIds["_pNodeId_" + type];
             var pArr = me.parentNodeIds["_pNodeId_" + type];
             for (var i = 0; i < data.length; i++) {
             for (var i = 0; i < data.length; i++) {
-                if (pArr && pArr.indexOf(data[i].gljType) >= 0) {
+                if (pArr && pArr.indexOf(data[i].gljClass) >= 0) {
                     cacheSection.push(data[i]);
                     cacheSection.push(data[i]);
-                } else if (type == data[i].gljType) {
+                } else if (type == data[i].gljClass) {
+                    //data[i].gljDistType = me.distTypeTree.distTypes[me.distTypeTree.prefix + data[i].gljDistType].data.fullName;
                     cacheSection.push(data[i]);
                     cacheSection.push(data[i]);
                 }
                 }
             }
             }
             sheetCommonObj.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
             sheetCommonObj.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
-            sheetCommonObj.showData(me.workBook.getSheet(0), me.setting, cacheSection);
+            sheetCommonObj.showData(me.workBook.getSheet(0), me.setting, cacheSection, me.distTypeTree);
             cacheSection = null;
             cacheSection = null;
         }
         }
     },
     },
     buildSheet: function(container) {
     buildSheet: function(container) {
         var me = repositoryGljObj;
         var me = repositoryGljObj;
-        me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);
+        me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30, me);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditStarting, me.onCellEditStart);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditStarting, me.onCellEditStart);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
+        me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onEnterCell);
     },
     },
+     onEnterCell: function (sender, args) {
+         let me = repositoryGljObj;
+         me.cellRowIdx = args.row;
+         let isHasData = false;
+         if(me.addGljObj){
+             for(let i=0; i<me.setting.header.length; i++){
+                 if(me.addGljObj[me.setting.header[i].dataCode]){
+                     isHasData = true;
+                     break;
+                 }
+             }
+         }
+         if(isHasData){
+             if(me.editingRowIdx !== me.cellRowIdx) {
+                 let isComple = true;
+                 let focusToCol;
+                 function getFocusToCol (me){
+                     if(!me.addGljObj[me.setting.header[0].dataCode]){
+                         return 0;
+                     }
+                    else if(!me.addGljObj[me.setting.header[5].dataCode]){
+                         return 5;
+                     }
+                     else {
+                         return -1;
+                     }
+                 }
+                 focusToCol = getFocusToCol(me);
+                 if(focusToCol === -1){
+
+                 }
+                 else {
+                    $('#gljAlertBtn').click();
+                     me.workBook.getSheet(0).options.isProtected = true;
+                     $('#aleCanceBtn').click(function () {
+                         me.workBook.getSheet(0).options.isProtected = false;
+                         me.workBook.getSheet(0).setActiveCell(me.editingRowIdx, focusToCol);
+                     });
+                     $('#gljAleClose').click(function () {
+                         me.workBook.getSheet(0).options.isProtected = false;
+                         me.workBook.getSheet(0).setActiveCell(me.editingRowIdx, focusToCol);
+                     });
+                     $('#aleConfBtn').click(function () {
+                         me.workBook.getSheet(0).options.isProtected = false;
+                         me.addGljObj = null;
+                         for(let col=0; col<me.setting.header.length; col++){
+                             me.workBook.getSheet(0).getCell(me.editingRowIdx, col).value('');
+                         }
+                         me.workBook.getSheet(0).setActiveCell(me.editingRowIdx, 0);
+                     });
+                 }
+             }
+         }
+     },
     onCellEditStart: function(sender, args) {
     onCellEditStart: function(sender, args) {
         var me = repositoryGljObj;
         var me = repositoryGljObj;
         var rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row);
         var rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row);
         me.currentEditingGlj = rObj;
         me.currentEditingGlj = rObj;
+        me.orgCode = me.workBook.getSheet(0).getValue(args.row, 0);
         var cacheSection = me.gljList;
         var cacheSection = me.gljList;
         if (cacheSection) {
         if (cacheSection) {
             for (var j = 0; j < cacheSection.length; j++) {
             for (var j = 0; j < cacheSection.length; j++) {
-                if (cacheSection[j][me.setting.header[0].dataCode] == rObj[me.setting.header[0].dataCode]) {
+                if (cacheSection[j][me.setting.header[0].dataCode] && cacheSection[j][me.setting.header[0].dataCode] == rObj[me.setting.header[0].dataCode]) {
                     rObj["ID"] = cacheSection[j]["ID"];
                     rObj["ID"] = cacheSection[j]["ID"];
+                    rObj.gljClass = cacheSection[j].gljClass;
                     break;
                     break;
                 }
                 }
             }
             }
         }
         }
     },
     },
     onCellEditEnd: function(sender, args) {
     onCellEditEnd: function(sender, args) {
-        var me = repositoryGljObj, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row),
+        var me = repositoryGljObj, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row, me),
             updateArr = [], addArr = [];
             updateArr = [], addArr = [];
+        me.editingRowIdx = args.row;
         if (me.currentEditingGlj["ID"]) {
         if (me.currentEditingGlj["ID"]) {
             rObj["ID"] = me.currentEditingGlj["ID"];
             rObj["ID"] = me.currentEditingGlj["ID"];
-            updateArr.push(rObj);
+            rObj.gljClass = me.currentEditingGlj.gljClass;
+            for(let col =0; col< me.setting.header.length; col++){
+                if(me.currentEditingGlj[me.setting.header[col].dataCode] !== rObj[me.setting.header[col].dataCode]){
+                    updateArr.push(rObj);
+                    break;
+                }
+            }
+            //update basePrice of ration when editting basePrice of glj
+            if(me.currentEditingGlj.basePrice !== rObj.basePrice){
+                let gljTypeParent = me.distTypeTree.distTypes[me.distTypeTree.prefix + me.currentEditingGlj.gljType],
+                    gljType = -1;
+                if(gljTypeParent && gljTypeParent.data.ID <=3){
+                    gljType = gljTypeParent.data.ID;
+                }
+                if(!gljTypeParent && me.currentEditingGlj.gljType <= 3){
+                    gljType = me.currentEditingGlj.gljType;
+                }
+                let gljBasePrcObj = {gljId: me.currentEditingGlj.ID, gljType: gljType, basePrice: rObj.basePrice};
+                if(gljBasePrcObj.gljType !== -1){
+                    //me.updateRationBasePrcRq(gljBasePrcObj);
+                }
+            }
         } else {
         } else {
-            addArr.push(rObj);
+            me.addGljObj = rObj;
+            let isCanSav = true;
+                if(!rObj[me.setting.header[0].dataCode] || !rObj[me.setting.header[5].dataCode]){
+                    isCanSav = false;
+                }
+            if(isCanSav){
+                me.addGljObj = null;
+                addArr.push(rObj);
+            }
+        }
+        if(me.gljCurTypeId !== 1){
+            rObj.gljClass = me.gljCurTypeId;
         }
         }
-        rObj.gljType = me.gljCurTypeId;
         me.currentEditingGlj = null;
         me.currentEditingGlj = null;
-        me.mixUpdateRequest(updateArr, addArr, []);
+        if(updateArr.length >0 || addArr.length >0){
+           me.mixUpdateRequest(updateArr, addArr, []);
+        }
     },
     },
     onRangeChanged: function(sender, args) {
     onRangeChanged: function(sender, args) {
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
@@ -211,6 +363,17 @@ repositoryGljObj = {
             me.mixUpdateRequest(updateArr, addArr, []);
             me.mixUpdateRequest(updateArr, addArr, []);
         }
         }
     },
     },
+    updateRationBasePrcRq: function (gljBasePrcObj) {
+        $.ajax({
+            type: 'post',
+            url: 'api/updateRationBasePrc',
+            data:{data: JSON.stringify({gljId: gljBasePrcObj.gljId, basePrice: gljBasePrcObj.basePrice})},
+            dataType: 'json',
+            success: function (result) {
+
+            }
+        });
+    },
     mixUpdateRequest: function(updateArr, addArr, removeIds) {
     mixUpdateRequest: function(updateArr, addArr, removeIds) {
         var me = repositoryGljObj;
         var me = repositoryGljObj;
         $.ajax({
         $.ajax({
@@ -229,6 +392,8 @@ repositoryGljObj = {
                     me.sortGlj();
                     me.sortGlj();
                     me.currentCache = me.getCache();
                     me.currentCache = me.getCache();
                     me.showGljItems(me.gljList, me.gljCurTypeId);
                     me.showGljItems(me.gljList, me.gljCurTypeId);
+                    console.log(`me.cC`);
+                    console.log(me.currentCache);
                 }
                 }
             },
             },
             error:function(err){
             error:function(err){
@@ -239,7 +404,7 @@ repositoryGljObj = {
     getCache: function() {
     getCache: function() {
         var me = this, rst = [];
         var me = this, rst = [];
         for (var i = 0; i < me.gljList.length; i++) {
         for (var i = 0; i < me.gljList.length; i++) {
-            if (me.gljList[i].gljType == me.gljCurTypeId) {
+            if (me.gljList[i].gljClass == me.gljCurTypeId) {
                 rst.push(me.gljList[i]);
                 rst.push(me.gljList[i]);
             }
             }
         }
         }
@@ -300,7 +465,8 @@ var gljTypeTreeOprObj = {
         me.currentCache = me.getCache();
         me.currentCache = me.getCache();
         me.showGljItems(me.gljList, gljTypeId);
         me.showGljItems(me.gljList, gljTypeId);
         if (me.parentNodeIds["_pNodeId_" + treeNode.ID]) {
         if (me.parentNodeIds["_pNodeId_" + treeNode.ID]) {
-            sheetCommonObj.shieldAllCells(me.workBook.getSheet(0), me.setting);
+            sheetCommonObj.lockCodeCells(me.workBook.getSheet(0), me.gljList.length);
+            //sheetCommonObj.shieldAllCells(me.workBook.getSheet(0), me.setting);
         } else {
         } else {
             sheetCommonObj.unShieldAllCells(me.workBook.getSheet(0));
             sheetCommonObj.unShieldAllCells(me.workBook.getSheet(0));
         }
         }

ファイルの差分が大きいため隠しています
+ 6 - 0
web/users/css/bootstrap.min.css


+ 296 - 0
web/users/css/style.css

@@ -0,0 +1,296 @@
+@charset "utf-8";
+/*
+1.登录
+2.主体框架
+3.侧栏主菜单
+4.内容区
+*/
+/*1.登录*/
+body{
+  background:#ededed
+}
+.loginItem {
+  padding:5px 20px 25px;
+  margin-bottom:20px;
+  background: #fff;
+  border-radius: 3px;
+  box-shadow: 0 2px 6px 0 rgba(0,0,0,.15)
+}
+.wraplogin {
+  width:690px;
+  margin:5% auto 0px;
+}
+.wraplogin .loginItem{
+  padding:0;
+  width:400px;
+  position: relative;
+  z-index: 1
+}
+.wraplogin .loginTop {
+  text-align: center;
+  color:#428BCA;
+  padding:30px 0;
+}
+.wraplogin .loginTop a{
+  font-size:30px
+}
+.wraplogin .loginTop a:hover{
+  text-decoration: none;
+}
+.wraplogin .loginForm{
+  padding: 20px 20px 10px
+}
+.wraplogin .loginBottom{
+  padding: 10px 20px 25px;
+  color: #ccc
+}
+/*2.主体框架*/
+.header {
+  background:#f4f5f5;
+  position: fixed;
+  z-index: 10;
+  width: 100%;
+  height: 50px;
+  top: 0;
+  left: 0;
+  border-bottom: 1px solid #ddd
+}
+.main{
+  position: relative;
+  z-index: 4;
+}
+.main-nav {
+  position: fixed;
+  z-index: 99;
+  width:124px;
+  left: 0;
+  top: 0;
+  height: 100%;
+  background: #f4f5f5;
+  border-right:1px solid #ddd;
+  box-shadow: 3px 0 10px 2px #e3e3e3
+}
+.main-panel{
+  padding-left:124px;
+  box-sizing: border-box;
+}
+.panel-sidebar{
+  box-sizing: border-box;
+  background: #fbfcfd;
+  position: fixed;
+  height: 100%;
+  z-index: 4;
+  left:124px;
+  padding-top: 100px;
+  border-right: 1px solid #ddd;
+  width: 200px
+}
+.panel-content{
+  padding:115px 0 0;
+  position: relative;
+  z-index: 3;
+  box-sizing: border-box;
+  overflow-y: auto;
+  height: 100vh;
+}
+.panel-content .content-wrap{
+  margin:0 15px 15px;
+}
+.panel-sidebar+.panel-content{
+  padding: 115px 0 0 200px;
+}
+.panel-title, .panel-title>.title-bar {
+  height:50px;
+  line-height: 50px
+}
+.panel-title{
+  position: fixed;
+  top: 50px;
+  z-index: 98;
+  width: 100%;
+  box-sizing: border-box;
+  background: #fff;
+  box-shadow: 0 1px 3px rgba(0,0,0,.05)
+}
+.panel-sidebar .panel-title{
+  width:200px;
+  border-right: 1px solid #ddd;
+  box-shadow: 0 1px 3px rgba(0,0,0,.1);
+}
+.panel-content .panel-title{
+  left: 0;
+  padding-left: 324px;
+  padding-right: 20px;
+}
+.panel-content .panel-title.fluid{
+  padding-left:124px
+}
+.panel-title>.title-bar{
+  padding-left: 20px
+}
+.panel-title>.title-bar>h2,.panel-title>.title-main>h2{
+  font-size: 16px;
+  margin:0;
+  height: 50px;
+  line-height: 50px;
+  display:block
+}
+.panel-title>.title-bar>h2 .btn{
+  margin-right:15px
+}
+.panel-title>.title-main .btn {
+  margin:0 0 0 20px
+}
+.panel-title>.title-main .btn.pull-right {
+  margin:10px 0 0 10px
+}
+.panel-title>.title-main{
+  padding-left: 15px
+}
+/*滚动*/
+.scrollbar-auto {
+    overflow-y: auto;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    top: 0;
+    right: 0;
+}
+.panel-sidebar .scrollbar-auto{
+    padding-top: 20px;
+    box-sizing: border-box;
+}
+.panel-sidebar .scrollbar-auto {
+    height: 100%;
+    width: 100%;
+    overflow-y: auto;
+    position: static;
+}
+/*头部*/
+.header .logo {
+  float: left;
+  margin-right: 20px;
+  margin:0
+}
+.header .logo>a{
+  height:50px;
+  line-height: 50px;
+  display: inline-block;
+  color:#337ab7;
+  font-size:20px;
+  padding:0 10px;
+  text-align: center
+}
+.header .logo>a:hover{
+  text-decoration: none;
+}
+.header-user > div {
+  float:left
+}
+.avatar .pic {
+  height: 35px;
+  width: 35px;
+  border-radius: 100%;
+  display: inline-block;
+  float:left;
+  margin:7px 7px 0 0
+}
+.avatar .pic img{
+  display: block;
+  width: 100%;
+  height: 100%;
+  border-radius: 100%;
+}
+.avatar > a{
+  display: block;
+  height:50px;
+  line-height: 50px;
+  color:#666;
+  padding:0 15px;
+  cursor: pointer;
+}
+.avatar > a:hover{
+  text-decoration: none;
+  box-shadow: inset 0 3px 5px rgba(0,0,0,.125)
+}
+.header .poj-name {
+  float:left;
+  height:50px;
+  line-height:50px;
+  padding:0 0 0 15px;
+  font-size:18px
+}
+.header .poj-name a{
+  color:#666
+}
+/*侧栏主菜单*/
+.nav-top{
+  padding-top: 50px
+}
+.bg-nav a{
+  color:#999;
+}
+.bg-nav > li.active > a{
+  border-radius: 0;
+  background: #666
+}
+.bg-nav > li > a:hover,.bg-nav > li.active > a:hover{
+  background: #999;
+  color:#f2f2f2;
+  border-radius: 0
+}
+.bg-nav > li + li {
+    margin-top:0;
+}
+.nav-box h3{
+  font-size: 14px;
+  font-weight: 700;
+  padding-bottom: 4px;
+  border-bottom: 1px solid #e2eaec;
+  padding-right: 15px;
+  margin-bottom: 10px;
+  margin-left: 20px
+}
+.nav-list li a{
+  color: #333;
+  display: block;
+  height: 35px;
+  line-height: 35px;
+  box-sizing: border-box;
+  padding-left: 17px;
+  padding-right: 45px;
+  text-overflow: ellipsis;
+  position: relative;
+}
+.nav-list li a:hover{
+  text-decoration: none;
+  background:#efefef;
+  cursor: pointer;
+}
+.nav-list li a .badge{
+  position: absolute;
+  right:17px;
+  top:9px
+}
+.nav-list li.active a{
+  background:#e1e1e1
+}
+.nav-list li.active .badge{
+  background:#207fd1
+}
+/*内容区*/
+.c-header {
+  padding:0 0 5px
+}
+.c-body{
+  padding:15px;
+  background:#fff;
+  box-shadow:0 1px 3px rgba(0,0,0,.05)
+}
+.form-group .necessary{
+  font-size:18px;
+  color:#f90000
+}
+.mb-30 {
+  margin-bottom:30px
+}

BIN
web/users/fonts/glyphicons-halflings-regular.eot


ファイルの差分が大きいため隠しています
+ 288 - 0
web/users/fonts/glyphicons-halflings-regular.svg


BIN
web/users/fonts/glyphicons-halflings-regular.ttf


BIN
web/users/fonts/glyphicons-halflings-regular.woff


BIN
web/users/fonts/glyphicons-halflings-regular.woff2


+ 49 - 0
web/users/js/admin.js

@@ -0,0 +1,49 @@
+/**
+ * 后台用户修改相关js
+ *
+ * @author CaiAoLin
+ * @date 2017/6/6
+ * @version
+ */
+let rules = {
+    newPassword: {
+        required: true,
+        minlength: 6
+    },
+    password: {
+        required: true,
+        minlength: 4
+    }
+};
+$(document).ready(function() {
+
+    // 新增只有前端需要的验证规则
+    rules.confirmPassword = {
+        required: true,
+        equalTo: "input[name='newPassword']"
+    };
+
+    // 表单验证规则
+    $("#save-form").validate({
+        rules: rules,
+        errorPlacement: function(error, element) {
+            error.addClass('help-block');
+            let parentEle = $(element).parent();
+            parentEle.addClass('has-warning');
+            $(element).prev('label').addClass('control-label');
+            $(element).after('<span class="glyphicon glyphicon-warning-sign form-control-feedback" aria-hidden="true"></span>');
+            $(element).after(error);
+        },
+        errorElement: "span",
+        success: function(element) {
+            $(element).parent().removeClass('has-warning');
+            $(element).siblings('.glyphicon-warning-sign').remove();
+        }
+    });
+
+    // 保存数据
+    $("#save").click(function() {
+        $("#save-form").attr('action', '/manager/admin').submit();
+    });
+
+});

+ 29 - 0
web/users/js/global.js

@@ -0,0 +1,29 @@
+/*自动高度*/
+function autoFlashHeight() {
+    $(".wrapContent").height($(window).height() - 48);
+    $(".mainContent").height($(window).height() - 48);
+    $(".scollContent").height($(window).height() - 130);
+    $(".slideContent").height($(window).height() - 46);
+};
+$(window).resize(autoFlashHeight);
+$(function () {
+    /*登录页*/
+    function waveloop1() {
+        $("#wave_bg_1").css({"left": "-236px"}).animate({"left": "-1233px"}, 25000, 'linear', waveloop1);
+    }
+
+    function waveloop2() {
+        $("#wave_bg_2").css({"left": "0px"}).animate({"left": "-1009px"}, 60000, 'linear', waveloop2);
+    }
+
+    waveloop1();
+    waveloop2();
+    /*工具提示*/
+    $(function () {
+        $('[data-toggle="tooltip"]').tooltip()
+    });
+    $(function () {
+        $('[data-toggle="popover"]').popover()
+    });
+
+});

+ 657 - 0
web/users/js/lib/bootstrap-paginator.js

@@ -0,0 +1,657 @@
+/**
+ * bootstrap-paginator.js v0.5
+ * --
+ * Copyright 2013 Yun Lai <lyonlai1984@gmail.com>
+ * --
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function ($) {
+
+    "use strict"; // jshint ;_;
+
+
+    /* Paginator PUBLIC CLASS DEFINITION
+     * ================================= */
+
+    /**
+     * Boostrap Paginator Constructor
+     *
+     * @param element element of the paginator
+     * @param options the options to config the paginator
+     *
+     * */
+    var BootstrapPaginator = function (element, options) {
+        this.init(element, options);
+    },
+        old = null;
+
+    BootstrapPaginator.prototype = {
+
+        /**
+         * Initialization function of the paginator, accepting an element and the options as parameters
+         *
+         * @param element element of the paginator
+         * @param options the options to config the paginator
+         *
+         * */
+        init: function (element, options) {
+
+            this.$element = $(element);
+
+            var version = (options && options.bootstrapMajorVersion) ? options.bootstrapMajorVersion : $.fn.bootstrapPaginator.defaults.bootstrapMajorVersion,
+                id = this.$element.attr("id");
+
+            if (version === 2 && !this.$element.is("div")) {
+
+                throw "in Bootstrap version 2 the pagination must be a div element. Or if you are using Bootstrap pagination 3. Please specify it in bootstrapMajorVersion in the option";
+            } else if (version > 2 && !this.$element.is("ul")) {
+                throw "in Bootstrap version 3 the pagination root item must be an ul element."
+            }
+
+
+
+            this.currentPage = 1;
+
+            this.lastPage = 1;
+
+            this.setOptions(options);
+
+            this.initialized = true;
+        },
+
+        /**
+         * Update the properties of the paginator element
+         *
+         * @param options options to config the paginator
+         * */
+        setOptions: function (options) {
+
+            this.options = $.extend({}, (this.options || $.fn.bootstrapPaginator.defaults), options);
+
+            this.totalPages = parseInt(this.options.totalPages, 10);  //setup the total pages property.
+            this.numberOfPages = parseInt(this.options.numberOfPages, 10); //setup the numberOfPages to be shown
+
+            //move the set current page after the setting of total pages. otherwise it will cause out of page exception.
+            if (options && typeof (options.currentPage)  !== 'undefined') {
+
+                this.setCurrentPage(options.currentPage);
+            }
+
+            this.listen();
+
+            //render the paginator
+            this.render();
+
+            if (!this.initialized && this.lastPage !== this.currentPage) {
+                this.$element.trigger("page-changed", [this.lastPage, this.currentPage]);
+            }
+
+        },
+
+        /**
+         * Sets up the events listeners. Currently the pageclicked and pagechanged events are linked if available.
+         *
+         * */
+        listen: function () {
+
+            this.$element.off("page-clicked");
+
+            this.$element.off("page-changed");// unload the events for the element
+
+            if (typeof (this.options.onPageClicked) === "function") {
+                this.$element.bind("page-clicked", this.options.onPageClicked);
+            }
+
+            if (typeof (this.options.onPageChanged) === "function") {
+                this.$element.on("page-changed", this.options.onPageChanged);
+            }
+
+            this.$element.bind("page-clicked", this.onPageClicked);
+        },
+
+
+        /**
+         *
+         *  Destroys the paginator element, it unload the event first, then empty the content inside.
+         *
+         * */
+        destroy: function () {
+
+            this.$element.off("page-clicked");
+
+            this.$element.off("page-changed");
+
+            this.$element.removeData('bootstrapPaginator');
+
+            this.$element.empty();
+
+        },
+
+        /**
+         * Shows the page
+         *
+         * */
+        show: function (page) {
+
+            this.setCurrentPage(page);
+
+            this.render();
+
+            if (this.lastPage !== this.currentPage) {
+                this.$element.trigger("page-changed", [this.lastPage, this.currentPage]);
+            }
+        },
+
+        /**
+         * Shows the next page
+         *
+         * */
+        showNext: function () {
+            var pages = this.getPages();
+
+            if (pages.next) {
+                this.show(pages.next);
+            }
+
+        },
+
+        /**
+         * Shows the previous page
+         *
+         * */
+        showPrevious: function () {
+            var pages = this.getPages();
+
+            if (pages.prev) {
+                this.show(pages.prev);
+            }
+
+        },
+
+        /**
+         * Shows the first page
+         *
+         * */
+        showFirst: function () {
+            var pages = this.getPages();
+
+            if (pages.first) {
+                this.show(pages.first);
+            }
+
+        },
+
+        /**
+         * Shows the last page
+         *
+         * */
+        showLast: function () {
+            var pages = this.getPages();
+
+            if (pages.last) {
+                this.show(pages.last);
+            }
+
+        },
+
+        /**
+         * Internal on page item click handler, when the page item is clicked, change the current page to the corresponding page and
+         * trigger the pageclick event for the listeners.
+         *
+         *
+         * */
+        onPageItemClicked: function (event) {
+
+            var type = event.data.type,
+                page = event.data.page;
+
+            this.$element.trigger("page-clicked", [event, type, page]);
+
+        },
+
+        onPageClicked: function (event, originalEvent, type, page) {
+
+            //show the corresponding page and retrieve the newly built item related to the page clicked before for the event return
+
+            var currentTarget = $(event.currentTarget);
+
+            switch (type) {
+            case "first":
+                currentTarget.bootstrapPaginator("showFirst");
+                break;
+            case "prev":
+                currentTarget.bootstrapPaginator("showPrevious");
+                break;
+            case "next":
+                currentTarget.bootstrapPaginator("showNext");
+                break;
+            case "last":
+                currentTarget.bootstrapPaginator("showLast");
+                break;
+            case "page":
+                currentTarget.bootstrapPaginator("show", page);
+                break;
+            }
+
+        },
+
+        /**
+         * Renders the paginator according to the internal properties and the settings.
+         *
+         *
+         * */
+        render: function () {
+
+            //fetch the container class and add them to the container
+            var containerClass = this.getValueFromOption(this.options.containerClass, this.$element),
+                size = this.options.size || "normal",
+                alignment = this.options.alignment || "left",
+                pages = this.getPages(),
+                listContainer = this.options.bootstrapMajorVersion === 2 ? $("<ul></ul>") : this.$element,
+                listContainerClass = this.options.bootstrapMajorVersion === 2 ? this.getValueFromOption(this.options.listContainerClass, listContainer) : null,
+                first = null,
+                prev = null,
+                next = null,
+                last = null,
+                p = null,
+                i = 0;
+
+
+            this.$element.prop("class", "");
+
+            this.$element.addClass("pagination");
+
+            switch (size.toLowerCase()) {
+            case "large":
+            case "small":
+            case "mini":
+                this.$element.addClass($.fn.bootstrapPaginator.sizeArray[this.options.bootstrapMajorVersion][size.toLowerCase()]);
+                break;
+            default:
+                break;
+            }
+
+            if (this.options.bootstrapMajorVersion === 2) {
+                switch (alignment.toLowerCase()) {
+                case "center":
+                    this.$element.addClass("pagination-centered");
+                    break;
+                case "right":
+                    this.$element.addClass("pagination-right");
+                    break;
+                default:
+                    break;
+                }
+            }
+
+
+            this.$element.addClass(containerClass);
+
+            //empty the outter most container then add the listContainer inside.
+            this.$element.empty();
+
+            if (this.options.bootstrapMajorVersion === 2) {
+                this.$element.append(listContainer);
+
+                listContainer.addClass(listContainerClass);
+            }
+
+            //update the page element reference
+            this.pageRef = [];
+
+            if (pages.first) {//if the there is first page element
+                first = this.buildPageItem("first", pages.first);
+
+                if (first) {
+                    listContainer.append(first);
+                }
+
+            }
+
+            if (pages.prev) {//if the there is previous page element
+
+                prev = this.buildPageItem("prev", pages.prev);
+
+                if (prev) {
+                    listContainer.append(prev);
+                }
+
+            }
+
+
+            for (i = 0; i < pages.length; i = i + 1) {//fill the numeric pages.
+
+                p = this.buildPageItem("page", pages[i]);
+
+                if (p) {
+                    listContainer.append(p);
+                }
+            }
+
+            if (pages.next) {//if there is next page
+
+                next = this.buildPageItem("next", pages.next);
+
+                if (next) {
+                    listContainer.append(next);
+                }
+            }
+
+            if (pages.last) {//if there is last page
+
+                last = this.buildPageItem("last", pages.last);
+
+                if (last) {
+                    listContainer.append(last);
+                }
+            }
+        },
+
+        /**
+         *
+         * Creates a page item base on the type and page number given.
+         *
+         * @param page page number
+         * @param type type of the page, whether it is the first, prev, page, next, last
+         *
+         * @return Object the constructed page element
+         * */
+        buildPageItem: function (type, page) {
+
+            var itemContainer = $("<li></li>"),//creates the item container
+                itemContent = $("<a></a>"),//creates the item content
+                text = "",
+                title = "",
+                itemContainerClass = this.options.itemContainerClass(type, page, this.currentPage),
+                itemContentClass = this.getValueFromOption(this.options.itemContentClass, type, page, this.currentPage),
+                tooltipOpts = null;
+
+
+            switch (type) {
+
+            case "first":
+                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }
+                text = this.options.itemTexts(type, page, this.currentPage);
+                title = this.options.tooltipTitles(type, page, this.currentPage);
+                break;
+            case "last":
+                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }
+                text = this.options.itemTexts(type, page, this.currentPage);
+                title = this.options.tooltipTitles(type, page, this.currentPage);
+                break;
+            case "prev":
+                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }
+                text = this.options.itemTexts(type, page, this.currentPage);
+                title = this.options.tooltipTitles(type, page, this.currentPage);
+                break;
+            case "next":
+                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }
+                text = this.options.itemTexts(type, page, this.currentPage);
+                title = this.options.tooltipTitles(type, page, this.currentPage);
+                break;
+            case "page":
+                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }
+                text = this.options.itemTexts(type, page, this.currentPage);
+                title = this.options.tooltipTitles(type, page, this.currentPage);
+                break;
+            }
+
+            itemContainer.addClass(itemContainerClass).append(itemContent);
+
+            itemContent.addClass(itemContentClass).html(text).on("click", null, {type: type, page: page}, $.proxy(this.onPageItemClicked, this));
+
+            if (this.options.pageUrl) {
+                itemContent.attr("href", this.getValueFromOption(this.options.pageUrl, type, page, this.currentPage));
+            }
+
+            if (this.options.useBootstrapTooltip) {
+                tooltipOpts = $.extend({}, this.options.bootstrapTooltipOptions, {title: title});
+
+                itemContent.tooltip(tooltipOpts);
+            } else {
+                itemContent.attr("title", title);
+            }
+
+            return itemContainer;
+
+        },
+
+        setCurrentPage: function (page) {
+            if (page > this.totalPages || page < 1) {// if the current page is out of range, throw exception.
+
+                throw "Page out of range";
+
+            }
+
+            this.lastPage = this.currentPage;
+
+            this.currentPage = parseInt(page, 10);
+
+        },
+
+        /**
+         * Gets an array that represents the current status of the page object. Numeric pages can be access via array mode. length attributes describes how many numeric pages are there. First, previous, next and last page can be accessed via attributes first, prev, next and last. Current attribute marks the current page within the pages.
+         *
+         * @return object output objects that has first, prev, next, last and also the number of pages in between.
+         * */
+        getPages: function () {
+
+            var totalPages = this.totalPages,// get or calculate the total pages via the total records
+                pageStart = (this.currentPage % this.numberOfPages === 0) ? (parseInt(this.currentPage / this.numberOfPages, 10) - 1) * this.numberOfPages + 1 : parseInt(this.currentPage / this.numberOfPages, 10) * this.numberOfPages + 1,//calculates the start page.
+                output = [],
+                i = 0,
+                counter = 0;
+
+            pageStart = pageStart < 1 ? 1 : pageStart;//check the range of the page start to see if its less than 1.
+
+            for (i = pageStart, counter = 0; counter < this.numberOfPages && i <= totalPages; i = i + 1, counter = counter + 1) {//fill the pages
+                output.push(i);
+            }
+
+            output.first = 1;//add the first when the current page leaves the 1st page.
+
+            if (this.currentPage > 1) {// add the previous when the current page leaves the 1st page
+                output.prev = this.currentPage - 1;
+            } else {
+                output.prev = 1;
+            }
+
+            if (this.currentPage < totalPages) {// add the next page when the current page doesn't reach the last page
+                output.next = this.currentPage + 1;
+            } else {
+                output.next = totalPages;
+            }
+
+            output.last = totalPages;// add the last page when the current page doesn't reach the last page
+
+            output.current = this.currentPage;//mark the current page.
+
+            output.total = totalPages;
+
+            output.numberOfPages = this.options.numberOfPages;
+
+            return output;
+
+        },
+
+        /**
+         * Gets the value from the options, this is made to handle the situation where value is the return value of a function.
+         *
+         * @return mixed value that depends on the type of parameters, if the given parameter is a function, then the evaluated result is returned. Otherwise the parameter itself will get returned.
+         * */
+        getValueFromOption: function (value) {
+
+            var output = null,
+                args = Array.prototype.slice.call(arguments, 1);
+
+            if (typeof value === 'function') {
+                output = value.apply(this, args);
+            } else {
+                output = value;
+            }
+
+            return output;
+
+        }
+
+    };
+
+
+    /* TYPEAHEAD PLUGIN DEFINITION
+     * =========================== */
+
+    old = $.fn.bootstrapPaginator;
+
+    $.fn.bootstrapPaginator = function (option) {
+
+        var args = arguments,
+            result = null;
+
+        $(this).each(function (index, item) {
+            var $this = $(item),
+                data = $this.data('bootstrapPaginator'),
+                options = (typeof option !== 'object') ? null : option;
+
+            if (!data) {
+                data = new BootstrapPaginator(this, options);
+
+                $this = $(data.$element);
+
+                $this.data('bootstrapPaginator', data);
+
+                return;
+            }
+
+            if (typeof option === 'string') {
+
+                if (data[option]) {
+                    result = data[option].apply(data, Array.prototype.slice.call(args, 1));
+                } else {
+                    throw "Method " + option + " does not exist";
+                }
+
+            } else {
+                result = data.setOptions(option);
+            }
+        });
+
+        return result;
+
+    };
+
+    $.fn.bootstrapPaginator.sizeArray = {
+
+        "2": {
+            "large": "pagination-large",
+            "small": "pagination-small",
+            "mini": "pagination-mini"
+        },
+        "3": {
+            "large": "pagination-lg",
+            "small": "pagination-sm",
+            "mini": ""
+        }
+
+    };
+
+    $.fn.bootstrapPaginator.defaults = {
+        containerClass: "",
+        size: "normal",
+        alignment: "left",
+        bootstrapMajorVersion: 2,
+        listContainerClass: "",
+        itemContainerClass: function (type, page, current) {
+            return (page === current) ? "active" : "";
+        },
+        itemContentClass: function (type, page, current) {
+            return "";
+        },
+        currentPage: 1,
+        numberOfPages: 5,
+        totalPages: 1,
+        pageUrl: function (type, page, current) {
+            return null;
+        },
+        onPageClicked: null,
+        onPageChanged: null,
+        useBootstrapTooltip: false,
+        shouldShowPage: function (type, page, current) {
+
+            var result = true;
+
+            switch (type) {
+            case "first":
+                result = (current !== 1);
+                break;
+            case "prev":
+                result = (current !== 1);
+                break;
+            case "next":
+                result = (current !== this.totalPages);
+                break;
+            case "last":
+                result = (current !== this.totalPages);
+                break;
+            case "page":
+                result = true;
+                break;
+            }
+
+            return result;
+
+        },
+        itemTexts: function (type, page, current) {
+            switch (type) {
+            case "first":
+                return "&lt;&lt;";
+            case "prev":
+                return "&lt;";
+            case "next":
+                return "&gt;";
+            case "last":
+                return "&gt;&gt;";
+            case "page":
+                return page;
+            }
+        },
+        tooltipTitles: function (type, page, current) {
+
+            switch (type) {
+            case "first":
+                return "Go to first page";
+            case "prev":
+                return "Go to previous page";
+            case "next":
+                return "Go to next page";
+            case "last":
+                return "Go to last page";
+            case "page":
+                return (page === current) ? "Current page is " + page : "Go to page " + page;
+            }
+        },
+        bootstrapTooltipOptions: {
+            animation: true,
+            html: true,
+            placement: 'top',
+            selector: false,
+            title: "",
+            container: false
+        }
+    };
+
+    $.fn.bootstrapPaginator.Constructor = BootstrapPaginator;
+
+
+
+}(window.jQuery));

ファイルの差分が大きいため隠しています
+ 7 - 0
web/users/js/lib/bootstrap.min.js


ファイルの差分が大きいため隠しています
+ 1578 - 0
web/users/js/lib/jquery.validate.js


+ 33 - 0
web/users/js/lib/messages_zh.js

@@ -0,0 +1,33 @@
+(function( factory ) {
+	if ( typeof define === "function" && define.amd ) {
+		define( ["jquery", "../jquery.validate"], factory );
+	} else {
+		factory( jQuery );
+	}
+}(function( $ ) {
+
+/*
+ * Translated default messages for the jQuery validation plugin.
+ * Locale: ZH (Chinese, 中文 (Zhōngwén), 汉语, 漢語)
+ */
+$.extend($.validator.messages, {
+	required: "这是必填字段",
+	remote: "请修正此字段",
+	email: "请输入有效的电子邮件地址",
+	url: "请输入有效的网址",
+	date: "请输入有效的日期",
+	dateISO: "请输入有效的日期 (YYYY-MM-DD)",
+	number: "请输入有效的数字",
+	digits: "只能输入数字",
+	creditcard: "请输入有效的信用卡号码",
+	equalTo: "你的输入不相同",
+	extension: "请输入有效的后缀",
+	maxlength: $.validator.format("最多可以输入 {0} 个字符"),
+	minlength: $.validator.format("最少要输入 {0} 个字符"),
+	rangelength: $.validator.format("请输入长度在 {0} 到 {1} 之间的字符串"),
+	range: $.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),
+	max: $.validator.format("请输入不大于 {0} 的数值"),
+	min: $.validator.format("请输入不小于 {0} 的数值")
+});
+
+}));

+ 14 - 0
web/users/js/lib/validate.extend.js

@@ -0,0 +1,14 @@
+/**
+ * jQuery validate 自定义验证
+ *
+ * @author CaiAoLin
+ * @date 2017/6/8
+ * @version
+ */
+
+//检测手机号是否正确
+jQuery.validator.addMethod("isMobile", function (value, element) {
+    let length = value.length;
+    let regPhone = /^1([34578]\d)\d{8}$/;
+    return this.optional(element) || (length == 11 && regPhone.test(value));
+}, "请正确填写您的手机号码");

+ 79 - 0
web/users/js/login.js

@@ -0,0 +1,79 @@
+/**
+ * 登录相关js
+ *
+ * @author CaiAoLin
+ * @date 2017/6/1
+ * @version
+ */
+let rules = {
+    username: {
+        required: true,
+        minlength: 2
+    },
+    password:{
+        required: true,
+        minlength: 4
+    }
+};
+$(document).ready(function() {
+    $("#login-form").validate({
+        rules: rules,
+        errorPlacement: function(error, element) {
+            error.addClass('help-block');
+            let parentEle = $(element).parent();
+            parentEle.parent().addClass('has-error');
+            $(element).parent().after(error);
+        },
+        errorElement: "span",
+        success: function(element) {
+            $("#common-error").remove();
+            $(element).parent().removeClass('has-error');
+        }
+    });
+
+    // 登录操作
+    let isLogin = false;
+    $("#login").click(function() {
+        if (isLogin) {
+            return false;
+        }
+        // 验证数据
+        if (!$("#login-form").valid()) {
+            return false;
+        }
+        let username = $("#username").val();
+        let password = $("#password").val();
+        $.ajax({
+            url: '/login/login',
+            type: 'post',
+            data: {username: username, password: password},
+            dataType: 'json',
+            error: function() {
+                isLogin = false;
+            },
+            beforeSend: function() {
+                isLogin = true;
+            },
+            success: function(response) {
+                isLogin = false;
+                if (response.error === 0) {
+                    // 正确则跳转
+                    window.location.href = '/dashboard';
+                } else {
+                    // 错误则提示
+                    show_error(response.msg);
+                }
+            }
+        });
+    });
+});
+/**
+ * 显示错误
+ *
+ * @param {string} msg
+ * @return {void}
+ */
+function show_error(msg) {
+    $("form > .form-group").addClass('has-error');
+    $("input").last().parent().after('<span id="common-error" class="error help-block">'+ msg +'</span>');
+}

+ 80 - 0
web/users/js/manager.js

@@ -0,0 +1,80 @@
+/**
+ * 后台管理相关js
+ *
+ * @author CaiAoLin
+ * @date 2017/7/25
+ * @version
+ */
+$(document).ready(function() {
+    let selectId = '';
+    // 编辑用户
+    $(".edit").click(function() {
+        // 获取当前点击的数据
+        let canLogin = $(this).data('login');
+        if (!canLogin) {
+            $("input[name='can_login']").attr('checked', 'checked');
+        } else {
+            $("input[name='can_login']").removeAttr('checked');
+        }
+
+        // 获取权限
+        let permission = $(this).data('permission');
+        permission = permission.split(',');
+
+        $("input[name='permission[]']").each(function(index) {
+            let permissionName = $(this).data('permission');
+
+            if (permission.indexOf(permissionName) < 0) {
+                $(this).removeAttr('checked');
+                return true;
+            }
+            $(this).attr('checked', 'checked');
+        });
+
+        selectId = $(this).data('id');
+        $('#edit-account').modal('show');
+    });
+
+
+    // 编辑后保存
+    let isSaving = false;
+    $("#save-manager").click(function() {
+        if (selectId === '' || isSaving) {
+            return false;
+        }
+
+        // 获取权限
+        let permission = [];
+        $("input[name='permission[]']:checked").each(function(index) {
+            let permissionName = $(this).data('permission');
+            permission.push(permissionName);
+        });
+        permission = permission.join(',');
+
+        // 获取是否可登录
+        let login = $("input[name='can_login']").is(':checked');
+
+        $.ajax({
+            url: '/manager/modify/' + selectId,
+            type: 'post',
+            data: {permission: permission, login: login ? 0 : 1},
+            dataType: 'json',
+            error: function() {
+                isSaving = false;
+            },
+            beforeSend: function() {
+                isSaving = true;
+            },
+            success: function(response) {
+                isSaving = false;
+                if (response.err === 0) {
+                    $('#edit-account').modal('hide');
+                } else {
+                    let msg = response.msg === undefined ? '未知错误' : response.msg;
+                    alert(msg);
+                }
+            }
+        });
+    });
+
+});

+ 0 - 88
web/users/login-infoinput.html

@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-
-<head>
-    <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="css/bootstrap/bootstrap.min.css">
-    <link rel="stylesheet" href="css/bootstrap/themes.css">
-    <link rel="stylesheet" href="css/main.css">
-    <link rel="stylesheet" href="css/font-awesome/font-awesome.min.css">
-</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=" d-inline-block">
-                    <button class="btn btn-link btn-sm " type="button">15812644017</button>
-                </div>
-                <span class="btn btn-link btn-sm new-msg">
-                  <i class="fa fa-envelope-o" aria-hidden="true"></i>&nbsp;2
-                </span>
-                <button class="btn btn-link btn-sm">注销</button>
-            </div>
-        </nav>
-    </div>
-    <div class="container mt-3">
-        <div class="row">
-            <div class="col-lg-8 offset-lg-2">
-                <div class="card newuser-input">
-                    <div class="card-block">
-                        <h4 class="card-title">在开始使用前,请填写以下信息。</h4>
-                        <h6 class="card-subtitle text-muted">详细填写这些信息,可以让我们更好的服务您。</h6>
-                    </div>
-                    <div class="card-block">
-                            <div class="form-group">
-                                <input class="form-control" placeholder="你的姓名" required="" autofocus="">
-                            </div>
-                            <div class="form-group">
-                                <input class="form-control" placeholder="企业名称" required="" autofocus="">
-                            </div>
-                            <div class="form-group">
-                                <select class="form-control">
-                                  <option>请选择企业所在地区</option>
-                                  <option>广东省</option>
-                                  <option>北京市</option>
-                                </select>
-                            </div>
-                        <div class="form-group">
-                            <a class="btn btn-link" data-toggle="collapse" href="#moreinfo" aria-expanded="false" aria-controls="moreinfo">更多选项</a>
-                        </div>
-                        <div class="collapse" id="moreinfo">
-                                <div class="form-group">
-                                    <select class="form-control">
-                                     <option>请选择企业类型</option>
-                                     <option>设计</option>
-                                     <option>施工</option>
-                                   </select>
-                                </div>
-                                <div class="form-group">
-                                    <select class="form-control">
-                                     <option>请选择企业规模</option>
-                                     <option>1-20</option>
-                                     <option>20-50</option>
-                                     <option>50-100</option>
-                                     <option>100+</option>
-                                   </select>
-                                </div>
-                        </div>
-                        <div class="form-group">
-                            <a class="btn btn-primary btn-block" href="login-welcome.html">下一步</a>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- JS. -->
-    <script src="js/jquery/jquery.min.js"></script>
-    <script src="js/tether/tether.min.js"></script>
-    <script src="js/bootstrap/bootstrap.min.js"></script>
-    <script src="js/global.js"></script>
-</body>
-
-</html>

+ 0 - 296
web/users/login-welcome.html

@@ -1,296 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-
-<head>
-    <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="css/bootstrap/bootstrap.min.css">
-    <link rel="stylesheet" href="css/bootstrap/themes.css">
-    <link rel="stylesheet" href="css/main.css">
-    <link rel="stylesheet" href="css/font-awesome/font-awesome.min.css">
-</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="navbar-text pt-0">
-          <div class="dropdown d-inline-block">
-              <button class="btn btn-link btn-sm dropdown-toggle" type="button" data-toggle="dropdown">陈特</button>
-              <div class="dropdown-menu dropdown-menu-right">
-                  <a class="dropdown-item" href="user-info.html" target="_blank">账号资料</a>
-                  <a class="dropdown-item" href="user-buy.html" target="_blank">产品购买</a>
-                  <a class="dropdown-item" href="user-set.html" 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>
-          <button class="btn btn-link btn-sm">注销</button>
-      </div>
-    </nav>
-      <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
-        <ul class="nav navbar-nav px-1">
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="http://example.com" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">文件</a>
-                <div class="dropdown-menu" aria-labelledby="supportedContentDropdown">
-                    <a class="dropdown-item" href="#">Action</a>
-                    <a class="dropdown-item" href="#">Another action</a>
-                    <a class="dropdown-item" href="#">Something else here</a>
-                </div>
-            </li>
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑</a>
-                <div class="dropdown-menu">
-                    <a class="dropdown-item" href="#">Action</a>
-                    <a class="dropdown-item" href="#">Another action</a>
-                    <a class="dropdown-item" href="#">Something else here</a>
-                </div>
-            </li>
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">工具</a>
-                <div class="dropdown-menu">
-                    <a class="dropdown-item" href="#">Action</a>
-                    <a class="dropdown-item" href="#">Another action</a>
-                    <a class="dropdown-item" href="#">Something else here</a>
-                </div>
-            </li>
-            <li class="nav-item">
-                <a class="nav-link" href="#" aria-haspopup="true" aria-expanded="false">帮助</a>
-            </li>
-        </ul>
-        <form class="form-inline">
-            <input class="form-control form-control-sm mr-1" type="text" placeholder="告诉我你想做什么">
-        </form>
-    </nav>
-    </div>
-    <div class="main">
-        <div class="poj-manage container-fluid">
-            <div class="row">
-                <div class="col-lg-2">
-                    <div class="poj-cate">
-                        <input type="text" class="mt-1 mb-1 form-control form-control-sm" placeholder="搜索所有工程">
-                        <ul class="nav nav-pills flex-column">
-                            <li class="nav-item">
-                                <a class="nav-link active" href="#">全部</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">最近使用</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">共享</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">协同工作</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">归档</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">回收站</a>
-                            </li>
-                        </ul>
-                    </div>
-                </div>
-                <div class="col-lg-10">
-                    <div class="toolsbar">
-                        <div class="tools-btn btn-group align-top">
-                            <a href="" class="btn btn-sm">新建工程</a>
-                            <a href="" class="btn btn-sm"><i class="fa fa-folder-o"></i>&nbsp;新建文件夹</a>
-                            <a href="" class="btn btn-sm">重命名</a>
-                            <a href="" class="btn btn-sm">删除</a>
-                            <a href="" class="btn btn-sm">移动到...</a>
-                            <a href="" class="btn btn-sm">复制到...</a>
-                            <a href="" class="btn btn-sm">共享</a>
-                            <a href="" class="btn btn-sm">协同</a>
-                        </div>
-                    </div>
-                    <div class="poj-list">
-                        <legend>全部</legend>
-                        <table class="table table-hover table-sm">
-                            <thead>
-                                <tr>
-                                    <th width="40"></th>
-                                    <th width="38%"></th>
-                                    <th width="40%">工程名称</th>
-                                    <th width="10%">最近使用</th>
-                                    <th width="10%">创建日期</th>
-                                </tr>
-                            </thead>
-                            <tbody>
-                                <tr>
-                                    <td></td>
-                                    <td><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;XX项目文件夹</td>
-                                    <td></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="pl-1"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;XX项目文件夹</td>
-                                    <td></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="pl-2"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;<a href="#">某某某某工厂工厂某某工厂建设某某工厂建设</a></td>
-                                    <td></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="pl-3"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;<a href="#" class="open-sidebar">1号生产车间(click)</a></td>
-                                    <td></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td><i class="fa fa-sort" data-toggle="tooltip" data-placement="top" title="长安拖动"></i></td>
-                                    <td></td>
-                                    <td><a href="zaojiashu.html">建筑工程(click)</a></td>
-                                    <td>2016-01-01</td>
-                                    <td>2016-01-01</td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td></td>
-                                    <td><a href="#">机械设备安装工程</a></td>
-                                    <td>2016-01-01</td>
-                                    <td>2016-01-01</td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="pl-2"><a href="#" class="tree-close" title="展开"><i class="fa fa-plus-square-o  mr-1"></i></a><i class="fa fa-folder-o"></i>&nbsp;<a href="#">2号生产车间</a></td>
-                                    <td>......</td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                            </tbody>
-                        </table>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <div class="slide-sidebar">
-            <div class="side-content">
-                <div class="p-1">
-                    <legend>1号生产车间 汇总</legend>
-                    <table class="table table-bordered table-hover table-sm">
-                        <thead>
-                            <tr>
-                                <th rowspan="2"></th>
-                                <th rowspan="2">序号</th>
-                                <th rowspan="2">名称</th>
-                                <th rowspan="2">金额</th>
-                                <th colspan="6">其中</th>
-                                <th rowspan="2">占造价比例(%)</th>
-                                <th rowspan="2">建筑面积</th>
-                                <th rowspan="2">单方造价</th>
-                            </tr>
-                            <tr>
-                                <th>分部分项合计</th>
-                                <th>措施项目合计</th>
-                                <th>其他项目合计</th>
-                                <th>安全文明施工费</th>
-                                <th>规费</th>
-                                <th>税金</th>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            <tr>
-                                <td>1</td>
-                                <td>一</td>
-                                <td>建筑工程</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                            </tr>
-                            <tr>
-                                <td>2</td>
-                                <td>二</td>
-                                <td>建筑工程</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                            </tr>
-                            <tr>
-                                <td>3</td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                            </tr>
-                            <tr>
-                                <td>4</td>
-                                <td>一</td>
-                                <td>合计</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                            </tr>
-                        </tbody>
-                    </table>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出信息-->
-    <div class="modal fade" id="myModal" data-backdrop="static">
-        <div class="modal-dialog modal-lg" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                    <h5 class="modal-title">欢迎使用Smartcost</h5>
-                </div>
-                <div class="modal-body">
-                    <p>推送内容在这</p>
-                </div>
-                <div class="modal-footer text-xs-center">
-                    <a href="project-management.html" class="btn btn-primary btn-lg">开始使用Smartcost</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- JS. -->
-    <script src="js/jquery/jquery.min.js"></script>
-    <script src="js/tether/tether.min.js"></script>
-    <script src="js/bootstrap/bootstrap.min.js"></script>
-    <script src="js/global.js"></script>
-</body>
-<script type="text/javascript">
-    $('#myModal').modal('show')
-</script>
-
-</html>

+ 0 - 132
web/users/login.html

@@ -1,132 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <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/ration_repository/css/main.css">
-    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
-    <script src="/lib/jquery/jquery.min.js"></script>
-    <script src="/public/web/url_util.js"></script>
-</head>
-<body>
-    <div class="container">
-        <form class="form-signin" method="post" onsubmit="return false">
-            <h1 class="d-flex justify-content-center">Smartcost</h1>
-            <h4 class="d-flex justify-content-center mb-2">用户登录</h4>
-            <div class="form-group">
-                <input id="inputEmail" class="form-control " placeholder="通行账号 邮箱/手机" required="" autofocus="" value="laiku123@qq.com">
-            </div>
-            <div class="form-group">
-                <input id="inputPassword" class="form-control " placeholder="输入密码" required="" type="password" value="19930523">
-            </div>
-            <div class="form-group has-danger">
-                <div id="hint" class="form-control-feedback">&nbsp;</div>
-            </div>
-            <div class="form-group">
-                <!--<button id="login" class="btn btn-primary btn-block" data-toggle="modal" data-target="#ver">登录</button>-->
-                <button id="login" class="btn btn-primary btn-block">登录</button>
-            </div>
-            <div class="pt-1 d-flex justify-content-center">
-                <a href="http://sso.smartcost.com.cn/getpasswd" target="_blank" class="mr-3">忘记密码</a>
-                <a href="http://sso.smartcost.com.cn/reg" target="_blank">免费注册</a>
-            </div>
-        </form>
-
-        <script>
-            $(document).ready(function () {
-                var referer = scUrlUtil.GetQueryString('referer');
-
-                $("#login").click(function () {
-                    var account = $("#inputEmail").val();
-                    var pw = $("#inputPassword").val();
-
-                    $.ajax({
-                        url: '/login',
-                        type: 'post',
-                        data: {"account": account, "pw": pw},
-                        success: function (result) {
-                            if (result.data) {
-//                                $('#ver').modal('show');
-                                if (referer) {
-                                    location.href = referer;
-                                } else {
-                                    location.href = '/';
-                                }
-                            }
-                            else {
-                                $('#hint').html(result.error);
-                            }
-                        },
-                        error: function (result) {
-                            $('#hint').html('内部程序错误!');
-                        }
-                    });
-                });
-
-                $(".form-control").on('input', function () {
-                    $('#hint').html('&nbsp;');
-                });
-            });
-        </script>
-
-        <!--登录错误-->
-        <!--<form class="form-signin login-error">
-            <h1 class="d-flex justify-content-center">Smartcost</h1>
-            <h4 class="d-flex justify-content-center mb-2">用户登录</h4>
-            <div class="form-group has-danger">
-                <input class="form-control form-control-danger" value="1212@qq.com" placeholder="通行账号 邮箱/手机" required="" autofocus="">
-                <div class="form-control-feedback">输入的邮箱/手机无效</div>
-            </div>
-            <div class="form-group has-danger">
-                <input class="form-control gform-control-danger" value="12313" placeholder="输入密码" required="" type="password">
-                <div class="form-control-feedback">密码错误</div>
-            </div>
-            <div class="form-group">
-                <button class="btn btn-primary btn-block">登录</button>
-            </div>
-            <div class="pt-1 d-flex justify-content-center">
-                <a href="http://sso.smartcost.com.cn/getpasswd" target="_blank" class="mr-3">忘记密码</a>
-                <a href="http://sso.smartcost.com.cn/reg" target="_blank">免费注册</a>
-            </div>
-        </form>-->
-    </div>
-    <!--弹出信息-->
-    <div class="modal fade" id="ver" data-backdrop="static">
-        <div class="modal-dialog modal-lg" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                    <h4 class="modal-title">选择登录版本</h4>
-                    <p class="m-0 text-warning"><i class="fa fa-exclamation-triangle"></i> <b>偏好设置</b> 中可以修改您的登录习惯。</p>
-                </div>
-                <div class="modal-body">
-                    <div class="row">
-                        <div class="col-sm-6">
-                            <div class="card card-block">
-                                <h3 class="card-title">重庆版免费版</h3>
-                                <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
-                                <a class="btn btn-primary" href="login-infoinput.html">开始使用</a>
-                            </div>
-                        </div>
-                        <div class="col-sm-6">
-                            <div class="card card-block">
-                                <h3 class="card-title">广东版免费版</h3>
-                                <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
-                                <a class="btn btn-primary" href="login-infoinput.html">开始使用</a>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- JS. -->
-
-    <script src="/lib/tether/tether.min.js"></script>
-    <script src="/lib/bootstrap/bootstrap.min.js"></script>
-    <script src="/web/maintain/ration_repository/js/global.js"></script>
-</body>
-
-</html>

+ 0 - 589
web/users/project-management.html

@@ -1,589 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-
-<head>
-    <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/css/bootstrap/themes.css">-->
-    <link rel="stylesheet" href="/web/building_saas/css/main.css">
-    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
-    <!--zTree-->
-  	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
-
-    <script>
-        // 这里的变量供页面调用
-        var userAccount = '<%- userAccount %>';
-        var userID = '<%- userID %>';
-    </script>
-</head>
-
-<body>
-    <div class="header">
-<!--        <div class="top-msg clearfix">
-            <div class="alert alert-warning mb-0 py-0" role="alert">
-                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
-                  <span aria-hidden="true">&times;</span>
-                </button>
-                <strong>注意!</strong> 这是一条消息通知 <a href="#">链接</a>
-            </div>
-        </div>-->
-        <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="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.html" target="_blank">账号资料</a>
-                      <a class="dropdown-item" href="user-buy.html" target="_blank">产品购买</a>
-                      <a class="dropdown-item" href="user-set.html" 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>
-              <button id="logout" class="btn btn-link btn-sm">注销</button>
-          </div>
-        </nav>
-        <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
-            <ul class="nav navbar-nav px-1">
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="http://example.com" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">文件</a>
-                    <div class="dropdown-menu" aria-labelledby="supportedContentDropdown">
-                        <a class="dropdown-item" href="#">Action</a>
-                        <a class="dropdown-item" href="#">Another action</a>
-                        <a class="dropdown-item" href="#">Something else here</a>
-                    </div>
-                </li>
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑</a>
-                    <div class="dropdown-menu">
-                        <a class="dropdown-item" href="#">Action</a>
-                        <a class="dropdown-item" href="#">Another action</a>
-                        <a class="dropdown-item" href="#">Something else here</a>
-                    </div>
-                </li>
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">工具</a>
-                    <div class="dropdown-menu">
-                        <a class="dropdown-item" href="#">Action</a>
-                        <a class="dropdown-item" href="#">Another action</a>
-                        <a class="dropdown-item" href="#">Something else here</a>
-                    </div>
-                </li>
-                <li class="nav-item">
-                    <a class="nav-link" href="#" aria-haspopup="true" aria-expanded="false">帮助</a>
-                </li>
-            </ul>
-            <form class="form-inline">
-                <input class="form-control form-control-sm mr-1" type="text" placeholder="告诉我你想做什么">
-            </form>
-        </nav>
-    </div>
-    <div class="main">
-        <div class="poj-manage container-fluid">
-            <div class="row">
-                <div class="col-lg-2">
-                    <div class="poj-cate">
-                        <input type="text" class="my-2 form-control form-control-sm" placeholder="搜索所有工程">
-                        <ul class="nav nav-pills flex-column">
-                            <li class="nav-item">
-                                <a class="nav-link active" href="#">全部</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">最近使用</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">共享</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">协同工作</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">归档</a>
-                            </li>
-                            <li class="nav-item">
-                                <a class="nav-link" href="#">回收站</a>
-                            </li>
-                        </ul>
-                    </div>
-                </div>
-                <div class="col-lg-10">
-                    <div class="toolsbar">
-                        <div class="tools-btn btn-group align-top">
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#addPoj" class="btn btn-sm">新建工程</a>
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#addFolder" class="btn btn-sm"><i class="fa fa-folder-o"></i>&nbsp;新建文件夹</a>
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#rename" class="btn btn-sm">重命名</a>
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="btn btn-sm">删除</a>
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#moveto" class="btn btn-sm">移动到...</a>
-                            <a href="javacript:void(0);" data-toggle="modal" data-target="#copyto" class="btn btn-sm">复制到...</a>
-                            <a href="" class="btn btn-sm">共享</a>
-                            <a href="" class="btn btn-sm">协同</a>
-                        </div>
-                    </div>
-                    <div class="poj-list">
-                        <legend>全部</legend>
-                        <table class="table table-hover table-sm">
-                            <thead>
-                                <tr>
-                                    <th width="40"></th>
-                                    <th width="78%">工程列表</th>
-                                    <th width="10%">最近使用</th>
-                                    <th width="10%">创建日期</th>
-                                </tr>
-                            </thead>
-                            <tbody>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-1"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;XX项目文件夹</td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                  <tr>
-                                      <td></td>
-                                      <td class="in-2"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;XX项目文件夹</td>
-                                      <td></td>
-                                      <td></td>
-                                  </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-3"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;XX项目文件夹</td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-4"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;<a href="#">某某某某工厂工厂某某工厂建设某某工厂建设</a></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-5"><a href="#" class="tree-open" title="收起"><i class="fa fa-minus-square-o mr-1"></i></a><i class="fa fa-folder-open-o"></i>&nbsp;<a href="#" class="open-sidebar">左1号生产车间(click)</a></td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
-                                <tr>
-                                    <td><i class="fa fa-sort" data-toggle="tooltip" data-placement="top" title="长安拖动"></i></td>
-                                    <td class="in-6"><span class="in-3 poj-icon">└</span><a href="zaojiashu.html">建筑工程(click)</a></td>
-                                    <td>2016-01-01</td>
-                                    <td>2016-01-01</td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-6"><span class="in-3 poj-icon">└</span><a href="#">机械设备安装工程</a></td>
-                                    <td>2016-01-01</td>
-                                    <td>2016-01-01</td>
-                                </tr>
-                                <tr>
-                                    <td></td>
-                                    <td class="in-5"><a href="#" class="tree-close" title="展开"><i class="fa fa-plus-square-o  mr-1"></i></a><i class="fa fa-folder-o"></i>&nbsp;<a href="#">2号生产车间</a></td>
-                                    <td>......</td>
-                                    <td>......</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <div class="slide-sidebar">
-            <div class="side-content">
-                <div class="p-3">
-                    <legend>1号生产车间 汇总</legend>
-                    <table class="table table-bordered table-hover table-sm">
-                        <thead>
-                            <tr>
-                                <th rowspan="2"></th>
-                                <th rowspan="2">序号</th>
-                                <th rowspan="2">名称</th>
-                                <th rowspan="2">金额</th>
-                                <th colspan="6">其中</th>
-                                <th rowspan="2">占造价比例(%)</th>
-                                <th rowspan="2">建筑面积</th>
-                                <th rowspan="2">单方造价</th>
-                            </tr>
-                            <tr>
-                                <th>分部分项合计</th>
-                                <th>措施项目合计</th>
-                                <th>其他项目合计</th>
-                                <th>安全文明施工费</th>
-                                <th>规费</th>
-                                <th>税金</th>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            <tr>
-                                <td>1</td>
-                                <td>一</td>
-                                <td>建筑工程</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                            </tr>
-                            <tr>
-                                <td>2</td>
-                                <td>二</td>
-                                <td>建筑工程</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                            </tr>
-                            <tr>
-                                <td>3</td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                            </tr>
-                            <tr>
-                                <td>4</td>
-                                <td>一</td>
-                                <td>合计</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td>0</td>
-                                <td> </td>
-                                <td> </td>
-                                <td> </td>
-                            </tr>
-                        </tbody>
-                    </table>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出新建工程-->
-    <div class="modal fade" id="addPoj" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">新建工程</h5>
-                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                      <span aria-hidden="true">&times;</span>
-                    </button>
-                </div>
-                <div class="modal-body">
-                    <form>
-                    <div class="collapse" id="moreinfo">
-                        <div class="form-group">
-                            <label>建设项目</label>
-                            <input type="text" class="form-control" placeholder="输入建设项目名称">
-                        </div>
-                        <div class="form-group">
-                            <label>单项工程</label>
-                            <input type="text" class="form-control" placeholder="输入单项工程名称">
-                        </div>
-                      </div>
-                        <div class="form-group">
-                            <label>单位工程</label>
-                            <input type="text" class="form-control" placeholder="输入单位工程名称">
-                        </div>
-                        <div class="form-group" >
-                            <label class="custom-control custom-checkbox">
-                              <input type="checkbox" class="custom-control-input" href="#moreinfo" data-toggle="collapse" data-parent="#moreinfo" aria-expanded="false" aria-controls="moreinfo">
-                              <span class="custom-control-indicator" ></span>
-                              <span class="custom-control-description">建立 <b>建设项目</b> 和 <b>单项工程</b> 文件夹</span>
-                            </label>
-                        </div>
-                        <div class="form-group">
-                            <label>计价方式</label>
-                            <div>
-                                <label class="custom-control custom-radio">
-                                  <input id="radio1" name="radio" type="radio" class="custom-control-input">
-                                  <span class="custom-control-indicator"></span>
-                                  <span class="custom-control-description">清单计价</span>
-                                </label>
-                                <label class="custom-control custom-radio">
-                                  <input id="radio2" name="radio" type="radio" class="custom-control-input">
-                                  <span class="custom-control-indicator"></span>
-                                  <span class="custom-control-description">定额计价</span>
-                                </label>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="project-management.html" class="btn btn-primary">确定</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出新建文件夹-->
-    <div class="modal fade" id="addFolder" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">新建文件夹</h5>
-                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                  </button>
-                </div>
-                <div class="modal-body">
-                    <form>
-                        <div class="form-group">
-                            <label>文件夹</label>
-                            <input type="text" class="form-control" placeholder="输入文件夹名称">
-                            <span class="form-text text-muted">Smartcost为你提供了灵活的工程管理功能,如:</span>
-                            <span class="form-text text-muted">当你想汇总多个 <b>单位工程</b> 时,只需把它们都放在一个文件夹即可。</span>
-                        </div>
-                    </form>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="project-management.html" class="btn btn-primary">确定</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出重命名-->
-    <div class="modal fade" id="rename" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">重命名</h5>
-                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                  </button>
-                </div>
-                <div class="modal-body">
-                    <form>
-                        <div class="form-group">
-                            <input type="text" class="form-control" placeholder="输入名称">
-                        </div>
-                    </form>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="project-management.html" class="btn btn-primary">确定</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出删除-->
-    <div class="modal fade" id="del" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">删除确认</h5>
-                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                  </button>
-                </div>
-                <div class="modal-body">
-                    <h5 class="text-danger">删除 "建筑工程" ?</h5>
-                    <h5 class="text-danger">删除 "XX项目文件夹" 以及它包含的子项?</h5>
-                    <p class="">删除后,你可以在回收站找到它。</p>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="" class="btn btn-danger">删除</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出移动到-->
-    <div class="modal fade" id="moveto" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">移动到...</h5>
-                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                  </button>
-                </div>
-                <div class="modal-body">
-                  <ul id="treeDemo" class="ztree"></ul>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="" class="btn btn-primary">确定</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!--弹出复制到-->
-    <div class="modal fade" id="copyto" data-backdrop="static">
-        <div class="modal-dialog" role="document">
-            <div class="modal-content">
-                <div class="modal-header">
-                  <h5 class="modal-title">复制到...</h5>
-                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                  </button>
-                </div>
-                <div class="modal-body">
-                  <ul id="treeDemo2" class="ztree"></ul>
-                </div>
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="" class="btn btn-primary">确定</a>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- 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/building_saas/js/global.js"></script>
-    <!-- zTree -->
-  	<script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
-  	<script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
-    <SCRIPT type="text/javascript">
-  		<!--
-  		var setting = {	};
-
-  		var zNodes =[
-  			{ name:"父节点1 - 展开", open:true,
-  				children: [
-  					{ name:"父节点11 - 折叠",
-  						children: [
-  							{ name:"叶子节点111"},
-  							{ name:"叶子节点112"},
-  							{ name:"叶子节点113"},
-  							{ name:"叶子节点114"}
-  						]},
-  					{ name:"父节点12 - 折叠",
-  						children: [
-  							{ name:"叶子节点121"},
-  							{ name:"叶子节点122"},
-  							{ name:"叶子节点123"},
-  							{ name:"叶子节点124"}
-  						]},
-  					{ name:"父节点13 - 没有子节点", isParent:true}
-  				]},
-  			{ name:"父节点2 - 折叠",
-  				children: [
-  					{ name:"父节点21 - 展开", open:true,
-  						children: [
-  							{ name:"叶子节点211"},
-  							{ name:"叶子节点212"},
-  							{ name:"叶子节点213"},
-  							{ name:"叶子节点214"}
-  						]},
-  					{ name:"父节点22 - 折叠",
-  						children: [
-  							{ name:"叶子节点221"},
-  							{ name:"叶子节点222"},
-  							{ name:"叶子节点223"},
-  							{ name:"叶子节点224"}
-  						]},
-  					{ name:"父节点23 - 折叠",
-  						children: [
-  							{ name:"叶子节点231"},
-  							{ name:"叶子节点232"},
-  							{ name:"叶子节点233"},
-  							{ name:"叶子节点234"}
-  						]}
-  				]},
-  			{ name:"父节点3 - 没有子节点", isParent:true}
-
-  		];
-
-  		$(document).ready(function(){
-  			$.fn.zTree.init($("#treeDemo"), setting, zNodes);
-  		});
-  		//-->
-  	</SCRIPT>
-    <SCRIPT type="text/javascript">
-  		<!--
-  		var setting = {	};
-
-  		var zNodes =[
-  			{ name:"父节点1 - 展开", open:true,
-  				children: [
-  					{ name:"父节点11 - 折叠",
-  						children: [
-  							{ name:"叶子节点111"},
-  							{ name:"叶子节点112"},
-  							{ name:"叶子节点113"},
-  							{ name:"叶子节点114"}
-  						]},
-  					{ name:"父节点12 - 折叠",
-  						children: [
-  							{ name:"叶子节点121"},
-  							{ name:"叶子节点122"},
-  							{ name:"叶子节点123"},
-  							{ name:"叶子节点124"}
-  						]},
-  					{ name:"父节点13 - 没有子节点", isParent:true}
-  				]},
-  			{ name:"父节点2 - 折叠",
-  				children: [
-  					{ name:"父节点21 - 展开", open:true,
-  						children: [
-  							{ name:"叶子节点211"},
-  							{ name:"叶子节点212"},
-  							{ name:"叶子节点213"},
-  							{ name:"叶子节点214"}
-  						]},
-  					{ name:"父节点22 - 折叠",
-  						children: [
-  							{ name:"叶子节点221"},
-  							{ name:"叶子节点222"},
-  							{ name:"叶子节点223"},
-  							{ name:"叶子节点224"}
-  						]},
-  					{ name:"父节点23 - 折叠",
-  						children: [
-  							{ name:"叶子节点231"},
-  							{ name:"叶子节点232"},
-  							{ name:"叶子节点233"},
-  							{ name:"叶子节点234"}
-  						]}
-  				]},
-  			{ name:"父节点3 - 没有子节点", isParent:true}
-
-  		];
-
-  		$(document).ready(function(){
-  			$.fn.zTree.init($("#treeDemo2"), setting, zNodes);
-  		});
-  		//-->
-  	</SCRIPT>
-</body>
-<script type="text/javascript">
-    autoFlashHeight();
-</script>
-
-<script>
-    $(document).ready(function () {
-        $("#logout").click(function () {
-            location.href = '/logout';
-        });
-    });
-</script>
-
-
-
-</html>

+ 48 - 0
web/users/views/dashboard/index.html

@@ -0,0 +1,48 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main"><h2>首页</h2></div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header">
+            <h4>通知</h4>
+        </div>
+        <div class="c-body">
+            <table class="table">
+                <thead>
+                <tr>
+                    <th>标题</th>
+                    <th width="200">发布时间</th>
+                    <th width="120">发布人</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr>
+                    <td><a href="#">标题A</a></td>
+                    <td>2017-02-01 09:30</td>
+                    <td>陈特</td>
+                </tr>
+                <tr>
+                    <td><a href="#">标题B</a></td>
+                    <td>2017-02-01 09:30</td>
+                    <td>陈特</td>
+                </tr>
+                <tr>
+                    <td><a href="#">标题C</a></td>
+                    <td>2017-02-01 09:30</td>
+                    <td>陈特</td>
+                </tr>
+                <tr>
+                    <td>【内部】<a href="#">标题D</a></td>
+                    <td>2017-02-01 09:30</td>
+                    <td>陈特</td>
+                </tr>
+                <tr>
+                    <td><a href="#">标题E</a></td>
+                    <td>2017-02-01 09:30</td>
+                    <td>陈特</td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>

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

@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang=zh-cn>
+<head>
+    <meta charset=utf-8>
+    <title>建筑造价后台</title>
+    <meta name=description content="纵横变更令审批系统">
+    <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="/web/users/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/users/css/style.css">
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/web/users/js/lib/bootstrap.min.js"></script>
+    <script src="/web/users/js/global.js"></script>
+    <script src="/web/users/js/lib/jquery.validate.js"></script>
+    <script src="/web/users/js/lib/validate.extend.js"></script>
+    <script src="/web/users/js/lib/messages_zh.js"></script>
+    <script src="/web/users/js/lib/bootstrap-paginator.js"></script>
+</head>
+<body>
+<div class="header">
+    <h1 class="logo"><a>建筑造价后台</a></h1>
+    <div class="header-box">
+        <div class="header-nav"></div>
+        <div class="header-user pull-right">
+            <div class="avatar btn-group">
+                <a class="dropdown-toggle" data-toggle="dropdown">
+                    <span class="pic"><img src="/img/avatar.png"></span>
+                    <span><%= manager.username %></span>
+                    <span class="caret"></span>
+                </a>
+                <ul class="dropdown-menu dropdown-menu-right">
+                    <li><a href="#">账号设置(CLD)</a></li>
+                    <li><a href="/login/logout">退出登录</a></li>
+                </ul>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="main">
+    <div class="main-nav">
+        <div class="nav-top">
+            <ul class="nav nav-pills nav-stacked bg-nav">
+                <% for(let tmp in menu) {%>
+                <li <% if (controller === menu[tmp].name) {%>class="active"<% } %>>
+                    <a href="<%= menu[tmp].url %>">
+                        <i class="<%= menu[tmp].iconClass %>" aria-hidden="true"></i> <%= menu[tmp].title %>
+                    </a>
+                </li>
+                <% } %>
+            </ul>
+        </div>
+    </div>
+    <div class="main-panel">
+        <%- body %>
+    </div>
+</div>
+<div class="modal fade" id="edit-account" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                <h4 class="modal-title" id="myModalLabel">编辑账号</h4>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>权限</label>
+                    <div class="checkbox">
+                        <label>
+                            <input type="checkbox" name="permission[]" data-permission="manager"> 用户管理
+                        </label>&nbsp;
+                        <label>
+                            <input type="checkbox" name="permission[]" data-permission="notify"> 通知管理
+                        </label>&nbsp;
+                        <label>
+                            <input type="checkbox" name="permission[]" data-permission="stdBillsmain"> 清单规则编辑器
+                        </label>&nbsp;
+                        <label>
+                            <input type="checkbox" name="permission[]" data-permission="rationRepository"> 定额编辑器
+                        </label>&nbsp;
+                        <label>
+                            <input type="checkbox" name="permission[]" data-permission="report"> 报表模板
+                        </label>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>禁止登录</label>
+                    <div class="checkbox">
+                        <label>
+                            <input type="checkbox" name="can_login"> 是
+                        </label>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" id="save-manager">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+</body>

+ 87 - 0
web/users/views/layout/page.html

@@ -0,0 +1,87 @@
+<ul aria-label="Page navigation" id="pages"></ul>
+<script type="text/javascript">
+    let options = {
+        bootstrapMajorVersion: 3,
+        currentPage: "<%= pages.current %>",
+        totalPages: "<%= pages.total %>",
+        size: "normal",
+        itemContainerClass: function(type, page, current) {
+            let className = 'page-item';
+            this.currentPage = parseInt(this.currentPage);
+            this.totalPages = parseInt(this.totalPages);
+
+            switch (type) {
+                case "prev":
+                    className = this.currentPage === 1 ? className + ' disabled' : className;
+                    break;
+                case "next":
+                    className = this.currentPage === this.totalPages ? className + ' disabled' : className;
+                    break;
+                case "page":
+                    className = page === this.currentPage ? className + ' active' : className;
+                    break;
+            }
+
+            return className;
+        },
+        itemContentClass: function(type, page, current) {
+            return 'page-link';
+        },
+        itemTexts: function(type, page, current) {
+            switch (type) {
+                case "first":
+                    return "&laquo;";
+                case "prev":
+                    return "上一页";
+                case "next":
+                    return "下一页";
+                case "last":
+                    return "最后一页";
+                case "page":
+                    return page;
+            }
+        },
+        shouldShowPage: function (type, page, current) {
+            let result = true;
+            switch (type) {
+                case "first":
+                    result = (current !== 1);
+                    break;
+                case "prev":
+                    break;
+                case "next":
+                    break;
+                case "last":
+                    result = false;
+                    break;
+                case "page":
+                    result = true;
+                    break;
+            }
+            return result;
+
+        },
+        pageUrl: function(type, page, current){
+            let queryData = JSON.parse('<%- pages.queryData %>');
+
+            // 如果没有附带查询条件则直接返回
+            if (Object.keys(queryData).length <= 0) {
+                return "?page=" + page;
+            }
+            // 有其它数据则重新赋值page,然后组合字符串
+            queryData.page = page;
+            let queryArray = [];
+            for(let tmp in queryData) {
+                let tempString = tmp + '=' + queryData[tmp];
+                queryArray.push(tempString);
+            }
+
+            let firstQuery = queryArray.shift();
+            let queryString = queryArray.join('&');
+            return  queryString === '' ? '?' + firstQuery : '?' + firstQuery + '&' + queryString;
+        }
+    };
+    if (options.totalPages > 0) {
+        $("#pages").bootstrapPaginator(options);
+    }
+</script>

+ 18 - 0
web/users/views/layout/second_menu.html

@@ -0,0 +1,18 @@
+<div class="panel-sidebar">
+    <div class="panel-title">
+        <div class="title-bar">
+            <h2><%= secondMenu[action].title %></h2>
+        </div>
+    </div>
+    <div class="scrollbar-auto">
+        <div class="nav-box">
+            <ul class="nav-list list-unstyled">
+                <% for (let tmp in secondMenu) { %>
+                <li <% if (secondMenu[tmp].name === action) { %>class="active"
+                        <% } %>
+                ><a href="<%= secondMenu[tmp].url %>"><span><%= secondMenu[tmp].title %></span></a></li>
+                <% } %>
+            </ul>
+        </div>
+    </div>
+</div>

+ 54 - 0
web/users/views/login/index.html

@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang=zh-cn>
+<head>
+    <meta charset=utf-8>
+    <title>建筑造价后台</title>
+    <meta name=description content=纵横变更令审批系统>
+    <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="/web/users/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/users/css/style.css">
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/web/users/js/lib/bootstrap.min.js"></script>
+    <script src="/web/users/js/global.js"></script>
+    <script src="/web/users/js/lib/jquery.validate.js"></script>
+    <script src="/web/users/js/lib/validate.extend.js"></script>
+    <script src="/web/users/js/lib/messages_zh.js"></script>
+</head>
+<body class="loginbody">
+<div class="wraplogin">
+    <div class="loginTop">
+        <a title="返回首页" href="#">建筑造价后台</a>
+    </div>
+    <div class="loginItem  center-block">
+        <div class="loginForm">
+            <form role="form" id="login-form">
+                <div class="form-group">
+                    <div class="input-group">
+                        <div class="input-group-addon"><i class="glyphicon glyphicon-user"></i></div>
+                        <input  class="form-control input-lg" placeholder="输入账号" name="username" id="username" value="admin">
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="input-group">
+                        <div class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></div>
+                        <input type="password" class="form-control input-lg"  placeholder="输入密码" id="password" name="password" value="admin1234">
+                    </div>
+                </div>
+                <a class="btn btn-primary btn-lg btn-block" href="javascript:void(0);" id="login">登录</a>
+            </form>
+        </div>
+        <div class="loginBottom">
+            <a href="getpasswd.html" target="_blank">忘记密码</a>
+        </div>
+    </div>
+</div>
+<div class="login_bottom">
+    <div class="login_wave">
+        <div id="wave_bg_1" style="left: -434.722px;"></div>
+        <div id="wave_bg_2" style="left: -336.283px;"></div>
+    </div>
+</div>
+<script type="text/javascript" src="/web/users/js/login.js"></script>
+</body>

+ 56 - 0
web/users/views/manager/index.html

@@ -0,0 +1,56 @@
+<%include ../layout/second_menu.html %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2><%= secondMenu[action].title %></h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header">
+            <!--办事处筛选-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    办事处 <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">广东办</a></li>
+                    <li><a href="#">总部</a></li>
+                </ul>
+            </div>
+        </div>
+        <div class="c-body">
+            <table class="table">
+                <thead>
+                <tr>
+                    <th>姓名</th>
+                    <th>办事处</th>
+                    <th>权限</th>
+                    <th width="100">操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <% managerList.forEach(function(manager) { %>
+                <tr>
+                    <td><%= manager.username %></td>
+                    <td><%= manager.office %></td>
+                    <td><%= manager.permissionStr %></td>
+                    <td>
+                        <a href="javascript:void(0);" class="edit btn btn-xs"
+                            data-permission="<%= manager.permission %>" data-login="<%= manager.can_login %>"
+                            data-id="<%= manager._id %>">编辑</a>
+                        <% if (manager.super_admin !== 1) { %>
+                        <a href="/manager/delete/<%= manager._id %>" class="btn btn-xs">删除</a>
+                        <% } %>
+                    </td>
+                </tr>
+                <% }) %>
+                </tbody>
+            </table>
+            <nav aria-label="Page navigation">
+                <%include ../layout/page.html %>
+            </nav>
+        </div>
+    </div>
+</div>
+<script type="text/javascript" src="/web/users/js/manager.js"></script>

+ 36 - 0
web/users/views/manager/save.html

@@ -0,0 +1,36 @@
+<%include ../layout/second_menu.html %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>
+                <%= secondMenu[action].title %>
+                <a href="javascript:void(0);" class="btn btn-primary btn-sm pull-right" id="save">确定修改</a>
+            </h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <form class="row" id="save-form" action="" method="post">
+                <div class="col-lg-4">
+                    <div class="form-group">
+                        <label>账号</label>
+                        <input class="form-control" value="<%= adminData.username %>" disabled="disabled">
+                    </div>
+                    <div class="form-group has-feedback">
+                        <label>旧密码</label>
+                        <input type="password" class="form-control" name="password" id="password">
+                    </div>
+                    <div class="form-group has-feedback">
+                        <label>新密码</label>
+                        <input type="password" class="form-control" name="newPassword" id="new-password">
+                    </div>
+                    <div class="form-group has-feedback">
+                        <label>确认新密码</label>
+                        <input type="password" class="form-control" name="confirmPassword">
+                    </div>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+<script type="text/javascript" src="/web/users/js/admin.js"></script>

+ 114 - 0
web/users/views/notify/index.html

@@ -0,0 +1,114 @@
+<%include ../layout/second_menu.html %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>用户通知
+                <a href="news-add.html" class="btn btn-primary btn-sm pull-right">新建通知</a></h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header">
+            <!--变更类型-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    所有状态 <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">已发布</a></li>
+                    <li><a href="#">未发布</a></li>
+                </ul>
+            </div>
+            <!--变更类别-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    所有年 <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">2015</a></li>
+                    <li><a href="#">2016</a></li>
+                    <li><a href="#">2017</a></li>
+                </ul>
+            </div>
+            <!--变更性质-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    所有月 <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">1</a></li>
+                    <li><a href="#">2</a></li>
+                    <li><a href="#">3</a></li>
+                    <li><a href="#">4</a></li>
+                    <li><a href="#">5</a></li>
+                    <li><a href="#">6</a></li>
+                    <li><a href="#">7</a></li>
+                    <li><a href="#">8</a></li>
+                    <li><a href="#">9</a></li>
+                    <li><a href="#">10</a></li>
+                    <li><a href="#">11</a></li>
+                </ul>
+            </div>
+        </div>
+        <div class="c-body">
+            <table class="table">
+                <thead>
+                <tr>
+                    <th>标题</th>
+                    <th>创建人</th>
+                    <th width="180">发布时间</th>
+                    <th width="100">操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr>
+                    <td><a href="javascript:void(0)" data-toggle="modal" data-target="#view">标题A chick me</a></td>
+                    <td>陈特</td>
+                    <td>2017-03-01 09:03:09</td>
+                    <td><a href="" class="btn btn-xs">编辑</a></td>
+                </tr>
+                <tr class="warning">
+                    <td><a href="#">标题B</a></td>
+                    <td>陈特</td>
+                    <td>未发布</td>
+                    <td><a href="" class="btn btn-xs">编辑</a></td>
+                </tr>
+                <tr>
+                    <td><a href="#">标题C</a></td>
+                    <td>陈特</td>
+                    <td>2017-03-01 09:03:09</td>
+                    <td><a href="" class="btn btn-xs">编辑</a></td>
+                </tr>
+                <tr>
+                    <td><a href="#">标题D</a></td>
+                    <td>陈特</td>
+                    <td>2017-03-01 09:03:09</td>
+                    <td><a href="" class="btn btn-xs">编辑</a></td>
+                </tr>
+
+                </tbody>
+            </table>
+            <nav aria-label="Page navigation">
+                <ul class="pagination pagination-sm">
+                    <li class="disabled">
+                        <a href="#" aria-label="Previous">
+                            <span aria-hidden="true">&laquo;</span>
+                        </a>
+                    </li>
+                    <li class="active"><a href="#">1</a></li>
+                    <li><a href="#">2</a></li>
+                    <li><a href="#">3</a></li>
+                    <li><a href="#">4</a></li>
+                    <li><a href="#">5</a></li>
+                    <li>
+                        <a href="#" aria-label="Next">
+                            <span aria-hidden="true">&raquo;</span>
+                        </a>
+                    </li>
+                </ul>
+            </nav>
+        </div>
+    </div>
+</div>

+ 29 - 0
web/users/views/tool/index.html

@@ -0,0 +1,29 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main">
+            <h2>工具</h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="row">
+            <div class="col-xs-6 mb-30 ">
+                <div class="c-body">
+                    <h2>清单规则编辑器
+                        <a href="/stdBillsmain" class="btn btn-primary pull-right">进入</a></h2>
+                </div>
+            </div>
+            <div class="col-xs-6 mb-30 ">
+                <div class="c-body">
+                    <h2>定额编辑器
+                        <a href="/rationRepository/main" class="btn btn-primary pull-right">进入</a></h2>
+                </div>
+            </div>
+            <div class="col-xs-6 mb-30 ">
+                <div class="c-body">
+                    <h2>报表模板
+                        <a href="#" class="btn btn-primary pull-right">进入</a></h2>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 80 - 0
web/users/views/user/index.html

@@ -0,0 +1,80 @@
+<%include ../layout/second_menu.html %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2><%= secondMenu[action].title %></h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header">
+            <!--最新注册-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    最新注册:最近24小时<span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">最近24小时</a></li>
+                    <li><a href="#">最近3天</a></li>
+                    <li><a href="#">最近7天</a></li>
+                    <li><a href="#">最近30天</a></li>
+                </ul>
+            </div>
+            <!--版本-->
+            <div class="btn-group">
+                <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
+                        aria-haspopup="true" aria-expanded="false">
+                    版本 <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    <li><a href="#">广东版</a></li>
+                    <li><a href="#">重庆版</a></li>
+                </ul>
+            </div>
+            <!--结果-->
+            <div class="btn-group">
+                &nbsp;共 <%= total %> 条结果
+            </div>
+            <!--搜索-->
+            <div class="btn-group pull-right">
+                <div class="input-group">
+                    <input type="text" class="form-control input-sm" placeholder="手机/邮箱/姓名/公司">
+                    <span class="input-group-btn">
+                        <button class="btn btn-default btn-sm" type="button">
+                            <i class="glyphicon glyphicon-search"></i>
+                        </button>
+                    </span>
+                </div>
+            </div>
+        </div>
+        <div class="c-body">
+            <table class="table">
+                <thead>
+                <tr>
+                    <th width="350">注册手机/邮箱</th>
+                    <th>姓名</th>
+                    <th>企业名称</th>
+                    <th>地区</th>
+                    <th width="180">注册时间</th>
+                </tr>
+                </thead>
+                <tbody>
+                <% userList.forEach(function (user){ %>
+                <tr>
+                    <td><%= user.mobile %> / <%= user.email %></td>
+                    <td><%= user.real_name %></td>
+                    <td><a tabindex="0" role="button" data-toggle="popover" data-trigger="focus" title="更多信息"
+                           data-content="企业类型:<%= model.companyType[user.company_type] %>,企业规模:<%= model.companyScale[user.company_scale] %>"><%= user.company %></a>
+                    </td>
+                    <td><%= model.province[user.province] %></td>
+                    <td><%= moment(user.create_time).format('YYYY-MM-DD HH:mm:ss') %></td>
+                </tr>
+                <% }) %>
+                </tbody>
+            </table>
+            <nav aria-label="Page navigation">
+                <%include ../layout/page.html %>
+            </nav>
+        </div>
+    </div>
+</div>