Browse Source

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

TonyKang 7 năm trước cách đây
mục cha
commit
c343d5e6f2
31 tập tin đã thay đổi với 2018 bổ sung399 xóa
  1. 55 0
      modules/common/const/engineering.js
  2. 18 0
      modules/common/const/province_const.js
  3. 64 0
      modules/common/helper/mongoose_helper.js
  4. 33 0
      modules/common/std/schemas/std_bills_lib_lists.js
  5. 32 0
      modules/common/std/schemas/std_ration_lib_map.js
  6. 53 0
      modules/common/std/std_bills_lib_lists_model.js
  7. 53 0
      modules/common/std/std_ration_lib_map_model.js
  8. 147 3
      modules/ration_repository/models/ration_item.js
  9. 49 1
      modules/users/controllers/login_controller.js
  10. 152 52
      modules/users/controllers/version_controller.js
  11. 50 6
      modules/users/models/schemas/version.js
  12. 163 63
      modules/users/models/version_model.js
  13. 1 0
      modules/users/routes/login_route.js
  14. 6 3
      modules/users/routes/version_route.js
  15. 3 3
      operation.js
  16. 4 2
      public/web/sheet/sheet_common.js
  17. 19 0
      test/models/schemas/test1.js
  18. 19 0
      test/models/schemas/test2.js
  19. 19 0
      test/models/schemas/test3.js
  20. 47 0
      test/models/test1_model.js
  21. 46 0
      test/models/test2_model.js
  22. 46 0
      test/models/test3_model.js
  23. 59 36
      web/maintain/ration_repository/js/ration.js
  24. 110 4
      web/maintain/ration_repository/js/ration_glj.js
  25. 235 28
      web/maintain/ration_repository/js/repository_glj.js
  26. 177 49
      web/users/js/version.js
  27. 1 53
      web/users/views/layout/layout.html
  28. 99 0
      web/users/views/version/add.html
  29. 16 0
      web/users/views/version/common.html
  30. 94 96
      web/users/views/version/index.html
  31. 148 0
      web/users/views/version/modal.html

+ 55 - 0
modules/common/const/engineering.js

@@ -0,0 +1,55 @@
+/**
+ * 专业工程相关常量
+ *
+ * @author CaiAoLin
+ * @date 2017/8/7
+ * @version
+ */
+const engineering = {
+    // 建筑工程
+    ARCHITECTURE: 1,
+    // 装饰工程
+    DECORATE: 2,
+    // 仿古建筑工程
+    ANTIQUE_ARCHITECTURE: 3,
+    // 安装工程
+    BUILD_IN: 4,
+    // 市政土建工程
+    MUNICIPAL_CONSTRUCTION: 5,
+    // 市政安装工程
+    MUNICIPAL_BUILD_IN: 6,
+    // 人工土石方工程
+    ARTIFICIAL_EARTHWORK: 7,
+    // 机械土石方工程
+    MECHANICAL_EARTHWORK: 8,
+    // 炉窖砌筑工程
+    KILN_MASONRY: 9,
+    // 园林工程
+    GARDEN: 10,
+    // 绿化工程
+    PLANTING: 11,
+    // 单拆除工程
+    DISMANTLE: 12,
+    // 建筑修缮工程
+    BUILDING_REPAIR: 13,
+    // 安装修缮工程
+    BUILD_IN_REPAIR: 14
+};
+const engineeringList = [
+    {name: "建筑工程", value: engineering.ARCHITECTURE},
+    {name: "装饰工程", value: engineering.DECORATE},
+    {name: "仿古建筑工程", value: engineering.ANTIQUE_ARCHITECTURE},
+    {name: "安装工程", value: engineering.BUILD_IN},
+    {name: "市政土建工程", value: engineering.MUNICIPAL_CONSTRUCTION},
+    {name: "市政安装工程", value: engineering.MUNICIPAL_BUILD_IN},
+    {name: "人工土石方工程", value: engineering.ARTIFICIAL_EARTHWORK},
+    {name: "机械土石方工程", value: engineering.MECHANICAL_EARTHWORK},
+    {name: "炉窖砌筑工程", value: engineering.KILN_MASONRY},
+    {name: "园林工程", value: engineering.GARDEN},
+    {name: "绿化工程", value: engineering.PLANTING},
+    {name: "单拆除工程", value: engineering.DISMANTLE},
+    {name: "建筑修缮工程", value: engineering.BUILDING_REPAIR},
+    {name: "安装修缮工程", value: engineering.BUILD_IN_REPAIR},
+];
+
+export {engineering as default, engineeringList as List};

+ 18 - 0
modules/common/const/province_const.js

@@ -0,0 +1,18 @@
+/**
+ * 省份常量
+ *
+ * @author CaiAoLin
+ * @date 2017/8/1
+ * @version
+ */
+const province = {
+    CHONGQING: 1,
+    GUANGDONG: 2
+};
+
+const provinceList = [
+    {id: province.CHONGQING, name: '重庆省'},
+    {id: province.GUANGDONG, name: '广东省'}
+];
+
+export {province as default, provinceList as List};

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

@@ -192,6 +192,70 @@ class MongooseHelper {
     }
 
     /**
+     * 自增
+     *
+     * @param {Object} condition
+     * @param {Object} incData
+     * @return {Promise}
+     */
+    incr(condition, incData) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            condition = self._convertId(condition);
+            self.model.update(condition, {$inc: incData}, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 嵌套结构的新增
+     *
+     * @param {Object} condition
+     * @param {Object} insertData
+     * @return {Promise}
+     */
+    addToSet(condition, insertData) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            condition = self._convertId(condition);
+            self.model.update(condition, {$addToSet: insertData}, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * 删除嵌套结构数据
+     *
+     * @param {Object} condition
+     * @param {Object} deleteData
+     * @return {Promise}
+     */
+    deleteSet(condition, deleteData) {
+        let self = this;
+        return new Promise(function(resolve, reject) {
+            condition = self._convertId(condition);
+            self.model.update(condition, {$pull: deleteData}, function(error, data) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(data);
+                }
+            });
+        });
+    }
+
+
+    /**
      * id转换为objectId
      *
      * @param {object} condition

+ 33 - 0
modules/common/std/schemas/std_bills_lib_lists.js

@@ -0,0 +1,33 @@
+/**
+ * 标准清单库数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'std_bills_lib_lists';
+let modelSchema = {
+    // 自增id
+    billsLibId: String,
+    // 添加信息的管理员
+    creator: String,
+    // 创建时间
+    createDate: String,
+    // 名称
+    billsLibName: String,
+    // 地区/省份字段
+    localeType: {
+        type: Number,
+        index: true
+    },
+    // 是否被删除
+    deleted: Boolean,
+    // 最近操作记录
+    recentOpr: Schema.Types.Mixed
+};
+
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 32 - 0
modules/common/std/schemas/std_ration_lib_map.js

@@ -0,0 +1,32 @@
+/**
+ * 定额库数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/8/1
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'std_ration_lib_map';
+let modelSchema = {
+    // 自增id
+    ID: {
+        type: Number,
+        index: true
+    },
+    // 展示名称
+    dispName: String,
+    // app类型
+    appType: Number,
+    // 地区/省份类型
+    localeType: {
+        type: Number,
+        index: true
+    },
+    descr: String,
+    // 是否被删除
+    deleted: Boolean
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 53 - 0
modules/common/std/std_bills_lib_lists_model.js

@@ -0,0 +1,53 @@
+/**
+ * 标准清单库
+ *
+ * @author CaiAoLin
+ * @date 2017/8/4
+ * @version
+ */
+import BaseModel from "../../common/base/base_model";
+import STDBillsLibListsSchema from "./schemas/std_bills_lib_lists";
+
+class STDBillsLibListsModel extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = STDBillsLibListsSchema;
+        parent.init();
+    }
+
+    /**
+     * 获取标准清单
+     *
+     * @return {Promise}
+     */
+    async getBillList() {
+        let result = false;
+        let billLib = await this.findDataByCondition({deleted: false}, null, false);
+        if (billLib.length <= 0) {
+            return result;
+        }
+
+        // 整理数据
+        let billList = {};
+        for(let tmp of billLib) {
+            let tmpRation = {id: tmp.billsLibId, name: tmp.billsLibName};
+            if (billList[tmp.localeType] === undefined) {
+                billList[tmp.localeType] = [tmpRation];
+            } else {
+                billList[tmp.localeType].push(tmpRation);
+            }
+        }
+
+        result = billList;
+        return result;
+    }
+
+}
+
+export default STDBillsLibListsModel;

+ 53 - 0
modules/common/std/std_ration_lib_map_model.js

@@ -0,0 +1,53 @@
+/**
+ * 定额库业务逻辑模型
+ *
+ * @author CaiAoLin
+ * @date 2017/8/1
+ * @version
+ */
+import BaseModel from "../base/base_model";
+import STDRationLibMapSchema from "./schemas/std_ration_lib_map";
+
+class STDRationLibMapModel extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = STDRationLibMapSchema;
+        parent.init();
+    }
+
+    /**
+     * 获取定额库
+     *
+     * @return {Promise}
+     */
+    async getRationLib() {
+        let result = false;
+        let rationLib = await this.findDataByCondition({deleted: false}, null, false);
+        if (rationLib.length <= 0) {
+            return result;
+        }
+
+        // 整理数据
+        let rationData = {};
+        for(let tmp of rationLib) {
+            let tmpRation = {id: tmp.ID, name: tmp.dispName};
+            if (rationData[tmp.localeType] === undefined) {
+                rationData[tmp.localeType] = [tmpRation];
+            } else {
+                rationData[tmp.localeType].push(tmpRation);
+            }
+        }
+
+        result = rationData;
+        return result;
+    }
+
+}
+
+export default STDRationLibMapModel;

+ 147 - 3
modules/ration_repository/models/ration_item.js

@@ -213,9 +213,153 @@ function round(v,e){
 }
 
 rationItemDAO.prototype.updateRationBasePrc = function (data, callback) {
-    let adjGljId = data.gljId, adjBasePrice = data.basePrice, adjGljType = data.gljType,
+    let basePrcArr = data.basePrcArr,
+       // adjGljId = data.gljId, adjBasePrice = data.basePrice, adjGljType = data.gljType,
         repId = data.repId, lastOpr = data.lastOpr;
-    async.waterfall([
+    //
+    let updateArr;
+    async.each(basePrcArr, function (basePrcObj, finalCb) {
+        let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
+        async.waterfall([
+            function (cb) {
+                rationItemModel.find({'rationGljList.gljId': adjGljId}, function (err, result) {
+                    if(err){
+                        cb(err);
+                    }
+                    else{
+                        cb(null, result);
+                    }
+                });
+            },
+            function (result, cb) {
+                async.each(result, function (rationItem, ecb) {
+                    let rationGljList = rationItem.rationGljList,
+                        gljIds = [];
+                    rationGljList.forEach(function (rationGlj) {
+                        gljIds.push(rationGlj.gljId);
+                    });
+                    gljDao.getGljItems(gljIds, function(err, gljItems){
+                        if(err){
+                            ecb(err);
+                        }
+                        else{
+                            let gljArr = [];
+                            for(let i=0; i<gljItems.length; i++){
+                                let gljParentType = -1;
+                                if(gljItems[i].ID === adjGljId){
+                                    gljItems[i].gljType = adjGljType;
+                                }
+                                if(gljItems[i].gljType <= 3){
+                                    gljParentType = gljItems[i].gljType;
+                                }
+                                if(gljItems[i].gljType > 200 && gljItems[i].gljType < 300){
+                                    gljParentType = 2;
+                                }
+                                if(gljItems[i].gljType > 300 && gljItems[i].gljType < 400){
+                                    gljParentType = 3;
+                                }
+                                if(gljItems[i].ID === adjGljId){
+                                    gljArr.push({gljId: gljItems[i].ID, basePrice: adjBasePrice, gljParentType: gljParentType});
+                                }
+                                else {
+                                    gljArr.push({gljId: gljItems[i].ID, basePrice: gljItems[i].basePrice, gljParentType: gljParentType});
+                                }
+                            }
+                            gljArr.forEach(function (gljItem) {
+                                rationGljList.forEach(function (rationGlj) {
+                                    if(gljItem.gljId === rationGlj.gljId){
+                                        gljItem.consumeAmt = rationGlj.consumeAmt;
+                                    }
+                                })
+                            });
+                            //recalculate the price of ration
+                            let labourPrc = [], materialPrc = [], machinePrc = [], singlePrc, updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, basePrice: 0};
+                            gljArr.forEach(function (gljItem) {
+                                if(gljItem.gljParentType !== -1){
+                                    singlePrc = round(gljItem.basePrice * gljItem.consumeAmt, 3);
+                                    if(gljItem.gljParentType === 1){
+                                        labourPrc.push(singlePrc);
+                                    }
+                                    else if(gljItem.gljParentType ===2){
+                                        materialPrc.push(singlePrc);
+                                    }
+                                    else{
+                                        machinePrc.push(singlePrc);
+                                    }
+                                }
+                            });
+                            if(labourPrc.length > 0){
+                                let sumLaP = 0;
+                                for(let i=0; i<labourPrc.length; i++){
+                                    sumLaP += labourPrc[i];
+                                }
+                                updatePrc.labourPrice = round(sumLaP, 2);
+                            }
+                            if(materialPrc.length > 0){
+                                let sumMtP = 0;
+                                for(let i= 0; i<materialPrc.length; i++){
+                                    sumMtP += materialPrc[i];
+                                }
+                                updatePrc.materialPrice = round(sumMtP, 2);
+                            }
+                            if(machinePrc.length > 0){
+                                let sumMaP = 0;
+                                for(let i =0; i< machinePrc.length; i++){
+                                    sumMaP += machinePrc[i];
+                                }
+                                updatePrc.machinePrice = round(sumMaP, 2);
+                            }
+                            updatePrc.basePrice = updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice;
+                            //updateDataBase
+                            rationItemModel.update({ID: rationItem.ID}, {$set: {labourPrice: updatePrc.labourPrice, materialPrice: updatePrc.materialPrice,
+                                    machinePrice: updatePrc.machinePrice, basePrice: updatePrc.basePrice}},
+                                function (err, result) {
+                                    if(err){
+                                        ecb(err);
+                                    }
+                                    else {
+                                        ecb(null);
+                                    }
+                                });
+                        }
+                    });
+                }, function(err){
+                    if(err){
+                        cb(err);
+                    }
+                    else {
+                        cb(null);
+                    }
+                });
+            },
+            function (cb) {
+                rationRepositoryDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
+                    if(err){
+                        cb(err);
+                    }
+                    else{
+                        cb(null);
+                    }
+                })
+            }
+        ], function (err) {
+            if(err){
+                finalCb(err);
+            }
+            else{
+                finalCb(null);
+            }
+        });
+    }, function (err) {
+        if(err){
+            callback(err, 'Error');
+        }
+        else{
+            callback(null, '');
+        }
+    });
+    //
+    /*async.waterfall([
         function (cb) {
             rationItemModel.find({'rationGljList.gljId': adjGljId}, function (err, result) {
                 if(err){
@@ -344,7 +488,7 @@ rationItemDAO.prototype.updateRationBasePrc = function (data, callback) {
         else{
             callback(null, '');
         }
-    });
+    });*/
 };
 
 rationItemDAO.prototype.getRationGljIds = function (data, callback) {

+ 49 - 1
modules/users/controllers/login_controller.js

@@ -9,6 +9,10 @@ import BaseController from "../../common/base/base_controller";
 import ManagerModel from "../models/manager_model";
 import crypto from "crypto";
 
+import Test1Model from "../../../test/models/test1_model";
+import Test2Model from "../../../test/models/test2_model";
+import Test3Model from "../../../test/models/test3_model";
+
 class LoginController extends BaseController {
 
     /**
@@ -72,7 +76,7 @@ class LoginController extends BaseController {
             };
             let updateResult = managerModel.updateById(managerData._id, updateData);
             if (!updateResult) {
-                throw '更新登录信息失败!';
+                throw {code: 44003, err: '更新登录信息失败!'};
             }
         } catch (error) {
             responseData.error = error.code;
@@ -95,6 +99,50 @@ class LoginController extends BaseController {
         response.redirect('/login');
     }
 
+    /**
+     * 压测接口
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async test(request, response) {
+        let responseData = {
+            error: 0,
+            msg: ''
+        };
+        try {
+
+            // 第一个库的操作
+            let test1Model = new Test1Model();
+            let test1Result = await test1Model.test();
+            if (!test1Result) {
+                throw 'test1出错';
+            }
+
+            // 第二个库操作
+            let test2Model = new Test2Model();
+            let test2Result = await test2Model.test();
+            if (!test2Result) {
+                throw 'test2出错';
+            }
+
+            // 第三个库操作
+            let test3Model = new Test3Model();
+            let test3Result = await test3Model.test();
+            if (!test3Result) {
+                throw 'test3出错';
+            }
+
+        } catch (error) {
+            console.log(error);
+            responseData.error = 1;
+            responseData.msg = error;
+        }
+
+        response.json(responseData);
+    }
+
 }
 
 export default LoginController;

+ 152 - 52
modules/users/controllers/version_controller.js

@@ -7,6 +7,10 @@
  */
 import BaseController from "../../common/base/base_controller";
 import VersionModel from "../models/version_model";
+import STDRationLibMapModel from "../../common/std/std_ration_lib_map_model";
+import STDBillLibListsModel from "../../common/std/std_bills_lib_lists_model";
+import {default as ProvinceConst, List as ProvinceList} from "../../common/const/province_const";
+import {default as EngineeringConst, List as EngineeringList} from "../../common/const/engineering";
 
 class VersionController extends BaseController {
 
@@ -21,33 +25,6 @@ class VersionController extends BaseController {
         let id = request.query.id;
 
         let versionList = [];
-        // @todo 后续从库中获取
-        let province = [
-            {id: 1, name: '重庆省'},
-            {id: 2, name: '广东省'},
-        ];
-
-        let billList = {
-            1: [
-                {id: '1', name: '重庆2017标准清单'},
-                {id: '2', name: '重庆2015标准清单'}
-            ],
-            2: [
-                {id: '3', name: '广东2017标准清单'},
-                {id: '4', name: '广东2015标准清单'},
-            ]
-        };
-
-        let rationList = {
-            1: [
-                {id: '1', name: '重庆2017定额'},
-                {id: '2', name: '重庆2015定额'}
-            ],
-            2: [
-                {id: '3', name: '广东2017定额'},
-                {id: '4', name: '广东2015定额'}
-            ]
-        };
         let selectedVersion = {};
         try {
             let versionModel = new VersionModel();
@@ -65,6 +42,7 @@ class VersionController extends BaseController {
             }
 
             selectedVersion = Object.keys(selectedVersion).length <= 0 ? versionList[0] : selectedVersion;
+            request.session.selectedVersion = selectedVersion;
 
         } catch (error) {
             console.log(error);
@@ -74,9 +52,6 @@ class VersionController extends BaseController {
             id: id,
             versionList: versionList,
             selectedVersion: selectedVersion,
-            billList: JSON.stringify(billList),
-            rationList: JSON.stringify(rationList),
-            province: JSON.stringify(province),
             layout: 'users/views/layout/layout'
         };
 
@@ -84,35 +59,35 @@ class VersionController extends BaseController {
     }
 
     /**
-     * 新增版本操作
+     * 新增计价页面
      *
      * @param {object} request
      * @param {object} response
      * @return {void}
      */
-    async add(request, response) {
+    async addValuation(request, response) {
         let name = request.body.name;
-        let standardBillId = request.body.standard_bill_id;
-        let standardBill = request.body.standard_bill;
-        let rationLibId = request.body.ration_lib_id;
-        let rationLib = request.body.ration_lib;
+        let id = request.body.id;
+        let section = request.body.section;
 
         let responseData = {
             err: 0,
             msg: ''
         };
         try {
+            if (id === undefined || id === '') {
+                throw '参数错误';
+            }
+
             let insertData = {
                 name: name,
-                standard_bill: [{id: standardBillId, name: standardBill}],
-                ration_lib: [{id: rationLibId, name: rationLib}]
             };
 
             let versionModel = new VersionModel();
-            let result = await versionModel.add(insertData);
+            let result = await versionModel.addValuation(id, section, insertData);
 
             if (!result) {
-                throw '新增版本失败';
+                throw '新增计价规则失败';
             }
         } catch (error) {
             console.log(error);
@@ -124,24 +99,144 @@ class VersionController extends BaseController {
     }
 
     /**
-     * 新增标准清单/定额库
+     * 修改计价规则页面
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async editValuation(request, response) {
+        let selectedVersion = request.session.selectedVersion;
+        let valuationId = request.params.id;
+        let section = request.params.section;
+
+        let billList = {};
+        let rationList = {};
+        let versionList = [];
+        let valuationData = {};
+        let valuationList = {};
+        try {
+            let versionModel = new VersionModel();
+            versionList = await versionModel.getVersionList();
+
+            // 获取标准清单
+            let stdBillLibListsModel = new STDBillLibListsModel();
+            billList = await stdBillLibListsModel.getBillList();
+
+            // 获取定额库
+            let stdRationLibMapModel = new STDRationLibMapModel();
+            rationList = await stdRationLibMapModel.getRationLib();
+
+            // 获取对应的计价规则数据
+            [valuationData, valuationList] = await versionModel.getValuation(selectedVersion._id, valuationId, section);
+            if (Object.keys(valuationData).length <= 0) {
+                throw '不存在数据';
+            }
+
+        } catch (error) {
+            console.log(error);
+        }
+
+        let renderData = {
+            versionList: versionList,
+            billList: JSON.stringify(billList),
+            rationList: JSON.stringify(rationList),
+            province: JSON.stringify(ProvinceList),
+            engineeringList: EngineeringList,
+            selectedVersion: selectedVersion,
+            valuationData: valuationData,
+            valuationList: valuationList,
+            valuationId: valuationId,
+            section: section,
+            layout: 'users/views/layout/layout'
+        };
+        response.render('users/views/version/add', renderData);
+    }
+
+    /**
+     * 保存计价规则
      *
      * @param {object} request
      * @param {object} response
      * @return {void}
      */
-    async addLib(request, response) {
+    async saveValuation(request, response) {
+        let valuationId = request.body.id;
+        try {
+            if (valuationId === '') {
+                throw 'id参数错误';
+            }
+
+            let versionModel = new VersionModel();
+            let result = await versionModel.saveValuation(valuationId, request.body);
+
+            if (!result) {
+                throw '保存失败';
+            }
+
+        } catch (error) {
+            console.log(error);
+        }
+
+        response.redirect(request.headers.referer);
+    }
+
+    /**
+     * 删除计价规则
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async deleteValuation(request, response) {
+        let id = request.params.id;
+        let section = request.params.section;
+        let selectedVersion = request.session.selectedVersion;
+
+        try {
+            if (id === undefined || id === '' || section === undefined || section === '') {
+                throw '参数错误';
+            }
+
+            let versionModel = new VersionModel();
+            let result = versionModel.deleteValuation(selectedVersion._id, id, section);
+
+            if (!result) {
+                throw '删除失败';
+            }
+
+        } catch (error) {
+            console.log(error);
+        }
+
+        response.redirect(request.headers.referer);
+    }
+
+    /**
+     * 快速切换启用/禁用
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async enableSwitch(request, response) {
+        let id = request.body.id;
+        let section = request.params.section;
+        let enable = request.body.enable;
+
         let responseData = {
             err: 0,
             msg: ''
         };
         try {
             let versionModel = new VersionModel();
-            let addResult = await versionModel.addLib(request.body);
-            if (!addResult) {
-                throw '新增失败';
+            let result = await versionModel.switchEnable(id, section, enable);
+
+            if (!result) {
+                throw '新增版本失败';
             }
         } catch (error) {
+            console.log(error);
             responseData.err = 1;
             responseData.msg = error;
         }
@@ -150,28 +245,33 @@ class VersionController extends BaseController {
     }
 
     /**
-     * 删除对应的标准清单/定额库
+     * 新增版本操作
      *
      * @param {object} request
      * @param {object} response
      * @return {void}
      */
-    async deleteLib(request, response) {
-        let id = request.body.id;
-        let model = request.body.model;
-        let deleteId = request.body.delete_id;
+    async addVersion(request, response) {
+        let name = request.body.name;
         let responseData = {
             err: 0,
             msg: ''
         };
         try {
+            let sessionManager = request.session.managerData;
+            let insertData = {
+                name: name,
+                creator: sessionManager.userID
+            };
+
             let versionModel = new VersionModel();
-            let result = await versionModel.deleteLib(id, deleteId, model);
+            let result = await versionModel.add(insertData);
 
             if (!result) {
-                throw '删除失败';
+                throw '新增版本失败';
             }
         } catch (error) {
+            console.log(error);
             responseData.err = 1;
             responseData.msg = error;
         }

+ 50 - 6
modules/users/models/schemas/version.js

@@ -9,18 +9,62 @@ import mongoose from "mongoose";
 
 let Schema = mongoose.Schema;
 let collectionName = 'version';
+let childrenSchema = new Schema({
+    // 计价名称
+    name: String,
+    // 工程专业
+    engineering: {
+        type: Number,
+        default: ''
+    },
+    // 标准清单
+    bill_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    // 定额库
+    ration_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    // 是否启用
+    enable: {
+        type: Boolean,
+        default: false
+    },
+    // 类型
+    type: {
+        type: Number
+    }
+});
 let modelSchema = {
+    // 是否发布
+    is_release: {
+        type: Boolean,
+        default: false
+    },
     // 自增id
     id: {
-        type: Number,
-        index: true
+        type: Number
+    },
+    // 清单计价规则
+    bill_valuation: {
+        type: [childrenSchema],
+        default: []
+    },
+    // 定额计价规则
+    ration_valuation: {
+        type: [childrenSchema],
+        default: []
     },
     // 名称
     name: String,
-    // 标准清单
-    standard_bill: Schema.Types.Mixed,
-    // 定额库
-    ration_lib: Schema.Types.Mixed
+    // 创建时间
+    create_time: Number,
+    // 创建者id
+    creator: String,
+    // 最后修改时间
+    update_time: Number
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 export {model as default, collectionName as collectionName};

+ 163 - 63
modules/users/models/version_model.js

@@ -11,6 +11,13 @@ import VersionSchema from "./schemas/version";
 class VersionModel extends BaseModel {
 
     /**
+     * 允许的块
+     *
+     * @var {Array}
+     */
+    sectionList = ['bill', 'ration'];
+
+    /**
      * 构造函数
      *
      * @return {void}
@@ -27,7 +34,10 @@ class VersionModel extends BaseModel {
      * @return {Promise}
      */
     async getVersionList() {
-        let versionData = await this.findDataByCondition({name: {$ne: ''}}, null, false);
+        // 筛选字段
+        let field = {_id: 1, name: 1, "ration_valuation._id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
+            "bill_valuation._id": 1, "bill_valuation.name": 1, "bill_valuation.enable": 1};
+        let versionData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
 
         return versionData === null ? [] : versionData;
     }
@@ -43,8 +53,8 @@ class VersionModel extends BaseModel {
             // 新增
             case 'add':
                 this.model.schema.path('name').required(true);
-                this.model.schema.path('standard_bill').required(true);
-                this.model.schema.path('ration_lib').required(true);
+                this.model.schema.path('creator').required(true);
+                this.model.schema.path('create_time').required(true);
                 break;
         }
     }
@@ -61,97 +71,187 @@ class VersionModel extends BaseModel {
             return result;
         }
 
+        this.setScene('add');
+        data.create_time = new Date().getTime();
         result = this.db.create(data);
         return result;
     }
 
     /**
-     * 新增标准清单/定额库
+     * 新增计价规则
      *
-     * @param {Object} postData
+     * @param {String} id
+     * @param {String} section
+     * @param {Object} data
      * @return {Promise}
      */
-    async addLib(postData) {
-        if (postData.id === undefined || postData.model === undefined) {
-            throw '参数错误';
-        }
-        let model = postData.model;
-        let id = postData.id;
-        let standardBillId = postData.standard_bill_id;
-        let standardBill = postData.standard_bill;
-        let rationLibId = postData.ration_lib_id;
-        let rationLib = postData.ration_lib;
-
-        switch (model) {
-            case 'bill':
-                if (standardBillId === undefined || standardBill === undefined) {
-                    throw '参数错误';
-                }
-                break;
-            case 'ration':
-                if (rationLibId === undefined || rationLib === undefined) {
-                    throw '参数错误';
-                }
-                break;
-        }
-
-        let versionData = await this.findDataByCondition({_id: id});
-        if (versionData === null || versionData.standard_bill === undefined) {
+    async addValuation(id, section, data) {
+        let condition = {_id: id};
+        let versionData = await this.findDataByCondition(condition);
+        if (versionData === null || versionData.name === undefined) {
             throw '没有找到对应的数据';
         }
 
-        let updateData = {};
-        let field = model === 'bill' ? 'standard_bill' : 'ration_lib';
-        let tmpData = {
-            id: model === 'bill' ? standardBillId : rationLibId,
-            name: model === 'bill' ? standardBill : rationLib
-        };
-        versionData[field].push(tmpData);
-        updateData[field] = versionData[field];
+        if (data.name === undefined || data.name === '') {
+            throw '计价规则名称为空';
+        }
+        if (this.sectionList.indexOf(section) < 0) {
+            throw '数据有误';
+        }
 
-        let result = await this.db.update({_id: id}, updateData);
+        let insertData = {};
+        insertData[section + '_valuation'] = data;
+        let result = await this.db.addToSet(condition, insertData);
 
         return result.ok === undefined ? false : result.ok;
     }
 
     /**
-     * 删除对应的标准清单库/定额库
+     * 保存计价数据
      *
-     * @param {Number} id
-     * @param {Number} libId
-     * @param {String} model
+     * @param {String} valuationId
+     * @param {Object} data
      * @return {Promise}
      */
-    async deleteLib(id, libId, model) {
-        let versionData = await this.findDataByCondition({_id: id});
-        if (versionData === null || versionData.standard_bill === undefined) {
-            throw '没有找到对应的数据';
+    async saveValuation(valuationId, data) {
+        data = this._filterValuationData(data);
+        let sectionString = data.section + "_valuation";
+        let condition = {};
+        condition[sectionString + "._id"] = valuationId;
+
+        let updateData = {};
+        updateData[sectionString + ".$.bill_lib"] = data.bill_lib;
+        updateData[sectionString + ".$.ration_lib"] = data.ration_lib;
+        updateData[sectionString + ".$.name"] = data.name;
+        updateData[sectionString + ".$.engineering"] = data.engineering;
+
+        let result = await this.db.update(condition, updateData);
+
+        return result !== null && result.ok === 1;
+    };
+
+    /**
+     * 更改启用/禁用
+     *
+     * @param {String} valuationId
+     * @param {String} section
+     * @param {String} enable
+     * @return {Promise}
+     */
+    async switchEnable(valuationId, section, enable) {
+        let sectionString = section + "_valuation";
+        let condition = {};
+        condition[sectionString + "._id"] = valuationId;
+
+        let updateData = {};
+        updateData[sectionString + ".$.enable"] = enable === "true";
+
+        let result = await this.db.update(condition, updateData);
+
+        return result !== null && result.ok === 1;
+    }
+
+    /**
+     * 过滤计价数据
+     *
+     * @param {Object} data
+     * @return {Object}
+     */
+    _filterValuationData(data) {
+        if (Object.keys(data).length <= 0) {
+            throw '数据有误';
+        }
+
+        if (data.section === undefined || data.section === '' || this.sectionList.indexOf(data.section) < 0) {
+            throw '类型错误';
+        }
+
+        // 判断名称
+        if (data.name === undefined || data.name === '') {
+            throw '名称不能为空';
         }
+        // 判断工程专业
+        if (data.engineering === undefined || data.engineering === '') {
+            throw '名称不能为空';
+        }
+        data.engineering = parseInt(data.engineering);
+        // 判断标准清单
+        if (data.bill_lib === undefined || data.bill_lib === '') {
+            throw '判断标准清单不能为空';
+        }
+        data.bill_lib = data.bill_lib instanceof Array ? data.bill_lib : [data.bill_lib];
+        for(let tmp in data.bill_lib) {
+            data.bill_lib[tmp] = JSON.parse(data.bill_lib[tmp]);
+        }
+        // 判断定额清单
+        if (data.ration_lib === undefined || data.ration_lib === '') {
+            throw '判断标准清单不能为空';
+        }
+        data.ration_lib = data.ration_lib instanceof Array ? data.ration_lib : [data.ration_lib];
+        for(let tmp in data.ration_lib) {
+            data.ration_lib[tmp] = JSON.parse(data.ration_lib[tmp]);
+        }
+
+        return data;
+    }
 
-        let field = model === 'bill' ? 'standard_bill' : 'ration_lib';
-        if (versionData[field].length <= 0) {
-            throw '没有对应的库数据';
+    /**
+     * 获取计价规则数据
+     *
+     * @param {String} versionId
+     * @param {String} id
+     * @param {String} section
+     * @return {Promise|Array}
+     */
+    async getValuation(versionId, id, section) {
+        if (this.sectionList.indexOf(section) < 0) {
+            throw '数据有误';
+        }
+        let versionData = await this.findDataByCondition({_id: versionId});
+        if (Object.keys(versionData).length <= 0) {
+            throw '版本数据有误';
         }
+        let result = {};
+        let sectionString = section + '_valuation';
 
-        let own = false;
-        for (let index in versionData[field]) {
-            if (versionData[field][index].id === libId) {
-                versionData[field].splice(index, 1);
-                own = true;
+        for(let valuation of versionData[sectionString]) {
+            if (valuation._id.toString() === id) {
+                result = valuation;
                 break;
             }
         }
 
-        if (!own) {
-            throw '没有对应的库数据';
-        }
-        let updateData = {};
-        updateData[field] = versionData[field];
-        let result = await this.db.update({_id: id}, updateData);
+        return [result, versionData[sectionString]];
+        /* 数据库获取版本
+        let condition = {_id: versionId};
+        let childCondition = {};
+        childCondition[sectionString] = {$elemMatch: {_id: id}};
 
-        return result.ok === undefined ? false : result.ok;
+        let result = await this.db.findOne(condition, childCondition);
+
+        return result !== null && result.bill_valuation.length > 0 ? result.bill_valuation[0] : {};
+        */
     }
 
+    /**
+     * 删除计价规则
+     *
+     * @param {String} versionId
+     * @param {String} valuationId
+     * @param {String} section
+     * @return {Promise}
+     */
+    async deleteValuation(versionId, valuationId, section) {
+        let condition = {_id: versionId};
+        let sectionString = section + '_valuation';
+        let deleteData = {};
+        deleteData[sectionString] = {_id: valuationId};
+
+        // 利用pull删除嵌套数据
+        let result = await this.db.deleteSet(condition, deleteData);
+
+        return result !== null && result.ok === 1;
+    }
 
 }
 

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

@@ -17,6 +17,7 @@ module.exports =function (app) {
     router.get('/', loginController.index);
     router.post('/login', loginController.login);
     router.get('/logout', loginController.logout);
+    router.get('/test', loginController.test);
 
     app.use("/login", router);
     app.use("/", router);

+ 6 - 3
modules/users/routes/version_route.js

@@ -14,9 +14,12 @@ const versionController = new VersionController();
 module.exports =function (app) {
     // action定义区域
     router.get('/', versionController.auth, versionController.init, versionController.index);
-    router.post('/add', versionController.auth, versionController.init, versionController.add);
-    router.post('/addLib', versionController.auth, versionController.init, versionController.addLib);
-    router.post('/deleteLib', versionController.auth, versionController.init, versionController.deleteLib);
+    router.get('/valuation/:section/:id', versionController.auth, versionController.init, versionController.editValuation);
+    router.get('/valuation/:section/delete/:id', versionController.auth, versionController.init, versionController.deleteValuation);
+    router.post('/add', versionController.auth, versionController.init, versionController.addVersion);
+    router.post('/add-valuation', versionController.auth, versionController.init, versionController.addValuation);
+    router.post('/save-valuation', versionController.auth, versionController.init, versionController.saveValuation);
+    router.post('/valuation/:section/enable', versionController.auth, versionController.init, versionController.enableSwitch);
 
     app.use("/version", router);
 };

+ 3 - 3
operation.js

@@ -21,7 +21,7 @@ dbm.connect();
 //引入报表模块
 fileUtils.getGlobbedFiles('./modules/reports/models/*.js').forEach(function(modelPath) {
     require(path.resolve(modelPath));
-})
+});
 
 
 //config.setupCache();
@@ -41,7 +41,7 @@ app.set('view options', {
 app.use(partials());
 
 let bodyParser = require('body-parser');
-app.use(bodyParser.urlencoded({extended: false}));
+app.use(bodyParser.urlencoded({extended: true}));
 app.use(bodyParser.json());
 
 app.use(session({
@@ -74,7 +74,7 @@ app.use(function (req, res, next) {
 //加载路由文件
 fileUtils.getGlobbedFiles('./modules/**/routes/*.js').forEach(function(modelPath) {
     require(path.resolve(modelPath))(app);
-})
+});
 
 app.use(function(req, res, next) {
     res.status(404).send('404 Error');

+ 4 - 2
public/web/sheet/sheet_common.js

@@ -7,6 +7,7 @@ var sheetCommonObj = {
     createSpread: function(container, SheetCount){
         var me = this;
         var spreadBook = new GC.Spread.Sheets.Workbook(container, { sheetCount: SheetCount });
+        spreadBook.options.allowCopyPasteExcelStyle = false;
         spreadBook.options.tabStripVisible = false;
         spreadBook.options.showHorizontalScrollbar = false;
         return spreadBook;
@@ -34,6 +35,7 @@ var sheetCommonObj = {
         spreadBook.options.tabStripVisible = false;
         spreadBook.options.showHorizontalScrollbar = false;
         spreadBook.options.scrollbarMaxAlign = true;
+        spreadBook.options.allowCopyPasteExcelStyle = false;
         var spreadNS = GC.Spread.Sheets;
         var sheet = spreadBook.getSheet(0);
         sheet.suspendPaint();
@@ -124,10 +126,10 @@ var sheetCommonObj = {
         //me.shieldAllCells(sheet);
     },
     analyzePasteData: function(setting, pastedInfo) {
-        var rst = [], propId = 0, preStrIdx = 0, itemObj = {};
+        var rst = [], propId = pastedInfo.cellRange.col, preStrIdx = 0, itemObj = {};
         for (var i = 0; i < pastedInfo.pasteData.text.length; i++) {
             if (pastedInfo.pasteData.text[i] === "\n") {
-                propId = 0;
+                propId = pastedInfo.cellRange.col;
                 preStrIdx = i + 1;
                 rst.push(itemObj);
                 if (i < pastedInfo.pasteData.text.length - 1) {

+ 19 - 0
test/models/schemas/test1.js

@@ -0,0 +1,19 @@
+/**
+ * 压测数据模型1
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'test1';
+let modelSchema = {
+    name: String,
+    value: {
+        type: Number
+    }
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 19 - 0
test/models/schemas/test2.js

@@ -0,0 +1,19 @@
+/**
+ * 压测数据模型2
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'test2';
+let modelSchema = {
+    name: String,
+    value: {
+        type: Number
+    },
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 19 - 0
test/models/schemas/test3.js

@@ -0,0 +1,19 @@
+/**
+ * 压测数据模型3
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'test3';
+let modelSchema = {
+    name: String,
+    value: {
+        type: Number
+    },
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 47 - 0
test/models/test1_model.js

@@ -0,0 +1,47 @@
+/**
+ * 压测模块1
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import BaseModel from "../../modules/common/base/base_model";
+import Test1Schema from "./schemas/test1";
+
+class Test1Model extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = Test1Schema;
+        parent.init();
+    }
+
+    /**
+     * 初始化数据
+     *
+     * @return {Promise}
+     */
+    async test() {
+        let name = 'test1';
+        // let update = {$inc: {value: 1}};
+        let update = {value: 1};
+        let condition = {name: name};
+        let options = {new: true};
+
+        // 先查找更新
+        // let idData = await this.db.findAndModify(condition, update, options);
+        let idData = await this.db.incr(condition, update);
+
+        // return idData !== null;
+        return idData !== null && idData.ok === 1;
+    }
+
+}
+
+export default Test1Model;
+

+ 46 - 0
test/models/test2_model.js

@@ -0,0 +1,46 @@
+/**
+ * 压测模块1
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import BaseModel from "../../modules/common/base/base_model";
+import Test2Schema from "./schemas/test2";
+
+class Test2Model extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = Test2Schema;
+        parent.init();
+    }
+
+    /**
+     * 初始化数据
+     *
+     * @return {Promise}
+     */
+    async test() {
+        let name = 'test2';
+        // let update = {$inc: {value: 1}};
+        let update = {value: 1};
+        let condition = {name: name};
+        let options = {new: true};
+
+        // 先查找更新
+        // let idData = await this.db.findAndModify(condition, update, options);
+        let idData = await this.db.incr(condition, update);
+
+        // return idData !== null;
+        return idData !== null && idData.ok === 1;
+    }
+}
+
+export default Test2Model;
+

+ 46 - 0
test/models/test3_model.js

@@ -0,0 +1,46 @@
+/**
+ * 压测模块1
+ *
+ * @author CaiAoLin
+ * @date 2017/8/3
+ * @version
+ */
+import BaseModel from "../../modules/common/base/base_model";
+import Test3Schema from "./schemas/test3";
+
+class Test3Model extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor() {
+        let parent = super();
+        parent.model = Test3Schema;
+        parent.init();
+    }
+
+    /**
+     * 初始化数据
+     *
+     * @return {Promise}
+     */
+    async test() {
+        let name = 'test3';
+        // let update = {$inc: {value: 1}};
+        let update = {value: 1};
+        let condition = {name: name};
+        let options = {new: true};
+
+        // 先查找更新
+        // let idData = await this.db.findAndModify(condition, update, options);
+        let idData = await this.db.incr(condition, update);
+
+        // return idData !== null;
+        return idData !== null && idData.ok === 1;
+    }
+}
+
+export default Test3Model;
+

+ 59 - 36
web/maintain/ration_repository/js/ration.js

@@ -15,6 +15,7 @@ var rationOprObj = {
     currentRations: {},
     currentEditingRation: null,
     currentSectionId: -1,
+    activeCell: null,
     rationsCodes: [],
     setting: {
         header:[
@@ -61,13 +62,13 @@ var rationOprObj = {
             sheetGLJ = rationGLJOprObj.sheet, settingGLJ = rationGLJOprObj.setting,
             sheetCoe = rationCoeOprObj.sheet, settingCoe = rationCoeOprObj.setting,
             sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting;
+        me.activeCell = {row: args.row, col: args.col};
         sheetCommonObj.cleanSheet(sheetGLJ, settingGLJ, -1);
         sheetCommonObj.shieldAllCells(sheetGLJ);
         sheetCommonObj.cleanSheet(sheetCoe, settingCoe, -1);
         sheetCommonObj.shieldAllCells(sheetCoe);
         sheetCommonObj.cleanSheet(sheetAss, settingAss, -1);
         sheetCommonObj.shieldAllCells(sheetAss);
-
         if(!(args.sheetArea === GC.Spread.Sheets.SheetArea.colHeader || args.sheetArea === GC.Spread.Sheets.SheetArea.corner)){
             var cacheSection = me.getCache();
             if (cacheSection && args.row < cacheSection.length) {
@@ -126,7 +127,6 @@ var rationOprObj = {
         return cacheSection;
     },
     rationDelOpr: function () {
-        console.log(`rebuildDelete`);
         let me = rationOprObj;
         me.workBook.commandManager().register('rationDelete', function () {
             let rationSheet = me.workBook.getActiveSheet();
@@ -140,8 +140,6 @@ var rationOprObj = {
                                 if(sels[sel].row + i < cacheSection.length){
                                     removeArr.push(cacheSection[sels[sel].row + i].ID);
                                     me.rationsCodes.splice(me.rationsCodes.indexOf(cacheSection[sels[sel].row + i].code), 1);
-                                    console.log(`me.rationsCodes`);
-                                    console.log(me.rationsCodes);
                                 }
                             }
                         }
@@ -160,7 +158,7 @@ var rationOprObj = {
                         }
                         else if(sels[sel].col !== 0 && !(sels[sel].col === 3 && sels.col + sels[sel].colCount -1 === 6)){
                             if(cacheSection){
-                                for(let i =0; i < sels[sel].rowCount; i++){
+                                for(let i = sels[sel].row === -1 ? 1 : 0; i < sels[sel].rowCount; i++){
                                     if(sels[sel].row + i < cacheSection.length){
                                         for(let col = sels[sel].col; col <= sels[sel].col + sels[sel].colCount - 1; col++){
                                             if(lockCols.indexOf(col) === -1){
@@ -168,7 +166,9 @@ var rationOprObj = {
                                             }
                                         }
                                     }
-                                    updateArr.push(cacheSection[sels[sel].row + i]);
+                                    if(cacheSection[sels[sel].row + i] && typeof cacheSection[sels[sel].row + i] !== 'undefined'){
+                                        updateArr.push(cacheSection[sels[sel].row + i]);
+                                    }
                                 }
                             }
                         }
@@ -184,7 +184,6 @@ var rationOprObj = {
         me.workBook.commandManager().setShortcutKey('rationDelete', GC.Spread.Commands.Key.del, false, false, false, false);
     },
     onRangeChanged: function(sender, args) {
-        console.log(`sdad`);
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
             var me = rationOprObj, updateArr = [], removeArr = [];
             var cacheSection = me.getCache();
@@ -303,13 +302,13 @@ var rationOprObj = {
             if (!sheetCommonObj.chkIfEmpty(rObj, me.setting)) {
                 //addArr.push(rObj);
                 me.addRationItem = rObj;
-                if(rObj.code){
+                if(rObj.code && rObj.code.trim().length > 0){
                     if(me.rationsCodes.indexOf(rObj.code) === -1){
                         addArr.push(rObj);
                         me.rationsCodes.push(rObj.code);
                         me.addRationItem = null;
                     }
-                    else{
+                    else if(!rObj.code && rObj.code === ''){
                         $('#alertModalBtn').click();
                         me.workBook.getSheet(0).options.isProtected = true;
                         $('#alertModalCls').click(function () {
@@ -326,6 +325,9 @@ var rationOprObj = {
                         });
                     }
                 }
+                else if(rObj.code && rObj.code.trim().length === 0){
+                    me.workBook.getSheet(0).setValue(args.row, args.col, '');
+                }
             }
         }
         if (updateArr.length > 0 || addArr.length > 0) {
@@ -335,50 +337,68 @@ var rationOprObj = {
     },
     onClipboardPasting: function(sender, args) {
         var me = rationOprObj;
-        console.log(`args`);
-        console.log(args);
       /*  if (args.cellRange.colCount != me.setting.header.length) {
             args.cancel = true;
         }*/
     },
     onClipboardPasted: function(e, info) {
-        console.log(`info`);
-        console.log(info);
         var me = rationOprObj;
         var cacheSection = me.getCache();
-        console.log(`cache`);
-        console.log(cacheSection);
         var updateArr = [], addArr = [];
         var items = sheetCommonObj.analyzePasteData(me.setting, info);
-        console.log(`items`);
-        console.log(items);
-        for (var i = 0; i < items.length; i++) {
+        let failPasteArr = [];
+        for (var i = 0, rowIdx =info.cellRange.row; i < items.length; i++, rowIdx++) {
             if (cacheSection) {
-                var hasCacheItem = false;
-                for (var j = 0; j < cacheSection.length; j++) {
-                    if (cacheSection[j][me.setting.header[0].dataCode] == items[i][me.setting.header[0].dataCode]) {
-                        hasCacheItem = true;
-                        items[i]["ID"] = cacheSection[j]["ID"];
-                        break;
+                //var hasCacheItem = false;
+                if(!cacheSection[rowIdx] && info.cellRange.col === 0 ){
+                    if(me.rationsCodes.indexOf(items[i].code) === -1){
+                        addArr.push(items[i]);
+                        me.rationsCodes.push(items[i].code);
+                    }
+                    else{
+                        failPasteArr.push(items[i].code);
+                        me.workBook.getSheet(0).setValue(rowIdx, 0, '');
                     }
                 }
-                if (!hasCacheItem && info.cellRange.col === 0) {
-                    addArr.push(items[i]);
-                } else if(hasCacheItem){
-                    updateArr.push(items[i]);
+                else if(cacheSection[rowIdx]){
+                    for(let col = 0; col < me.setting.header.length; col++){
+                        if(!items[i][me.setting.header[col].dataCode] && typeof cacheSection[rowIdx][me.setting.header[col].dataCode] !== 'undefined'){
+                            items[i][me.setting.header[col].dataCode] = cacheSection[rowIdx][me.setting.header[col].dataCode];
+                        }
+                    }
+                    if(info.cellRange.col === 0){
+                        if(me.rationsCodes.indexOf(items[i].code) === -1){
+                            items[i].ID = cacheSection[rowIdx].ID;
+                            updateArr.push(items[i]);
+                        }
+                        else{
+                            me.workBook.getSheet(0).setValue(rowIdx, 0, cacheSection[rowIdx].code);
+                        }
+                    }
+                    else{
+                        items[i].ID = cacheSection[rowIdx].ID;
+                        updateArr.push(items[i]);
+                    }
                 }
+
             } else {
                 //add
                 if(info.cellRange.col === 0){
-                    addArr.push(items[i])
+                    //是否含有已存在的编号
+                        if(me.rationsCodes.indexOf(items[i].code) === -1){
+                            addArr.push(items[i]);
+                        }
+                        else{
+                            failPasteArr.push(items[i]);
+                        }
                 }
             }
         };
-        console.log(`updateArr`);
-        console.log(updateArr);
-        console.log(addArr);
-        if (updateArr.length > 0 || addArr.length > 0) {
-            //me.mixUpdateRequest(updateArr, addArr, []);
+       /* if(failPasteArr.length > 0 && !(updateArr.length > 0 || addArr.length > 0)){
+            me.showRationItems(me.currentSectionId);
+        }*/
+         if (updateArr.length > 0 || addArr.length > 0) {
+            me.mixUpdateRequest(updateArr, addArr, []);
         }
     },
     getRationsCodes: function (repId) {
@@ -405,8 +425,8 @@ var rationOprObj = {
             cache:false,
             timeout:5000,
             success:function(result){
-                if (result.err) {
-                    alert(err);
+                if (result.error) {
+                    alert(`error`);
                     me.getRationItems(me.currentSectionId);
                 } else {
                     var cacheSection = me.updateCache(addArr, updateArr, removeIds, result);
@@ -417,6 +437,9 @@ var rationOprObj = {
                         return rst;
                     });
                     me.showRationItems(me.currentSectionId);
+                   /* me.workBook.getSheet(0).setActiveCell(me.activeCell.row, me.activeCell.col);
+                    let spreadBook = new GC.Spread.Sheets.Workbook(rationOprObj.sheet, { sheetCount: 1 });
+                    spreadBook.focus(true);*/
                 }
             },
             error:function(){

+ 110 - 4
web/maintain/ration_repository/js/ration_glj.js

@@ -5,6 +5,7 @@ var rationGLJOprObj = {
     sheet: null,
     currentRationItem: null,
     distTypeTree: null,
+    activeCell: null,
     cache: {},
     setting: {
         header:[
@@ -17,7 +18,7 @@ var rationGLJOprObj = {
         ],
         view:{
             comboBox:[],
-            lockColumns:[1,2,3,5,6]
+            lockColumns:[1,2,3,5]
         }
     },
     getDistTypeTree: function (gljDistType) {
@@ -81,12 +82,81 @@ var rationGLJOprObj = {
         me.getGljDistType(function () {
             me.onContextmenuOpr();
             sheetCommonObj.initSheet(me.sheet, me.setting, 30);
+            me.rationGljDelOpr();
             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.sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
         });
     },
+    rationGljDelOpr: function () {
+        let me = rationGLJOprObj, spreadBook = me.sheet.getParent();
+        spreadBook.commandManager().register('rationGljDelete', function () {
+            console.log(me.cache["_GLJ_" + me.currentRationItem.ID]);
+            let sels = me.sheet.getSelections(), updateArr = [], removeArr = [], lockCols = me.setting.view.lockColumns;
+            let cacheSection = me.cache["_GLJ_" + me.currentRationItem.ID], isUpdate = false;
+            console.log(`sels`);
+            console.log(sels);
+            if(sels.length > 0){
+                for(let sel = 0; sel < sels.length; sel++){
+                    if(sels[sel].colCount === me.setting.header.length){
+                        if(cacheSection){
+                            for(let i = 0; i < sels[sel].rowCount; i++){
+                                if(sels[sel].row + i < cacheSection.length){
+                                    //removeArr.push(cacheSection[sels[sel].row + i].ID);
+                                    isUpdate = true;
+                                    cacheSection.splice(sels[sel].row + i, 1);
+                                    me.updateRationItem();
+                                    //me.rationsCodes.splice(me.rationsCodes.indexOf(cacheSection[sels[sel].row + i].code), 1);
+                                }
+                            }
+                        }
+                    }
+                    else{
+                        if(sels[sel].col === 0){
+                            $('#alertText').text("编号不能为空,修改失败!");
+                            $('#alertModalBtn').click();
+                            me.sheet.options.isProtected = true;
+                            $('#alertModalCls').click(function () {
+                                me.sheet.options.isProtected = false;
+                            });
+                            $('#alertModalCof').click(function () {
+                                me.sheet.options.isProtected = false;
+                            });
+                        }
+                        else if(sels[sel].col !== 0 && sels[sel].col !== 5 && !(sels[sel].col === 1 && sels.col + sels[sel].colCount -1 === 3)){
+                            console.log(`enter`);
+                            if(cacheSection){
+                                for(let i = sels[sel].row === -1 ? 1 : 0; i < sels[sel].rowCount; i++){
+                                    if(sels[sel].row + i < cacheSection.length){
+                                        for(let col = sels[sel].col; col <= sels[sel].col + sels[sel].colCount - 1; col++){
+                                            if(lockCols.indexOf(col) === -1){
+                                                isUpdate = true;
+                                                cacheSection[sels[sel].row + i][me.setting.header[col].dataCode] = 0;
+                                                me.sheet.setValue(sels[sel].row + i, col, 0.00);
+                                            }
+                                        }
+                                    }
+                                    //updateArr.push(cacheSection[sels[sel].row + i]);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if(isUpdate){
+                me.updateRationItem();
+                sheetCommonObj.cleanSheet(me.sheet, me.setting, -1);
+                me.showGljItems(me.currentRationItem.ID);
+            }
+           /* if(updateArr.length > 0 || removeArr.length > 0){
+                me.mixUpdateRequest(updateArr, [], removeArr);
+            }*/
+
+        });
+        spreadBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
+        spreadBook.commandManager().setShortcutKey('rationGljDelete', GC.Spread.Commands.Key.del, false, false, false, false);
+    },
     onRangeChanged: function(sender, args) {
         if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
             var me = rationGLJOprObj, updateArr = [], removeArr = [];
@@ -108,9 +178,9 @@ var rationGLJOprObj = {
     },
     onClipboardPasting: function(sender, args) {
         var me = rationGLJOprObj;
-        if (args.cellRange.colCount != 1 || args.cellRange.col != 0 || !(me.currentRationItem)) {
+        /*if (args.cellRange.colCount != 1 || args.cellRange.col != 0 || !(me.currentRationItem)) {
             args.cancel = true;
-        }
+        }*/
     },
     onClipboardPasted: function(e, info) {
         var me = rationGLJOprObj, repId = storageUtil.getSessionCache("RationGrp","repositoryID");
@@ -124,6 +194,29 @@ var rationGLJOprObj = {
                 me.addGljItems(codes, repId);
             } else {
                 //修改用量
+                if(me.cache["_GLJ_" + me.currentRationItem.ID] && info.cellRange.row < me.cache["_GLJ_" + me.currentRationItem.ID].length){
+                    let tempConsumes = sheetCommonObj.analyzePasteData(me.setting, info);
+                    let maxCount = info.cellRange.row + info.cellRange.rowCount -1 > me.cache["_GLJ_" + me.currentRationItem.ID].length -1 ?
+                        me.cache["_GLJ_" + me.currentRationItem.ID].length - info.cellRange.row : info.cellRange.rowCount;
+                    for(let i = 0; i < maxCount; i++){
+                        me.cache["_GLJ_" + me.currentRationItem.ID][info.cellRange.row + i].consumeAmt = tempConsumes[i].consumeAmt;
+                    }
+                    me.updateRationItem();
+                    if(info.cellRange.row + info.cellRange.rowCount -1 >= me.cache["_GLJ_" + me.currentRationItem.ID].length -1){
+                        me.sheet.suspendPaint();
+                        for(let rowIdx = me.cache["_GLJ_" + me.currentRationItem.ID].length; rowIdx <= info.cellRange.row + info.cellRange.rowCount -1; rowIdx++){
+                            me.sheet.setValue(rowIdx, info.cellRange.col, '');
+                        }
+                        me.sheet.resumePaint();
+                    }
+                }
+                else if(info.cellRange.row >= me.cache["_GLJ_" + me.currentRationItem.ID].length){
+                    me.sheet.suspendPaint();
+                    for(let rowIdx = info.cellRange.row; rowIdx <= info.cellRange.row + info.cellRange.rowCount -1; rowIdx ++){
+                        me.sheet.setValue(rowIdx, info.cellRange.col, '');
+                    }
+                    me.sheet.resumePaint();
+                }
             }
         }
     },
@@ -366,6 +459,19 @@ var rationGLJOprObj = {
                                 }
                             }
                         }
+                        function compare(){
+                            return function (a, b) {
+                                let rst = 0;
+                                if (a.code > b.code) {
+                                    rst = 1;
+                                }
+                                else if (a.code < b.code) {
+                                    rst = -1;
+                                }
+                                return rst;
+                            }
+                        }
+                        cacheArr.sort(compare());
                         me.cache["_GLJ_" + rationID] = cacheArr;
                         me.showGljItems(rationID);
                     }

+ 235 - 28
web/maintain/ration_repository/js/repository_glj.js

@@ -274,9 +274,11 @@ var pageOprObj = {
     },
     onCellEditEnd: function(sender, args) {
         var me = repositoryGljObj, rObj = sheetCommonObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row, me),
-            updateArr = [], addArr = [];
+            updateArr = [], addArr = [], updateBasePrcArr = [];
         me.editingRowIdx = args.row;
         rObj.basePrice = rObj.basePrice ? rObj.basePrice : 0;
+        console.log(`rObj`);
+        console.log(rObj);
         if (me.currentEditingGlj["ID"]) {
             rObj["ID"] = me.currentEditingGlj["ID"];
             rObj.gljClass = me.currentEditingGlj.gljClass;
@@ -301,13 +303,15 @@ var pageOprObj = {
                 }
                 let gljBasePrcObj = {gljId: me.currentEditingGlj.ID, gljType: gljType, basePrice: rObj.basePrice};
                 if(gljBasePrcObj.gljType !== -1){
-                    me.updateRationBasePrcRq(gljBasePrcObj);
+                    updateBasePrcArr.push(gljBasePrcObj);
+                    me.updateRationBasePrcRq(updateBasePrcArr);
                 }
             }
             //update basePrice of ration when editting gljType of glj
             if(me.currentEditingGlj.gljType !== rObj.gljType){
                let gljTypeObj = {gljId: me.currentEditingGlj.ID, gljType: rObj.gljType, basePrice: rObj.basePrice};
-                me.updateRationBasePrcRq(gljTypeObj);
+                updateBasePrcArr.push(gljTypeObj);
+                me.updateRationBasePrcRq(updateBasePrcArr);
             }
         } else {
             me.addGljObj = rObj;
@@ -325,6 +329,8 @@ var pageOprObj = {
         }
         if(updateArr.length >0 || addArr.length >0){
             me.currentEditingGlj = null;
+            //me.workBook.getSheet(0).setValue(11, 5, "人工");
+            console.log(addArr);
             me.mixUpdateRequest(updateArr, addArr, []);
         }
     },
@@ -447,41 +453,220 @@ var pageOprObj = {
              }
          }
      },
-    onClipboardPasting: function(sender, args) {
-        var me = repositoryGljObj;
-        if (args.cellRange.colCount != me.setting.header.length || me.gljCurTypeId < 0 || me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]) {
-            args.cancel = true;
-        }
-    },
+     validUpdateObj: function (pasteObj, rowIdx) {
+         let rst = {}, backUpObj = {},
+             me = repositoryGljObj,
+             tempObj = me.currentCache[rowIdx],
+             reCalBasePrc = false, isValid = true;
+         //备份原始数据
+         for(let atr in tempObj){
+             backUpObj[atr] = tempObj[atr];
+         }
+         if(typeof pasteObj.code !== 'undefined'){
+             if(pasteObj.code.trim().length !== 0){
+                 let isExist = false;
+                 for(let i = 0; i < me.gljList.length; i++){
+                     if(me.gljList[i].code === pasteObj.code){
+                         isExist = true;
+                         break;
+                     }
+                 }
+                 if(!isExist){
+                     tempObj.code = pasteObj.code;
+                 }
+                 else isValid = false;
+             }
+             else isValid = false;
+         }
+         if(typeof pasteObj.name !== 'undefined'){
+             if(pasteObj.name.trim().length === 0) isValid = false;
+             else tempObj.name = pasteObj.name;
+         }
+         if(typeof pasteObj.specs !== 'undefined'){
+             tempObj.specs = pasteObj.specs;
+         }
+         if(typeof pasteObj.unit !== 'undefined'){
+             tempObj.unit = pasteObj.unit;
+         }
+         if(typeof pasteObj.gljType !== 'undefined'){
+             let isExsit = false;
+             for(let i = 0; i < me.distTypeTree.comboDatas.length; i++){
+                 if(pasteObj.gljType === me.distTypeTree.comboDatas[i].text){
+                     isExsit = true;
+                     reCalBasePrc = true;
+                     tempObj.gljType = me.distTypeTree.comboDatas[i].value;
+                     tempObj.shortName = me.distTypeTree.distTypes[me.distTypeTree.prefix + tempObj.gljType].data.shortName;
+
+                 }
+             }
+             if(!isExsit) isValid = false;
+         }
+         //
+         pasteObj.basePrice = !isNaN(parseFloat(pasteObj.basePrice)) && (pasteObj.basePrice && typeof pasteObj.basePrice !== 'undefined') ? parseFloat(pasteObj.basePrice) :
+                                me.currentCache[rowIdx].basePrice;
+         if(pasteObj.basePrice !== me.currentCache[rowIdx].basePrice){
+             reCalBasePrc = true;
+             tempObj.basePrice = pasteObj.basePrice;
+         }
+         if(isValid){
+             rst.updateGlj = tempObj;
+             if(reCalBasePrc){
+                 //重新计算定额基价对象
+                 rst.updateBasePrc = {gljId: tempObj.ID, gljType: tempObj.gljType, basePrice: tempObj.basePrice};
+             }
+         }
+         else {
+             for(let attr in backUpObj){
+                 tempObj[attr] = backUpObj[attr];
+             }
+         }
+         return rst;
+     },
+     //粘贴的数据是否是可添加的数据,只有含有编号,名称,类型才可添加
+     isValidObj: function(pasteObj) {
+        let me = repositoryGljObj;
+         if(!(pasteObj.code && typeof pasteObj.code !== 'undefined') || !(pasteObj.name && typeof pasteObj.name !== 'undefined') ||
+         !(pasteObj.gljType && typeof pasteObj.gljType !== 'undefined')){
+             return false;
+         }
+         if(pasteObj.gljType && typeof pasteObj.gljType !== 'undefined'){
+             let isExist = false;
+             for(let i = 0; i < me.distTypeTree.comboDatas.length; i++){
+                 if(me.distTypeTree.comboDatas[i].text === pasteObj.gljType){
+                     isExist = true;
+                     pasteObj.gljType = me.distTypeTree.comboDatas[i].value;
+                     pasteObj.shortName = me.distTypeTree.distTypes[me.distTypeTree.prefix + pasteObj.gljType].data.shortName;
+                     break;
+                 }
+             }
+             if(!isExist){
+                 return false;
+             }
+         }
+         if(pasteObj.code && typeof pasteObj.code !== 'undefined'){
+            for(let i = 0; i < me.gljList.length; i++){
+                if(me.gljList[i].code === pasteObj.code){
+                    return false;
+                }
+            }
+         }
+         pasteObj.basePrice = !isNaN(parseFloat(pasteObj.basePrice)) && (pasteObj.basePrice && typeof pasteObj.basePrice !== 'undefined') ? parseFloat(pasteObj.basePrice) : 0;
+         pasteObj.gljClass = me.gljCurTypeId;
+         return true;
+     },
+     onClipboardPasting: function(sender, args) {
+         var me = repositoryGljObj;
+         /*if (args.cellRange.colCount != me.setting.header.length || me.gljCurTypeId < 0 || me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]) {
+          args.cancel = true;
+          }*/
+         if (me.gljCurTypeId < 0 ) {
+             args.cancel = true;
+         }
+     },
     onClipboardPasted: function(e, info) {
         var me = repositoryGljObj;
         var updateArr = [], addArr = [];
         var items = sheetCommonObj.analyzePasteData(me.setting, info);
-        var hasCacheItem = false;
-        for (var i = 0; i < items.length; i++) {
-            for (var j = 0; j < me.gljList.length; j++) {
-                if (me.gljList[j][me.setting.header[0].dataCode] == items[i][me.setting.header[0].dataCode]) {
-                    hasCacheItem = true;
-                    items[i]["ID"] = me.gljList[j]["ID"];
-                    break;
+        let beginRow = info.cellRange.row, endRow = info.cellRange.row + info.cellRange.rowCount - 1,
+            maxRow = me.currentCache.length - 1, updateItems = [], addItems = [], updateBasePrcArr = [] , updateCount, resumeArr = [];
+        if(endRow <= maxRow){
+            //updateItems = items;
+            for(let i = 0; i < items.length; i++){
+                let updateObj = me.validUpdateObj(items[i], info.cellRange.row + i);
+                if(updateObj && typeof updateObj.updateGlj !== 'undefined'){
+                    updateArr.push(updateObj.updateGlj);
+                    if(typeof updateObj.updateBasePrc !== 'undefined'){
+                        updateBasePrcArr.push(updateObj.updateBasePrc);
+                    }
+                }
+                else{
+                    resumeArr.push(info.cellRange.row + i);
+                }
+            }
+        }
+        else if(beginRow <= maxRow && endRow > maxRow){
+            updateCount = maxRow - beginRow + 1;
+            for(let i = 0; i < updateCount; i++){
+                let updateObj = me.validUpdateObj(items[i], info.cellRange.row + i);
+                if(updateObj && typeof updateObj.updateGlj !== 'undefined'){
+                    updateArr.push(updateObj.updateGlj);
+                    if(typeof updateObj.updateBasePrc !== 'undefined'){
+                        updateBasePrcArr.push(updateObj.updateBasePrc);
+                    }
+                }
+                else{
+                    resumeArr.push(info.cellRange.row + i);
+                }
+            }
+            if(info.cellRange.colCount === me.setting.header.length){
+                for(let i = updateCount ; i < items.length; i++){
+                    if(me.isValidObj(items[i])){
+                        addItems.push(items[i]);
+                        addArr.push(items[i]);
+                    }
+                    else{
+                        resumeArr.push(info.cellRange.row + i);
+                    }
+                }
+            }
+            else{
+                for(let i = updateCount ; i < items.length; i++){
+                    resumeArr.push(info.cellRange.row + i);
+                }
+            }
+        }
+        else{
+            if(info.cellRange.colCount === me.setting.header.length){
+                for(let i = 0; i < items.length; i++){
+                    if(me.isValidObj(items[i])){
+                        addArr.push(items[i]);
+                    }
+                    else{
+                        resumeArr.push(info.cellRange.row + i);
+                    }
                 }
             }
-            if (!hasCacheItem) {
-                items[i].gljType = me.gljCurTypeId;
-                addArr.push(items[i]);
-            } else {
-                updateArr.push(items[i]);
+            else{
+                for(let i = 0; i < items.length; i++){
+                    resumeArr.push(info.cellRange.row + i);
+                }
+            }
+        }
+        //repaint
+        if(resumeArr.length > 0){
+            info.sheet.suspendPaint();
+            for(let i = 0; i < resumeArr.length ; i++){
+                if(resumeArr[i] < me.currentCache.length){
+                    for(let col = 0; col < me.setting.header.length; col++){
+                        if(me.setting.header[col].dataCode === 'gljType'){
+                            let gljType = me.currentCache[resumeArr[i]][me.setting.header[col].dataCode];
+                            info.sheet.setValue(resumeArr[i], col, me.distTypeTree.distTypes["gljType" + gljType].data.fullName);
+                        }
+                        else{
+                            info.sheet.setValue(resumeArr[i], col, me.currentCache[resumeArr[i]][me.setting.header[col].dataCode]);
+                        }
+                    }
+                }
+                else{
+                    for(let col = 0; col < me.setting.header.length; col++){
+                        info.sheet.setValue(resumeArr[i], col, '');
+                    }
+                }
             }
+            info.sheet.resumePaint();
         }
         if (updateArr.length > 0 || addArr.length > 0) {
-            me.mixUpdateRequest(updateArr, addArr, []);
+           me.mixUpdateRequest(updateArr, addArr, []);
+        }
+        if(updateBasePrcArr.length > 0){
+           me.updateRationBasePrcRq(updateBasePrcArr);
         }
     },
-    updateRationBasePrcRq: function (gljObj) {
+    updateRationBasePrcRq: function (basePrcArr) {
         $.ajax({
             type: 'post',
             url: 'api/updateRationBasePrc',
-            data:{data: JSON.stringify({repId: pageOprObj.rationLibId, lastOpr: userAccount, gljId: gljObj.gljId, basePrice: gljObj.basePrice, gljType: gljObj.gljType})},
+            data:{data: JSON.stringify({repId: pageOprObj.rationLibId, lastOpr: userAccount, basePrcArr: basePrcArr})},
             dataType: 'json',
             success: function (result) {
                 if(result.error){
@@ -518,10 +703,14 @@ var pageOprObj = {
                     alert(result.message);
                     me.getRationItems(me.currentRepositoryId);
                 } else {
-                    console.log(`enterSc`);
                     me.updateCache(addArr, updateArr, removeIds, result);
                     me.sortGlj();
-                    me.currentCache = me.getCache();
+                    if(me.currentOprParent === 1){
+                        me.currentCache = me.getParentCache(me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]);
+                    }
+                    else{
+                        me.currentCache = me.getCache();
+                    }
                     me.showGljItems(me.gljList, me.gljCurTypeId);
                 }
             },
@@ -530,6 +719,21 @@ var pageOprObj = {
             }
         })
     },
+     getParentCache: function (nodes) {
+        let me = repositoryGljObj, rst = [];
+        for(let i = 0; i < me.gljList.length; i++){
+            if(nodes.indexOf(me.gljList[i].gljClass) !== -1){
+                rst.push(me.gljList[i]);
+            }
+        }
+         rst.sort(function (a, b) {
+             let rst = 0;
+             if(a.code > b.code) rst = 1;
+             else if(a.code < b.code)rst = -1;
+             return rst;
+         });
+         return rst;
+     },
     getCache: function() {
         var me = this, rst = [];
         for (var i = 0; i < me.gljList.length; i++) {
@@ -591,13 +795,16 @@ var gljTypeTreeOprObj = {
         var me = repositoryGljObj,
             gljTypeId = treeNode.ID;
         me.gljCurTypeId = treeNode.ID;
-        me.currentCache = me.getCache();
+        //me.currentCache = me.getCache();
         me.showGljItems(me.gljList, gljTypeId);
-        console.log(me.gljCurTypeId);
         if (me.parentNodeIds["_pNodeId_" + treeNode.ID]) {
+            me.currentOprParent = 1;
+            me.currentCache = me.getParentCache(me.parentNodeIds["_pNodeId_" + treeNode.ID]);
             sheetCommonObj.lockCodeCells(me.workBook.getSheet(0), me.gljList.length);
             //sheetCommonObj.shieldAllCells(me.workBook.getSheet(0), me.setting);
         } else {
+            me.currentOprParent = 0;
+            me.currentCache = me.getCache();
             sheetCommonObj.unShieldAllCells(me.workBook.getSheet(0));
         }
     },

+ 177 - 49
web/users/js/version.js

@@ -8,36 +8,97 @@
 $(document).ready(function() {
     let isAdding = false;
     let model = '';
+    let section = 'bill';
+    let id = $("#version-id").val();
 
-    // 初始化数据
-    initVersion();
+    // 计价规则页面初始化数据
+    if ($("#section").length > 0) {
+        initVersion();
+    }
+
+    // 计价类型选择
+    $(".nav-tabs li > a").click(function() {
+        section = $(this).attr("aria-controls");
+    });
 
     // 新增版本
     $("#add-version").click(function() {
         try {
             let [name, standardBill, rationLib, standardBillString, rationLibString] = getAndValidData(model);
-            let id = $("#version-id").val();
 
-            let postData = {};
             let url = '/version/add';
-            switch (model) {
-                case 'all':
-                    postData = {model: model, name: name, standard_bill_id: standardBill, ration_lib_id: rationLib,
-                        standard_bill: standardBillString, ration_lib: rationLibString};
-                    break;
-                case 'bill':
-                    url = '/version/addLib';
-                    postData = {model: model, standard_bill_id: standardBill, standard_bill: standardBillString, id: id};
-                    break;
-                case 'ration':
-                    url = '/version/addLib';
-                    postData = {model: model, ration_lib_id: rationLib, ration_lib: rationLibString, id: id};
-                    break;
+            if (model === 'all') {
+                // 新增版本操作
+                $.ajax({
+                    url: url,
+                    type: 'post',
+                    data: {name: name},
+                    error: function() {
+                        isAdding = false;
+                    },
+                    beforeSend: function() {
+                        isAdding = true;
+                    },
+                    success: function(response) {
+                        isAdding = false;
+                        if (response.err === 0) {
+                            window.location.reload();
+                        } else {
+                            let msg = response.msg === undefined ? '未知错误' : response.msg;
+                            alert(msg);
+                        }
+                    }
+                });
+            } else {
+                // 新增标准清单/定额库
+                let addLib = {
+                    name: '',
+                    id: ''
+                };
+                switch (model) {
+                    case 'bill':
+                        addLib.name = standardBillString;
+                        addLib.id = standardBill;
+                        break;
+                    case 'ration':
+                        addLib.name = rationLibString;
+                        addLib.id = rationLib;
+                        break;
+                }
+                // 判断是否有重复的数据
+                if ($("input:hidden[name='"+ model +"_lib'][data-id='"+ addLib.id +"']").length > 0) {
+                    alert('重复添加数据!');
+                    return false;
+                }
+
+                let removeHtml = '<a class="pull-right text-danger remove-lib" data-model="bill" ' +
+                    'title="移除"><span class="glyphicon glyphicon-remove"></span></a>';
+                let tmpHtml = '<p class="form-control-static">' + removeHtml + addLib.name +
+                    '<input type="hidden" data-id="'+ addLib.id +'" name=\'' + model + '_lib\' value=\'' + JSON.stringify(addLib) + '\'>' + '</p>';
+                $("." + model + "-list").append(tmpHtml);
+                $('#addversion').modal('hide');
+            }
+
+        } catch (error) {
+            alert(error);
+        }
+    });
+
+    // 新增计价规则
+    $("#add-valuation").click(function() {
+        try {
+            if (id === '') {
+                throw '页面数据有误';
+            }
+            let name = $("input[name='valuation_name']").val();
+            if (name === '') {
+                throw '请填写计价规则名称';
             }
+
             $.ajax({
-                url: url,
+                url: '/version/add-valuation',
                 type: 'post',
-                data: postData,
+                data: {name: name, id: id, section: section},
                 error: function() {
                     isAdding = false;
                 },
@@ -54,9 +115,9 @@ $(document).ready(function() {
                     }
                 }
             });
-
         } catch (error) {
             alert(error);
+            return false;
         }
     });
 
@@ -93,8 +154,8 @@ $(document).ready(function() {
         switch (model) {
             case 'all':
                 $("#name-area").show();
-                $("#bill-area").show();
-                $("#ration-area").show();
+                $("#bill-area").hide();
+                $("#ration-area").hide();
                 $("#add-version-title").text('添加新版本');
                 break;
             case 'bill':
@@ -114,44 +175,48 @@ $(document).ready(function() {
         $("#addversion").modal('show');
     });
 
-    // 移除操作
-    let isDeleting = false;
-    $(".remove-version").click(function() {
-        let model = $(this).data('model');
-        let id = $("#version-id").val();
-        let deleteId = $(this).data('id');
-        deleteId = parseInt(deleteId);
-
-        if (model === undefined || model === '' || isNaN(deleteId)) {
-            return false;
+    // 保存计价规则
+    $("#save-valuation").click(function() {
+        if (validValuation()) {
+            $("form").submit();
         }
-        if (isDeleting) {
+    });
+
+    // 移除操作
+    $(".bill-list, .ration-list").on("click", ".remove-lib", function() {
+        $(this).parent().remove();
+    });
+
+    // 计价规则启用/禁止
+    $(".enable").click(function() {
+        let goingChangeStatus = switchChange($(this));
+        let id = $(this).data('id');
+        if (id === undefined || id === '' || isAdding) {
             return false;
         }
-
         $.ajax({
-            url: '/version/deleteLib',
+            url: '/version/valuation/' + section + '/enable',
             type: 'post',
-            data: {id: id, model: model, delete_id: deleteId},
+            dataType: "json",
+            data: {id: id, enable: goingChangeStatus},
             error: function() {
-                isDeleting = false;
+                isAdding = false;
+                switchChange($(this));
             },
             beforeSend: function() {
-                isDeleting = true;
+                isAdding = true;
             },
             success: function(response) {
-                isDeleting = false;
-                if (response.err === 0) {
-                    window.location.reload();
-                } else {
-                    let msg = response.msg === undefined ? '未知错误' : response.msg;
-                    alert(msg);
+                isAdding = false;
+                if (response.err !== 0) {
+                    switchChange($(this));
+                    alert('更改失败');
                 }
             }
         });
-
     });
 
+
 });
 
 /**
@@ -191,18 +256,18 @@ function initVersion() {
  */
 function getAndValidData(model) {
     let name = $("input[name='version_name']").val();
-    let standardBill = $("select[name='standard_bill']").val();
-    let rationLib = $("select[name='ration_lib']").val();
+    let standardBill = $("select[name='standard_bill']").children("option:selected").val();
+    let rationLib = $("select[name='ration_lib']").children("option:selected").val();
 
     if (name === '' && model === 'all') {
         throw '版本名字不能为空';
     }
 
-    if ((model === 'all' || model === 'bill') && (standardBill === '' || standardBill === undefined)) {
+    if ( model === 'bill' && (standardBill === '' || standardBill === undefined)) {
         throw '请选择标准清单库';
     }
 
-    if ((model === 'all' || model === 'ration') && (rationLib === '' || rationLib === undefined)) {
+    if (model === 'ration' && (rationLib === '' || rationLib === undefined)) {
         throw '请选择定额库';
     }
 
@@ -211,3 +276,66 @@ function getAndValidData(model) {
 
     return [name, standardBill, rationLib, standardBillString, rationLibString];
 }
+
+/**
+ * 验证计价规则数据
+ *
+ * @return {boolean}
+ */
+function validValuation() {
+    let result = false;
+    try {
+        let valuationName = $("input[name='name']").val();
+        if (valuationName === '') {
+            throw '请填写计价规则名称';
+        }
+
+        let engineering = $("select[name='engineering']").val();
+        if (engineering === '' || engineering <= 0) {
+            throw '请选择工程专业';
+        }
+
+        if ($("input:hidden[name='bill_lib']").length <= 0) {
+            throw '请添加标准清单';
+        }
+
+        if ($("input:hidden[name='ration_lib']").length <= 0) {
+            throw '请添加定额库';
+        }
+
+        result = true;
+    } catch (error) {
+        alert(error);
+        result = false;
+    }
+
+    return result;
+}
+
+/**
+ * 切换switch效果
+ *
+ * @param {Object} element
+ * @return {boolean}
+ */
+function switchChange(element) {
+    // 第一个元素判断当前的状态
+    let firstButton = element.children("button").first();
+    let secondButton = element.children("button").eq(1);
+    let currentStatus = firstButton.is(":disabled");
+    if (currentStatus) {
+        // 当前为true切换到false
+        firstButton.removeClass('btn-success').removeClass('disabled').addClass('btn-default').removeAttr("disabled");
+        firstButton.text('开启');
+        secondButton.removeClass("btn-default").addClass("btn-danger").addClass("disabled").attr("disabled", "disabled");
+        secondButton.text('已禁用');
+    } else {
+        // 当前false切换到true
+        firstButton.removeClass("btn-default").addClass("btn-success").addClass("disabled").attr("disabled", "disabled");
+        firstButton.text('已开启');
+        secondButton.removeClass('btn-danger').removeClass('disabled').addClass('btn-default').removeAttr("disabled");
+        secondButton.text('禁用');
+    }
+
+    return !currentStatus;
+}

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

@@ -98,57 +98,5 @@
         </div>
     </div>
 </div>
-
-<!-- 弹窗新增版本 -->
-<div class="modal fade" id="addversion" tabindex="-1" role="dialog">
-    <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="add-version-title">添加新版本</h4>
-            </div>
-            <div class="modal-body">
-                <div class="form-group" id="name-area">
-                    <label>版本名称</label>
-                    <input class="form-control" placeholder="" name="version_name">
-                </div>
-                <div class="form-group" id="bill-area">
-                    <label>标准清单</label>
-                    <div class="row">
-                        <div class="col-xs-4">
-                            <select class="form-control" name="standard_bill_province">
-                                <option value="">请选择省份</option>
-                            </select>
-                        </div>
-                        <div class="col-xs-8">
-                            <select class="form-control" name="standard_bill">
-                                <option value="">请选择标准清单</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group" id="ration-area">
-                    <label>定额库</label>
-                    <div class="row">
-                        <div class="col-xs-4">
-                            <select class="form-control" name="ration_lib_province">
-                                <option value="">请选择省份</option>
-                            </select>
-                        </div>
-                        <div class="col-xs-8">
-                            <select class="form-control" name="ration_lib">
-                                <option value="">请选择定额库</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary" id="add-version">确定添加</button>
-            </div>
-        </div>
-    </div>
-</div>
-
+<%include ../version/modal.html %>
 </body>

+ 99 - 0
web/users/views/version/add.html

@@ -0,0 +1,99 @@
+<%include ./common.html %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>重庆版<span class="text-muted pull-right">已发布 2017-08-04</span><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-header" style="padding:0">
+            <ul class="nav nav-tabs">
+                <% valuationList.forEach(function(valuation) { %>
+                <li role="presentation" <% if (valuation._id.toString() === valuationId) { %>class="active"<% } %>><a href="/version/valuation/<%= section %>/<%= valuation._id %>"><%= valuation.name %></a></li>
+                <% }) %>
+            </ul>
+        </div>
+        <div class="c-body">
+            <form method="post" action="/version/save-valuation" enctype="application/x-www-form-urlencoded21">
+                <div class=" row">
+                    <div class="col-md-4">
+                        <div class="form-group">
+                            <label>名称</label>
+                            <div class="input-group">
+                                <input type="text" class="form-control" value="<%= valuationData.name %>" name="name">
+                                <span class="input-group-btn">
+                                     <button class="btn btn-default" type="button" id="save-valuation">保存</button>
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-md-12">
+                        <legend>
+                            <div class="form-group row">
+                                <label class="col-sm-2 col-form-label">工程专业</label>
+                                <div class="col-sm-3">
+                                    <select class="form-control" name="engineering">
+                                        <option value="">请选择工程</option>
+                                        <% engineeringList.forEach(function(engineering) {%>
+                                        <option value="<%= engineering.value %>" <% if (engineering.value === valuationData.engineering) {%>selected="selected"<% } %>><%= engineering.name %></option>
+                                        <% }) %>
+                                    </select>
+                                </div>
+                            </div>
+                        </legend>
+                    </div>
+                    <div class="col-md-4">
+                        <div class="form-group">
+                            <label>标准清单</label>
+                            <div class="bill-list">
+                                <% if (valuationData.bill_lib.length > 0) { %>
+                                <% valuationData.bill_lib.forEach(function (bill){ %>
+                                <p class="form-control-static">
+                                    <a class="pull-right text-danger remove-lib" data-model="bill" title="移除">
+                                        <span class="glyphicon glyphicon-remove"></span>
+                                    </a>
+                                    <input type="hidden" name="bill_lib" data-id="<%= bill.id %>" value="<%= JSON.stringify({id: bill.id, name: bill.name}) %>">
+                                    <%= bill.name %>
+                                </p>
+                                <% }) %>
+                                <% } %>
+                            </div>
+                            <a class="btn btn-link btn-sm add-version" href="javascript:void(0)" data-model="bill">添加</a>
+                        </div>
+                        <div class="form-group">
+                            <label>定额库</label>
+                            <div class="ration-list">
+                                <% if (valuationData.ration_lib.length > 0) { %>
+                                <% valuationData.ration_lib.forEach(function (ration){ %>
+                                <p class="form-control-static">
+                                    <a class="pull-right text-danger remove-lib" data-model="ration" title="移除" data-id="<%= ration.id %>">
+                                        <span class="glyphicon glyphicon-remove"></span>
+                                    </a>
+                                    <input type="hidden" name="ration_lib" data-id="<%= ration.id %>" value="<%= JSON.stringify({id: ration.id, name: ration.name}) %>">
+                                    <%= ration.name %>
+                                </p>
+                                <% }) %>
+                                <% } %>
+                            </div>
+                            <a href="#" class="btn btn-link btn-sm add-version" data-model="ration">添加</a>
+                        </div>
+                    </div>
+                    <div class="col-md-8">
+                        <legend>造价书列设置<a href="javascript:void(0)" data-toggle="modal" data-target="#set-column" class="btn btn-primary btn-sm pull-right">设置</a></legend>
+                        <div>
+                            S JS预览在此
+                        </div>
+                    </div>
+                </div>
+                <input type="hidden" name="section" value="<%= section %>" id="section">
+                <input type="hidden" name="id" value="<%= valuationId %>">
+            </form>
+        </div>
+    </div>
+</div>
+<script type="text/javascript">
+    let province = '<%- province %>';
+    let billList = '<%- billList %>';
+    let rationList = '<%- rationList %>';
+</script>
+<script type="text/javascript" src="/web/users/js/version.js"></script>

+ 16 - 0
web/users/views/version/common.html

@@ -0,0 +1,16 @@
+<div class="panel-sidebar">
+    <div class="panel-title">
+        <div class="title-bar">
+            <h2><a class="pull-right add-version" title="添加新版本" href="javascript:void(0)" data-model="all"><span class="glyphicon glyphicon-plus"></span></a>版本管理</h2>
+        </div>
+    </div>
+    <div class="scrollbar-auto">
+        <div class="nav-box">
+            <ul class="nav-list list-unstyled" id="version-select">
+                <% versionList.forEach(function (version){ %>
+                <li <% if(selectedVersion._id.toString() === version._id.toString()) { %>class="active"<% } %>><a href="/version?id=<%= version._id %>"><span><%= version.name %></span><% if (!version.is_release) { %><span class="text-muted">(未发布)</span><% } %></a></li>
+                <% }) %>
+            </ul>
+        </div>
+    </div>
+</div>

+ 94 - 96
web/users/views/version/index.html

@@ -1,100 +1,98 @@
-<div class="panel-sidebar">
-	<div class="panel-title">
-		<div class="title-bar">
-			<h2><a class="pull-right add-version" title="添加新版本" href="javascript:void(0)" data-model="all"><span class="glyphicon glyphicon-plus"></span></a>版本管理</h2>
-		</div>
-	</div>
-	<div class="scrollbar-auto">
-		<div class="nav-box">
-			<ul class="nav-list list-unstyled" id="version-select">
-				<% versionList.forEach(function (version){ %>
-				<li <% if(selectedVersion._id === version._id) { %>class="active"<% } %>><a href="/version?id=<%= version._id %>"><span><%= version.name %></span></a></li>
-				<% }) %>
-			</ul>
-		</div>
-	</div>
-</div>
+<%include ./common.html %>
 <div class="panel-content">
-	<% if(Object.keys(selectedVersion).length > 0) { %>
-	<div class="panel-title">
-		<div class="title-main">
-			<h2><%= selectedVersion.name %><a href="" class="btn btn-primary btn-sm pull-right">确定修改</a></h2>
-		</div>
-	</div>
-	<div class="content-wrap container-fluid">
-		<div class="c-body row">
-			<div class="col-md-4">
-				<div class="form-group">
-					<label>标准清单</label>
-					<div id="bill-list">
-						<% selectedVersion.standard_bill.forEach(function (bill){ %>
-						<p class="form-control-static"><a class="pull-right text-danger remove-version" data-model="bill" data-id="<%= bill.id %>" title="移除"><span class="glyphicon glyphicon-remove"></span></a><%= bill.name %></p>
-						<% }) %>
-					</div>
-					<a class="btn btn-link btn-sm add-version" href="javascript:void(0)" data-model="bill">添加</a>
-				</div>
-				<div class="form-group">
-					<label>定额库</label>
-					<div id="ration-list">
-						<% selectedVersion.ration_lib.forEach(function (ration){ %>
-						<p class="form-control-static"><a class="pull-right text-danger remove-version" data-model="ration" title="移除" data-id="<%= ration.id %>"><span class="glyphicon glyphicon-remove"></span></a><%= ration.name %></p>
-						<% }) %>
-					</div>
-					<a href="#" class="btn btn-link btn-sm add-version" data-model="ration">添加</a>
-				</div>
-				<input type="hidden" name="version-id" value="<%= selectedVersion._id %>" id="version-id">
-			</div>
-			<!--<div class="col-md-4">-->
-				<!--<div class="form-group">-->
-					<!--<label >文本选项</label>-->
-					<!--<input type="text" class="form-control" placeholder="输入内容">-->
-				<!--</div>-->
-				<!--<div class="form-group">-->
-					<!--<label >数字选项</label>-->
-					<!--<input type="number" class="form-control" placeholder="输入内容">-->
-				<!--</div>-->
-				<!--<div class="form-group">-->
-					<!--<label >下拉选项</label>-->
-					<!--<select class="form-control"><option>选择1</option><option>选择2</option></select>-->
-				<!--</div>-->
-			<!--</div>-->
-			<!--<div class="col-md-4">-->
-				<!--<div class="form-group">-->
-					<!--<label >多选</label>-->
-					<!--<div>-->
-						<!--<label class="checkbox-inline">-->
-							<!--<input type="checkbox" id="inlineCheckbox1" value="option1"> 1-->
-						<!--</label>-->
-						<!--<label class="checkbox-inline">-->
-							<!--<input type="checkbox" id="inlineCheckbox2" value="option2"> 2-->
-						<!--</label>-->
-						<!--<label class="checkbox-inline">-->
-							<!--<input type="checkbox" id="inlineCheckbox3" value="option3"> 3-->
-						<!--</label>-->
-					<!--</div>-->
-				<!--</div>-->
-				<!--<div class="form-group">-->
-					<!--<label >单选</label>-->
-					<!--<div>-->
-						<!--<label class="radio-inline">-->
-							<!--<input type="radio" name="inlineRadioOptions" id="inlineRadio1" value="option1"> 1-->
-						<!--</label>-->
-						<!--<label class="radio-inline">-->
-							<!--<input type="radio" name="inlineRadioOptions" id="inlineRadio2" value="option2"> 2-->
-						<!--</label>-->
-						<!--<label class="radio-inline">-->
-							<!--<input type="radio" name="inlineRadioOptions" id="inlineRadio3" value="option3"> 3-->
-						<!--</label>-->
-					<!--</div>-->
-				<!--</div>-->
-			<!--</div>-->
-		</div>
+    <% if(Object.keys(selectedVersion).length > 0) {%>
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>重庆版<span class="text-muted pull-right">已发布 2017-08-04</span><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-header" style="padding:0">
+            <ul class="nav nav-tabs">
+                <li role="presentation" class="active"><a href="#bill" aria-controls="bill" role="tab" data-toggle="tab">清单计价</a></li>
+                <li role="presentation"><a href="#ration" aria-controls="ration" role="tab" data-toggle="tab">定额计价</a></li>
+            </ul>
+        </div>
+        <div class="c-body tab-content">
+            <div class="tab-pane active" role="tabpanel" id="bill">
+                <a class="btn btn-default btn-sm" href="#" data-toggle="modal" data-target="#valuation-dialog"><span class="glyphicon glyphicon-plus"></span> 添加计价规则</a>
+                <table class="table">
+                    <thead>
+                    <tr>
+                        <th>计价规则</th>
+                        <th>启用/禁用</th>
+                        <th>操作</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <% if (selectedVersion.bill_valuation.length > 0) { %>
+                    <% selectedVersion.bill_valuation.forEach(function(bill) { %>
+                    <tr>
+                        <td><%= bill.name %></td>
+                        <td>
+                            <% if (bill.enable) { %>
+                            <div class="btn-group enable" data-id="<%= bill.id %>">
+                                <button class="btn btn-success  disabled" disabled="disabled">已开启</button>
+                                <button class="btn btn-default" title="禁用">禁用</button>
+                            </div>
+                            <% }else { %>
+                            <div class="btn-group enable" data-id="<%= bill.id %>">
+                                <button class="btn btn-default" title="开启">开启</button>
+                                <button class="btn btn-danger disabled" disabled="disabled">已禁用</button>
+                            </div>
+                            <% } %>
+                        </td>
+                        <td>
+                            <a href="/version/valuation/bill/<%= bill.id %>" class="btn btn-sm">编辑</a>
+                            <a href="/version/valuation/bill/delete/<%= bill.id %>" class="btn btn-sm text-danger">删除</a>
+                        </td>
+                    </tr>
+                    <% }) %>
+                    <% } %>
+                    </tbody>
+                </table>
+            </div>
+            <div class="tab-pane" role="tabpanel" id="ration">
+                <a class="btn btn-default btn-sm" href="javascript:void(0)" data-toggle="modal" data-target="#valuation-dialog"><span class="glyphicon glyphicon-plus"></span> 添加计价规则</a>
+                <table class="table">
+                    <thead>
+                    <tr>
+                        <th>计价规则</th>
+                        <th>启用/禁用</th>
+                        <th>操作</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <% if (selectedVersion.ration_valuation.length > 0) { %>
+                    <% selectedVersion.ration_valuation.forEach(function(ration) { %>
+                    <tr>
+                        <td><%= ration.name %></td>
+                        <td>
+                            <% if (ration.enable) { %>
+                            <div class="btn-group enable" data-id="<%= ration.id %>">
+                                <button class="btn btn-success  disabled" disabled="disabled">已开启</button>
+                                <button class="btn btn-default" title="禁用">禁用</button>
+                            </div>
+                            <% }else { %>
+                            <div class="btn-group enable" data-id="<%= ration.id %>">
+                                <button class="btn btn-default" title="开启">开启</button>
+                                <button class="btn btn-danger disabled" disabled="disabled">已禁用</button>
+                            </div>
+                            <% } %>
+                        </td>
+                        <td>
+                            <a href="/version/valuation/ration/<%= ration.id %>" class="btn btn-sm">编辑</a>
+                            <a href="/version/valuation/ration/delete/<%= ration.id %>" class="btn btn-sm text-danger">删除</a>
+                        </td>
+                    </tr>
+                    <% }) %>
+                    <% } %>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+        <input type="hidden" name="id" value="<%= selectedVersion._id %>" id="version-id">
+        <% } %>
 	</div>
-	<% } %>
 </div>
-<script type="text/javascript">
-	let province = '<%- province %>';
-	let billList = '<%- billList %>';
-	let rationList = '<%- rationList %>';
-</script>
 <script type="text/javascript" src="/web/users/js/version.js"></script>

+ 148 - 0
web/users/views/version/modal.html

@@ -0,0 +1,148 @@
+<!-- 弹窗新增版本 -->
+<div class="modal fade" id="addversion" tabindex="-1" role="dialog">
+    <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="add-version-title">添加新版本</h4>
+            </div>
+            <div class="modal-body">
+                <div class="form-group" id="name-area">
+                    <label>版本名称</label>
+                    <input class="form-control" placeholder="" name="version_name">
+                </div>
+                <div class="form-group" id="bill-area">
+                    <label>标准清单</label>
+                    <div class="row">
+                        <div class="col-xs-4">
+                            <select class="form-control" name="standard_bill_province">
+                                <option value="">请选择省份</option>
+                            </select>
+                        </div>
+                        <div class="col-xs-8">
+                            <select class="form-control" name="standard_bill">
+                                <option value="">请选择标准清单</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group" id="ration-area">
+                    <label>定额库</label>
+                    <div class="row">
+                        <div class="col-xs-4">
+                            <select class="form-control" name="ration_lib_province">
+                                <option value="">请选择省份</option>
+                            </select>
+                        </div>
+                        <div class="col-xs-8">
+                            <select class="form-control" name="ration_lib">
+                                <option value="">请选择定额库</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary" id="add-version">确定添加</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 弹窗新增计价 -->
+<div class="modal fade" id="valuation-dialog" 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>
+                    <input class="form-control" name="valuation_name" >
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary" id="add-valuation">确定添加</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 弹窗造价书列设置 -->
+<div class="modal fade" id="set-column" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+    <div class="modal-dialog modal-lg" 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="row">
+                    <div class="col-md-3">
+                        <div class="input-group">
+                            <span class="input-group-addon" id="basic-addon1">空行</span>
+                            <input type="number" class="form-control input-sm" value="3">
+                        </div>
+                    </div>
+                    <div class="col-md-3">
+                        <div class="input-group">
+                            <span class="input-group-addon" id="basic-addon1">数据绑定列数</span>
+                            <input type="number" class="form-control input-sm" value="4">
+                        </div>
+                    </div>
+                    <div class="col-md-3">
+                        <div class="input-group">
+                            <span class="input-group-addon" id="basic-addon1">表头行数</span>
+                            <input type="number" class="form-control input-sm" value="1">
+                        </div>
+                    </div>
+                    <div class="col-md-3">
+                        <div class="checkbox">
+                            <label>
+                                <input type="checkbox"> 是否包含树结构
+                            </label>
+                        </div>
+                    </div>
+                </div>
+                <div class="">
+                    <div class="btn-toolbar" role="toolbar">
+                        <div class="btn-group" role="group" >
+                            <a href="#" class="btn btn-default btn-sm">合并</a>
+                            <a href="#" class="btn btn-default btn-sm">拆分</a>
+                        </div>
+                        <div class="btn-group" role="group">
+                            <a href="#" class="btn btn-default btn-sm">左对齐</a>
+                            <a href="#" class="btn btn-default btn-sm">居中</a>
+                            <a href="#" class="btn btn-default btn-sm">右对齐</a>
+                        </div>
+                        <div class="btn-group" role="group">
+                            <a href="#" class="btn btn-default btn-sm">上对齐</a>
+                            <a href="#" class="btn btn-default btn-sm">垂直居中</a>
+                            <a href="#" class="btn btn-default btn-sm">下对齐</a>
+                        </div>
+                        <div class="btn-group" role="group">
+                            <div class="input-group">
+                                <span class="input-group-addon" id="basic-addon1">字体</span>
+                                <input type="text" class="form-control input-sm" >
+                                <div class="input-group-btn">
+                                    <a href="#" class="btn btn-default btn-sm">设置</a>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div>
+                    S JS在此
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary">确定</button>
+            </div>
+        </div>
+    </div>
+</div>