浏览代码

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

Chenshilong 8 年之前
父节点
当前提交
437515750c

+ 132 - 0
modules/complementary_glj_lib/controllers/gljController.js

@@ -0,0 +1,132 @@
+/**
+ * Created by Zhong on 2017/8/22.
+ */
+import BaseController from "../../common/base/base_controller";
+import stdgljutil  from "../../../public/cache/std_glj_type_util";
+import GljDao from "../models/gljModel";
+
+let gljDao = new GljDao();
+let callback = function(req, res, err, message, data){
+    res.json({error: err, message: message, data: data});
+};
+
+class GljController extends BaseController{
+    redirectGlj(req, res){
+        let gljLibId;
+        if(typeof req.session.sessionCompilation.ration_valuation[0].glj_lib[0] !== 'undefined'){
+            gljLibId = req.session.sessionCompilation.ration_valuation[0].glj_lib[0].id;
+        }
+        else if(typeof req.session.sessionCompilation.bill_valuation[0].glj_lib[0] !== 'undefined'){
+            gljLibId = req.session.sessionCompilation.bill_valuation[0].glj_lib[0].id;
+        }
+        res.render('building_saas/complementary_glj_lib/html/tools-gongliaoji.html',{
+            userID: req.session.sessionUser.ssoId,
+            gljLibId: gljLibId,
+            compilationId: req.session.sessionCompilation._id
+        });
+    }
+    getGljDistType (req, res) {
+        let gljDistTypeCache = stdgljutil.getStdGljTypeCacheObj().toArray();
+        if(gljDistTypeCache.length >0 ){
+            callback(req, res, null, '', gljDistTypeCache);
+        }
+        else {
+            callback(req, res, 1, 'Error', null);
+        }
+    }
+    getGljTree(req,res){
+        let gljLibId = req.body.gljLibId;
+        gljDao.getGljTypes(gljLibId,function(err,data){
+            callback(req,res,err, 'Get Tree', data)
+        });
+    }
+   /* updateRationBasePrc(req, res){
+        let basePrcArr = JSON.parse(req.body.basePrcArr);
+        rationItemDao.updateRationBasePrc(basePrcArr, function (err, message) {
+            if(err){
+                callback(req, res, err, message, null);
+            }
+            else{
+                callback(req, res, err, message, null);
+            }
+        });
+    }*/
+
+   /* getRationGljIds(req, res){
+        let rationLibs = req.body.rationLibs;
+        gljDao.getRationGljIds(rationLibs, function (err, msg, data) {
+            callback(req, res, err, msg, data);
+        })
+    }*/
+    createNewGljTypeNode(req, res) {
+        let repId = req.body.repositoryId;
+        let lastNodeId = req.body.lastNodeId;
+        let lastOpr = req.body.lastOpr;
+        let nodeData = JSON.parse(req.body.rawNodeData);
+        gljDao.createNewNode(repId, lastOpr, lastNodeId, nodeData, function(err, msg, data){
+            callback(req,res,err,msg, data)
+        });
+    }
+    updateGljNodes(req, res) {
+        let nodes = JSON.parse(req.body.nodes);
+        let repId = req.body.repId,
+            lastOpr = req.body.lastOpr;
+        gljDao.updateNodes(repId, lastOpr, nodes, function(err,results){
+            callback(req,res, err, results)
+        });
+    }
+    deleteGljNodes(req, res) {
+        let nodes = JSON.parse(req.body.nodes);
+        let preNodeId = req.body.preNodeId;
+        let preNodeNextId = req.body.preNodeNextId;
+        let repId = req.body.repId, lastOpr = req.body.lastOpr;
+        gljDao.removeNodes(repId, lastOpr, nodes, preNodeId, preNodeNextId, function(err,results){
+            callback(req,res, err, results)
+        });
+    }
+    getGljItems(req, res) {
+        let stdGljLibId = req.body.stdGljLibId,
+            userId = req.body.userId,
+            compilationId = req.body.compilationId;
+            gljDao.getGljItems(stdGljLibId, userId, compilationId, function(err, data){
+                callback(req,res,err,'Get Items',data)
+            });
+    }
+   /* getGljItemsByIds(req, res) {
+        let gljIds = JSON.parse(req.body.gljIds);
+        gljDao.getGljItems(gljIds, function(err, data){
+            callback(req,res,err,'Get Items',data)
+        });
+    }
+    getGljItemsByCodes(req, res) {
+        let gljCodes = JSON.parse(req.body.gljCodes),
+            repId = req.body.repId;
+        gljDao.getGljItemsByCode(repId, gljCodes, function(err, data){
+            callback(req,res,err,'Get Items',data)
+        });
+    }*/
+    updateComponent(req, res){
+        let libId = req.body.libId,
+            updateArr = req.body.updateArr,
+            oprtor = req.body.oprtor;
+        gljDao.updateComponent(libId, oprtor, updateArr, function (err, message, rst) {
+            callback(req, res, err, message, rst);
+        })
+    }
+    mixUpdateGljItems(req, res){
+        let userId = req.body.userId,
+            compilationId = req.body.compilationId,
+            updateItems = JSON.parse(req.body.updateItems),
+            addItems = JSON.parse(req.body.addItems),
+            removeIds = JSON.parse(req.body.removeIds);
+        gljDao.mixUpdateGljItems(userId, compilationId, updateItems, addItems, removeIds, function(err, message, rst){
+            if (err) {
+                callback(req, res, err, message, null);
+            } else {
+                callback(req, res, err, message, rst);
+            }
+        });
+    }
+}
+
+export default GljController;

+ 236 - 0
modules/complementary_glj_lib/models/gljModel.js

@@ -0,0 +1,236 @@
+/**
+ * Created by Zhong on 2017/8/22.
+ */
+import {complementaryGljModel, stdGljModel, gljClassModel} from "./schemas";
+import counter from "../../../public/counter/counter";
+import async from "async";
+
+class GljDao {
+    getGljTypes (gljLibId, callback){
+        gljClassModel.find({"repositoryId": gljLibId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
+            if(data.length) {
+                callback(false,data);
+            }
+            else  if(err) callback("获取工料机类型错误!",false);
+        })
+    }
+
+
+    getGljItemsByRep(repositoryId,callback){
+        gljModel.find({"repositoryId": repositoryId},function(err,data){
+            if(err) callback(true, "")
+            else callback(false,data);
+        })
+    }
+
+    getGljItemByType (repositoryId, type, callback){
+        gljModel.find({"repositoryId": repositoryId, "gljType": type},function(err,data){
+            if(err) callback(true, "")
+            else callback(false, data);
+        })
+    };
+
+    getGljItem (repositoryId, code, callback){
+        gljModel.find({"repositoryId": repositoryId, "code": code},function(err,data){
+            if(err) callback(true, "")
+            else callback(false, data);
+        })
+    };
+    //获得用户的补充工料机和用户当前所在编办的标准工料机
+    getGljItems (stdGljLibId, userId, compilationId, callback){
+        let rst = {stdGljs: [], complementaryGljs: []};
+        async.parallel([
+            function (cb) {
+                stdGljModel.find({repositoryId: stdGljLibId}, function (err, stdGljs) {
+                    if(err){
+                        cb(err);
+                    }
+                    else{
+                        rst.stdGljs = stdGljs;
+                        cb(null);
+                    }
+                });
+            },
+            function (cb) {
+                complementaryGljModel.find({userId: userId, compilationId: compilationId}, function (err, complementaryGljs) {
+                    if(err){
+                        cb(err);
+                    }
+                    else{
+                        rst.complementaryGljs = complementaryGljs;
+                        cb(null);
+                    }
+                });
+            }
+        ], function (err) {
+            if(err){
+                callback(true, null);
+            }
+            else{
+                callback(false, rst);
+            }
+        })
+
+    };
+
+    getGljItemsByCode (repositoryId, codes, callback){
+        gljModel.find({"repositoryId": repositoryId,"code": {"$in": codes}},function(err,data){
+            if(err) callback(true, "")
+            else callback(false, data);
+        })
+    };
+
+    //-oprtor
+    updateComponent(libId, updateArr, callback){
+        let parallelFucs = [];
+        for(let i = 0; i < updateArr.length; i++){
+            parallelFucs.push((function(obj){
+                return function (cb) {
+                    if(typeof obj.component === 'undefined'){
+                        obj.component = [];
+                    }
+                    gljModel.update({repositoryId: libId, ID: obj.ID}, obj, function (err, result) {
+                        if(err){
+                            cb(err);
+                        }
+                        else{
+                            cb(null, obj);
+                        }
+                    })
+                }
+            })(updateArr[i]));
+        }
+        async.parallel(parallelFucs, function (err, result) {
+            if(err){
+                callback(err, '更新组成物错误!', null);
+            }
+            else{
+                callback(null, '成功!', result);
+            }
+        });
+    }
+    //-oprtor
+    mixUpdateGljItems (userId, compilationId, updateItems, addItems, rIds, callback) {
+        if (updateItems.length == 0 && rIds.length == 0) {
+            GljDao.addGljItems(userId, compilationId, addItems, callback);
+        }
+        else if(rIds.length > 0 && updateItems.length > 0){
+            async.parallel([
+                function (cb) {
+                    GljDao.removeGljItems(rIds, cb);
+                },
+                function (cb) {
+                    GljDao.updateGljItems(userId, compilationId, updateItems, cb);
+                }
+            ], function (err) {
+                if(err){
+                    callback(true, "Fail to update and delete", false)
+                }
+                else{
+                    callback(false, "Save successfully", false);
+                }
+            })
+        }
+        else if (rIds.length > 0 && updateItems.length === 0) {
+            GljDao.removeGljItems(rIds, callback);
+        }
+        else if(updateItems.length > 0 || addItems.length > 0){
+            GljDao.updateGljItems(userId, compilationId, updateItems, function(err, results){
+                if (err) {
+                    callback(true, "Fail to update", false);
+                } else {
+                    if (addItems && addItems.length > 0) {
+                        GljDao.addGljItems(userId, compilationId, addItems, callback);
+                    } else {
+                        callback(false, "Save successfully", results);
+                    }
+                }
+            });
+        }
+    }
+
+    /*mixUpdateGljItems (repId, lastOpr, updateItems, addItems, rIds, callback) {
+     if (updateItems.length == 0 && rIds.length == 0) {
+     GljDao.addGljItems(repId, lastOpr, addItems, callback);
+     } else if (rIds.length > 0) {
+     GljDao.removeGljItems(repId, lastOpr, rIds, function(err, message, docs) {
+     });
+     }else{
+     GljDao.updateGljItems(repId, lastOpr, updateItems, function(err, results){
+     if (err) {
+     callback(true, "Fail to update", false);
+     } else {
+     if (addItems && addItems.length > 0) {
+     GljDao.addGljItems(repId, lastOpr, addItems, callback);
+     } else {
+     callback(false, "Save successfully", results);
+     }
+     }
+     });
+     }
+     };*/
+
+    static removeGljItems (rIds, callback) {
+        if (rIds && rIds.length > 0) {
+            complementaryGljModel.collection.remove({ID: {$in: rIds}}, null, function(err, docs){
+                if (err) {
+                    callback(true, "Fail to remove", false);
+                } else {
+                    callback(false, "Remove successfully", docs);
+                }
+            })
+        } else {
+            callback(false, "No records were deleted!", null);
+        }
+    }
+
+    static addGljItems (userId, compilationId, items, callback) {
+        if (items && items.length > 0) {
+            counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, items.length, function(err, result){
+                var maxId = result.value.sequence_value;
+                var arr = [];
+                for (var i = 0; i < items.length; i++) {
+                    var obj = new complementaryGljModel(items[i]);
+                    obj.ID = (maxId - (items.length - 1) + i);
+                    obj.userId = userId;
+                    obj.compilationId = compilationId;
+                    arr.push(obj);
+                }
+                complementaryGljModel.collection.insert(arr, null, function(err, docs){
+                    if (err) {
+                        callback(true, "Fail to add", false);
+                    } else {
+                        callback(false, "Add successfully", docs);
+                    }
+                });
+            });
+        } else {
+            callback(true, "No source", false);
+        }
+    }
+
+    static updateGljItems(userId, compilationId, items, callback) {
+        var functions = [];
+        for (var i=0; i < items.length; i++) {
+            functions.push((function(doc) {
+                return function(cb) {
+                    var filter = {};
+                    if (doc.ID) {
+                        filter.ID = doc.ID;
+                    } else {
+                        filter.userId = userId;
+                        filter.compilationId = compilationId;
+                        filter.code = doc.code;
+                    }
+                    complementaryGljModel.update(filter, doc, cb);
+                };
+            })(items[i]));
+        }
+        async.parallel(functions, function(err, results) {
+            callback(err, results);
+        });
+    }
+}
+
+export default GljDao;
+

+ 60 - 0
modules/complementary_glj_lib/models/schemas.js

@@ -0,0 +1,60 @@
+/**
+ * Created by Zhong on 2017/8/22.
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let gjlComponentSchema = mongoose.Schema(
+    {
+        ID: Number,
+        consumeAmt: Number
+    },
+    {_id: false},
+    {versionKey: false}
+);
+//补充工料机跟用户和编办绑定
+let complementaryGljSchema = new Schema({
+    userId: Number,
+    compilationId: String,
+    ID: Number,
+    code: String,
+    name: String,
+    specs: String,
+    unit: String,
+    basePrice: String,
+    gljClass: Number,
+    gljType: Number,
+    shortName: String,
+    component: [gjlComponentSchema]
+}, {versionKey: false});
+
+//标准工料机
+let stdGljSchema = new Schema({
+    deleted: Boolean,
+    repositoryId: Number,
+    ID: Number,
+    code: String,
+    name: String,
+    specs: String,
+    basePrice: Number,
+    gljClass: Number,
+    gljType: Number,
+    shortName: String,
+    component: [gjlComponentSchema]
+},{versionKey: false});
+
+//标准工料机分类树
+let gljClassSchema = mongoose.Schema({
+    repositoryId: Number,
+    ID: Number,
+    ParentID: Number,
+    NextSiblingID: Number,
+    Name: String,
+    deleted: Boolean
+}, {versionKey: false});
+
+let complementaryGljModel = mongoose.model('complementary_glj_lib', complementaryGljSchema, 'complementary_glj_lib');
+let stdGljModel = mongoose.model('std_glj_lib_gljList', stdGljSchema, 'std_glj_lib_gljList');
+let gljClassModel = mongoose.model('std_glj_lib_gljClass', gljClassSchema, 'std_glj_lib_gljClass');
+
+export {complementaryGljModel, stdGljModel, gljClassModel};

+ 29 - 0
modules/complementary_glj_lib/routes/routes.js

@@ -0,0 +1,29 @@
+/**
+ * Created by Zhong on 2017/8/22.
+ */
+
+import express from "express";
+import GljController from "../controllers/gljController"
+
+let router = express.Router();
+let gljController = new GljController();
+
+module.exports = function (app) {
+    app.get('/complementartGlj', gljController.init, gljController.redirectGlj);
+
+   /* router.post("/updateRationBasePrc",gljController.init, gljController.updateRationBasePrc);//更新定额单价
+    router.post("/getRationGljIds", gljController.init, gljController.getRationGljIds);
+    router.post("/createNewGljTypeNode", gljController.init, gljController.createNewGljTypeNode);
+    router.post("/updateGljNodes", gljController.init, gljController.updateGljNodes);
+    router.post("/deleteGljNodes", gljController.init, gljController.deleteGljNodes);*/
+    router.post("/getGljDistType", gljController.init, gljController.getGljDistType);
+    router.post("/getGljTree", gljController.init, gljController.getGljTree);
+    router.post("/getGljItems", gljController.init, gljController.getGljItems);
+    router.post("/updateComponent", gljController.init, gljController.updateComponent);
+    router.post("/mixUpdateGljItems", gljController.init, gljController.mixUpdateGljItems);
+    //router.post("/getGljItemsByIds", gljController.init, gljController.getGljItemsByIds);
+    //router.post("/getGljItemsByCodes", gljController.init, gljController.getGljItemsByCodes);
+
+    app.use("/complementartGlj/api", router);
+
+};

+ 9 - 9
modules/pm/models/project_model.js

@@ -9,7 +9,9 @@ let copyProjController = require('../controllers/copy_proj_controller');
 let Projects = require("./project_schema");
 let projectType = {
     folder: 'Folder',
-    tender: 'Tender'
+    tender: 'Tender',
+    project: 'Project',
+    engineering: 'Engineering',
 };
 
 let ProjectsDAO = function(){};
@@ -44,6 +46,7 @@ ProjectsDAO.prototype.updateUserProjects = function(userId, datas, callback){
                 }
             } else {
                 hasError = true;
+                console.log(err);
                 callback(1, '提交数据出错.', null);
             }
         };
@@ -54,9 +57,7 @@ ProjectsDAO.prototype.updateUserProjects = function(userId, datas, callback){
                 Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll)
             } else if (data.updateType === 'new') {
                 data.updateData['userID'] = userId;
-                if (data.updateData.projType === projectType.folder) {
-                    data.updateData['createDateTime'] = new Date();
-                }
+                data.updateData['createDateTime'] = new Date();
                 newProject = new Projects(data.updateData);
                 newProject.save(function (err, result) {
                     if (!err && result._doc.projType === projectType.tender) {
@@ -92,6 +93,7 @@ ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
             callback(1, '提交数据出错.', null);
         }
     };
+    console.log(datas);
     if (datas) {
         for (i = 0; i < datas.length && !hasError; i++) {
             data = datas[i];
@@ -99,14 +101,12 @@ ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
                 Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll)
             } else if (data.updateType === 'copy') {
                 data.updateData['userID'] = userId;
-                if (data.updateData.projType === 'Tender') {
-                    data.updateData['createDateTime'] = new Date();
-                };
-                newProject = new Projects(data.updateData);
+                data.updateData['createDateTime'] = new Date();
+                let newProject = new Projects(data.updateData);
                 newProject['srcProjectId'] = data.srcProjectId;
                 newProject.save(function (err, result) {
                     if (!err && result._doc.projType === 'Tender') {
-                        copyProjController.copyProjectData(this.newProject.srcProjectId, result._doc.ID, updateAll);
+                        copyProjController.copyProjectData(newProject.srcProjectId, result._doc.ID, updateAll);
                     } else {
                         updateAll(err);
                     }

+ 15 - 3
modules/pm/routes/pm_route.js

@@ -9,9 +9,21 @@ let pmController = require('./../controllers/pm_controller');
 module.exports = function (app) {
 
     app.get('/pm', function(req, res){
-        res.render('building_saas/pm/html/project-management.html',
-            {userAccount: req.session.userAccount,
-                userID: req.session.sessionUser.ssoId});
+        // 获取编办信息
+        let sessionCompilation = req.session.sessionCompilation;
+        // 清单计价
+        let billValuation = sessionCompilation.bill_valuation !== undefined ? sessionCompilation.bill_valuation : [];
+
+        // 定额计价
+        let rationValuation = sessionCompilation.ration_valuation !== undefined ? sessionCompilation.ration_valuation : [];
+        let renderData = {
+            userAccount: req.session.userAccount,
+            userID: req.session.sessionUser.ssoId,
+            compilationData: sessionCompilation,
+            billValuation: JSON.stringify(billValuation),
+            rationValuation: JSON.stringify(rationValuation),
+        };
+        res.render('building_saas/pm/html/project-management.html', renderData);
     });
 
     let pmRouter = express.Router();

+ 1 - 1
modules/users/controllers/boot_controller.js

@@ -27,7 +27,7 @@ class BootController extends BaseController {
         // 判断是否有存入编办信息
         if (sessionCompilation === undefined && compilationId !== '') {
             let compilationModel = new CompilationModel();
-            let compilationData = await compilationModel.findDataByCondition({_id: compilationId});
+            let compilationData = await compilationModel.getCompilationById(compilationId);
 
             request.session.sessionCompilation = compilationData;
         }

+ 2 - 3
modules/users/controllers/login_controller.js

@@ -74,13 +74,12 @@ class LoginController {
 
             let compilationModel = new CompilationModel();
             compilationList = preferenceSetting.login_ask === 1 ? await compilationModel.getList() : [];
-
             // 获取编办信息
             let sessionCompilation = request.session.sessionCompilation;
-            if (preferenceSetting.login_ask === 0 && sessionCompilation === undefined &&
+            if (preferenceSetting.login_ask === 0 && !sessionCompilation &&
                 preferenceSetting.select_version !== '') {
-                let compilationData = await compilationModel.findDataByCondition({_id: preferenceSetting.select_version});
 
+                let compilationData = await compilationModel.getCompilationById(preferenceSetting.select_version);
                 request.session.sessionCompilation = compilationData;
             }
 

+ 1 - 1
modules/users/controllers/user_controller.js

@@ -175,7 +175,7 @@ class UserController extends BaseController {
             if (data.login_ask === 1) {
                 // 查找对应编办
                 let compilationModel = new CompilationModel();
-                let compilationData = await compilationModel.findDataByCondition({_id: selectVersion});
+                let compilationData = await compilationModel.getCompilationById(selectVersion);
 
                 request.session.sessionCompilation = compilationData;
             }

+ 35 - 1
modules/users/models/compilation_model.js

@@ -29,11 +29,45 @@ class CompilationModel extends BaseModel {
     async getList() {
         // 筛选字段
         let field = {_id: 1, name: 1, is_release: 1};
-        let compilationData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
+        let compilationData = await this.findDataByCondition({name: {$ne: ''}, is_release: true}, field, false);
 
         return compilationData === null ? [] : compilationData;
     }
 
+    /**
+     * 根据id获取可用的编办数据
+     *
+     * @param {String} id
+     * @return {Promise}
+     */
+    async getCompilationById(id) {
+        let condition = {_id: id, is_release: true};
+        let compilationData = await this.findDataByCondition(condition);
+        if (compilationData.bill_valuation === undefined) {
+            return compilationData;
+        }
+
+        if (compilationData.bill_valuation.length > 0) {
+            for (let index in compilationData.bill_valuation) {
+                if (compilationData.bill_valuation[index].enable) {
+                    continue;
+                }
+                delete compilationData.bill_valuation[index];
+            }
+        }
+
+        if (compilationData.ration_valuation.length > 0) {
+            for (let index in compilationData.ration_valuation) {
+                if (compilationData.ration_valuation[index].enable) {
+                    continue;
+                }
+                delete compilationData.ration_valuation[index];
+            }
+        }
+
+        return compilationData;
+    }
+
 }
 
 export default CompilationModel;

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

@@ -21,6 +21,7 @@ module.exports = function (app) {
 
     router.get("/logout", function (req, res) {
         delete req.session.sessionUser;
+        delete req.session.sessionCompilation;
         res.redirect("/");
     });
     app.use('/',router)

+ 1 - 1
public/models/delete_schema.js

@@ -5,7 +5,7 @@
 var mongoose = require("mongoose");
 var Schema = mongoose.Schema;
 
-// ·ÑÓÃ×Ö¶Î
+
 var deleteSchema = new Schema({
     deleted: Boolean,
     deleteDateTime: Date,

+ 2 - 2
server.js

@@ -3,8 +3,8 @@ let express = require('express');
 let config = require("./config/config.js");
 let fileUtils = require("./modules/common/fileUtils");
 let dbm = require("./config/db/db_manager");
-//config.setToLocalDb();
-config.setToQaDb();
+config.setToLocalDb();
+// config.setToQaDb();
 
 let path = require('path');
 let session = require('express-session');

+ 319 - 0
web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html

@@ -0,0 +1,319 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>工料机库编辑-Smartcost</title>
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css" type="text/css">
+    <link rel="stylesheet" href="/web/building_saas/css/main.css" type="text/css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css" type="text/css">
+    <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css" type="text/css">
+    <!--zTree-->
+  	<link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
+    <style type="text/css">
+        .modal-lg{max-width: 1000px}
+    </style>
+</head>
+<body>
+    <div class="header">
+        <!-- <div class="top-msg clearfix">
+            <div class="alert alert-warning mb-0 py-0" role="alert">
+                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+                  <span aria-hidden="true">&times;</span>
+                </button>
+                <strong>Warning!</strong> Better check yourself, you're not looking too good.
+            </div>
+        </div> -->
+        <nav class="navbar navbar-toggleable-lg navbar-light bg-faded p-0 justify-content-between">
+            <span class="header-logo px-2">Smartcost</span>
+            <div class="navbar-text"><a href="project-management.html">项目管理</a></div>
+            <div class="float-lg-right navbar-text pt-0">
+                <div class="dropdown d-inline-block">
+                    <button class="btn btn-link btn-sm dropdown-toggle" type="button" data-toggle="dropdown">陈特</button>
+                    <div class="dropdown-menu dropdown-menu-right">
+                        <a class="dropdown-item" href="user-info.html" target="_blank">账号资料</a>
+                        <a class="dropdown-item" href="user-buy.html" target="_blank">产品购买</a>
+                        <a class="dropdown-item" href="user-set.html" target="_blank">偏好设置</a>
+                    </div>
+                </div>
+                <span class="btn btn-link btn-sm new-msg">
+                  <i class="fa fa-envelope-o" aria-hidden="true"></i>&nbsp;2
+                </span>
+                <button class="btn btn-link btn-sm">注销</button>
+            </div>
+        </nav>
+        <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
+            <ul class="nav navbar-nav px-1">
+                <li class="nav-item">
+                    <a class="nav-link" href="#" aria-expanded="false"><i class="fa fa-sliders"></i> 选项</a>
+                </li>
+                <li class="nav-item dropdown">
+                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-wrench"></i> 工具</a>
+                    <div class="dropdown-menu">
+                        <a class="dropdown-item" href="#">定额库编辑器</a>
+                        <a class="dropdown-item" href="#">工料机库编辑器</a>
+                    </div>
+                </li>
+                <li class="nav-item dropdown">
+                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-question-circle-o"></i> 帮助</a>
+                    <div class="dropdown-menu">
+                        <a class="dropdown-item" href="#">帮助</a>
+                        <a class="dropdown-item" href="#">升级说明</a>
+                        <a class="dropdown-item" href="#">重庆市2008定额说明</a>
+                        <a class="dropdown-item" href="#">纵横官网</a>
+                        <a class="dropdown-item" href="#">动画教程</a>
+                        <a class="dropdown-item" href="#">联系客服</a>
+                        <a class="dropdown-item" href="#">关于</a>
+                    </div>
+                </li>
+                <li class="nav-item">
+                    <a href="javacript:void(0);" data-toggle="modal" data-target="#history" class="nav-link"><i class="fa fa-history"></i> 历史记录</a>
+                </li>
+            </ul>
+            <form class="form-inline">
+                <input class="form-control form-control-sm mr-1" type="text" placeholder="告诉我你想做什么">
+            </form>
+        </nav>
+    </div>
+    <div class="main">
+        <div class="main-nav">
+            <ul class="nav flex-column">
+              <li><a href="#">定额库编辑器</a></li>
+              <li><a href="tools-gongliaoji.html" class="active">工料机库编辑器</a></li>
+            </ul>
+        </div>
+        <div class="content">
+            <div class="container-fluid">
+              <div class="row">
+                <div class="col-lg-2 p-0">
+                  <div class="print-list">
+                    <div class="form-list">
+                      <ul id="repositoryTree" class="ztree"></ul>
+                    </div>
+                  </div>
+                </div>
+                <div id="GLJListSheet" class="col-lg-7 p-0">
+
+                </div>
+                <div id="gljComponentSheet" class="col-lg-3 p-0">
+                </div>
+              </div>
+            </div>
+        </div>
+      </div>
+      <!--弹出组成物-->
+    <button id="componentBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#component" style="display: none"></button>
+      <div class="modal fade" id="component" data-backdrop="static">
+          <div class="modal-dialog modal-lg" role="document" id="modalCon">
+              <div class="modal-content" >
+                  <div class="modal-header">
+                    <h5 class="modal-title">内容</h5>
+                      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                      </button>
+                  </div>
+                  <div class="modal-body">
+                    <div class="row">
+                      <div class="col-4">
+                        <div  class="modal-auto-height">
+                            <div class="print-list">
+                                <div class="form-list" id="componentTreeDiv">
+                                    <ul id="componentTree" class="ztree"></ul>
+                                </div>
+                            </div>
+                        </div>
+                      </div>
+                      <div class="col-8">
+                          <div class="row">
+                              <div class="modal-auto-height col-12" id="gljRadios">
+                                  <input type="radio" class="glj-radio" name="glj" value="allGljs">所有工料机&nbsp;&nbsp;
+                                  <input type="radio" class="glj-radio" name="glj" value="stdGljs">标准工料机&nbsp;&nbsp;
+                                  <input type="radio" class="glj-radio" name="glj" value="complementaryGljs">补充工料机
+                              </div>
+                              <div class="modal-auto-height col-12"  id="componentSheet">
+                               <!--   <table class="table table-sm table-bordered m-0">
+                                      <thead>
+                                      <tr><th></th><th>编码</th><th>名称</th><th>规格型号</th><th>计量单位</th><th>单价</th><th>类型</th></tr>
+                                      </thead>
+                                      <tbody>
+                                      <tr><td>1</td><td></td><td></td><td></td><td></td><td></td></tr>
+                                      <tr><td>2</td><td></td><td></td><td></td><td></td><td></td></tr>
+                                      <tr><td>3</td><td></td><td></td><td></td><td></td><td></td></tr>
+                                      <tr><td>4</td><td></td><td></td><td></td><td></td><td></td></tr>
+                                      </tbody>
+                                  </table>-->
+                              </div>
+                          </div>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="modal-footer">
+                      <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                      <a href="javascript:void(0);" class="btn btn-primary">确定</a>
+                  </div>
+              </div>
+          </div>
+      </div>
+    <!--弹出警告-->
+    <button id="gljAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#gljAlert" style="display: none"></button>
+    <button id="codeAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#codeAlert" style="display: none"></button>
+    <div class="modal fade" id="gljAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="gdid" value="123">
+        <div class="modal-dialog" role="document" style="width: 1200px;">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">取消确认</h5>
+                    <button type="button" id="gljAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger" id="alertGljTxt">编号和类型不可为空!是否取消操作?</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" id="aleCanceBtn" data-dismiss="modal">取消</button>
+                    <a href="javascript: void(0);" id="aleConfBtn" class="btn btn-danger" data-dismiss="modal">确认</a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="modal" id="codeAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="codedid" value="123">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">警告</h5>
+                    <button type="button" id="codAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger" id="alertText">输入的编号已存在,请重新输入!</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-danger" id="codAleConfBtn" data-dismiss="modal">确认</button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- JS. -->
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.contextMenu.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.ui.position.js"></script>
+    <script src="/lib/tether/tether.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/web/building_saas/js/global.js"></script>
+    <!-- zTree -->
+    <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
+    <script>GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";</script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.exedit.js"></script>
+    <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
+    <script type="text/javascript" src="/public/web/QueryParam.js"></script>
+    <script type="text/javascript" src="/web/building_saas/complementary_glj_lib/js/glj.js"></script>
+    <script type="text/javascript" src="/web/building_saas/complementary_glj_lib/js/gljComponent.js"></script>
+    <script type="text/javascript" src="/web/building_saas/complementary_glj_lib/js/components.js"></script>
+    <script type="text/javascript" src="/public/web/ztree_common.js"></script>
+    <script type="text/javascript" src="/web/building_saas/complementary_glj_lib/js/sheetOpr.js"></script>
+    <script type="text/javascript" src="/public/web/storageUtil.js"></script>
+    <SCRIPT type="text/javascript">
+        let userId = "<%= userID%>";
+        let compilationId = "<%= compilationId%>";
+        let stdGljLibId = "<%= gljLibId%>";//用户当前编办下的标准工料机库ID,目前认为一个编办只有一个标准工料机库
+        let gljSetting = {
+            view: {
+                //addHoverDom: gljTypeTreeOprObj.addHoverDom,
+                //removeHoverDom: gljTypeTreeOprObj.removeHoverDom,
+                expandSpeed: "",
+                selectedMulti: false
+            },
+            edit: {
+                enable: false,
+                editNameSelectAll: true,
+                showRemoveBtn: true,
+                showRenameBtn: true,
+                removeTitle: "删除节点",
+                renameTitle: "更改名称"
+            },
+            data: {
+                keep: {
+                    parent:true,
+                    leaf:true
+                },
+                key: {
+                    children: "items",
+                    name: "Name"
+                },
+                simpleData: {
+                    enable: false,
+                    idKey: "ID",
+                    pIdKey: "ParentID",
+                    rootPId: -1
+                }
+            },
+            callback:{
+                onClick: gljTypeTreeOprObj.onClick
+            }
+        };
+        //组成物弹出窗口组成物分类树
+        let componentSetting = {
+            view: {
+                //addHoverDom: gljTypeTreeOprObj.addHoverDom,
+                //removeHoverDom: gljTypeTreeOprObj.removeHoverDom,
+                expandSpeed: "",
+                selectedMulti: false
+            },
+            edit: {
+                enable: false,
+                editNameSelectAll: true,
+                showRemoveBtn: true,
+                showRenameBtn: true,
+                removeTitle: "删除节点",
+                renameTitle: "更改名称"
+            },
+            data: {
+                keep: {
+                    parent:true,
+                    leaf:true
+                },
+                key: {
+                    children: "items",
+                    name: "Name"
+                },
+                simpleData: {
+                    enable: false,
+                    idKey: "ID",
+                    pIdKey: "ParentID",
+                    rootPId: -1
+                }
+            },
+            callback:{
+                onClick: componentTypeTreeOprObj.onClick
+            }
+        };
+        $(document).ready(function(){
+            //解决spreadjs sheet初始化没高度宽度
+            $('#modalCon').width($(window).width()*0.5);
+            $('#componentTreeDiv').height($(window).height() - 300);
+            $("#componentSheet").height($("#componentTreeDiv").height()-21.6);
+            $("#componentSheet").width($('#modalCon').width() * 0.63);
+            pageOprObj.initPage($("#GLJListSheet")[0], $('#gljComponentSheet')[0], $('#componentSheet')[0]);
+        });
+        //组成物弹出窗大小设置
+        $(window).resize(function () {
+            $('#modalCon').width($(window).width()*0.5);
+            $('#componentTreeDiv').height($(window).height() - 300);
+            $("#componentSheet").height($("#componentTreeDiv").height()-21.6);
+            $("#componentSheet").width($('#modalCon').width()* 0.63);
+        });
+  	</SCRIPT>
+</body>
+<script type="text/javascript">
+    autoFlashHeight();
+</script>
+
+</html>

+ 210 - 0
web/building_saas/complementary_glj_lib/js/components.js

@@ -0,0 +1,210 @@
+/**
+ * Created by Zhong on 2017/8/25.
+ */
+/*
+   弹出组成物窗口 组成物表
+ * */
+let componentOprObj = {
+    treeObj:null,
+    rootNode: null,//分类树根节点
+    radiosSelected: null,//allGljs, stdGljs, complementaryGljs
+    workBook: null,
+    setting: {
+        owner: "components",
+        header: [
+            {headerName:"选择", headerWidth: 40, dataCode: "select", hAlign: "center", vAlign: "center"},
+            {headerName:"编码",headerWidth:80,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
+            {headerName:"名称",headerWidth:120,dataCode:"name", dataType: "String", hAlign: "left", vAlign: "center"},
+            {headerName:"规格型号",headerWidth:80,dataCode:"specs", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"计量单位",headerWidth:80,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"单价",headerWidth:80,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
+            {headerName:"类型",headerWidth:80,dataCode:"gljType", dataType: "String",  hAlign: "center", vAlign: "center"}
+        ],
+        view: {
+            lockedCells: [1, 2, 3]
+        }
+    },
+    buildSheet: function (container) {
+        let me = componentOprObj;
+        me.workBook = sheetOpr.buildSheet(container, me.setting, 30);
+        me.workBook.getSheet(0).setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
+        me.workBook.getSheet(0).setFormatter(-1, 1, "@", GC.Spread.Sheets.SheetArea.viewport);
+        me.workBook.getSheet(0).options.isProtected = true;
+        sheetOpr.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
+        me.radiosChange();
+    },
+    setShowGljList: function (gljList) {
+        //初始为所有工料机,机械类型可添加机械组成物,混凝土,砂浆、配合比可添加普通材料
+        let materialArr = [202, 203, 204];//混凝土、砂浆、配合比, 201普通材料
+        let that = repositoryGljObj, me = componentOprObj;
+            for(let i = 0; i < gljList.length; i++){
+                if(that.currentGlj.gljType === 3 && gljList[i].gljType === 302 ||
+                    materialArr.indexOf(that.currentGlj.gljType) !== -1 && gljList[i].gljType === 201){
+                    //去除与已添加的组成物重复的条目
+                    let isExist = false;
+                    for(let j = 0; j < that.currentComponent.length; j++){
+                        if(that.currentComponent[j].ID === gljList[i].ID){
+                            isExist = true;
+                            break;
+                        }
+                    }
+                    if(!isExist){
+                        gljList[i].isChecked = false;
+                        me.showGljList.push(gljList[i]);
+                    }
+                }
+            }
+    },
+    //初始默认radio
+    initRadio: function () {
+        let that = repositoryGljObj, me = componentOprObj;
+        //默认radio所有工料机
+        if(typeof $("input[name='glj']:checked")[0] !== 'undefined'){
+            $("input[name='glj']:checked")[0].checked = false;
+        }
+        $("input[value = 'allGljs']")[0].checked = true;
+        me.radiosSelected = 'allGljs';
+        //初始为所有工料机,机械类型可添加机械组成物,混凝土,砂浆、配合比可添加普通材料
+        me.showGljList = [];
+        if(me.radiosSelected === 'allGljs'){
+            me.setShowGljList(that.stdGljList);
+            me.setShowGljList(that.complementaryGljList);
+            that.sortGlj(me.showGljList);
+        }
+    },
+    //监听radios选择事件
+    radiosChange: function () {
+        let me = componentOprObj, re = repositoryGljObj;
+        let materialArr = [202, 203, 204];//混凝土、砂浆、配合比, 201普通材料
+        $('.glj-radio').change(function () {
+            let val = $("input[name='glj']:checked").val();
+            me.radiosSelected = val;
+            //选择改变,数据重新筛选显示
+            me.showGljList = [];
+            if(me.radiosSelected === 'allGljs'){
+                me.setShowGljList(re.stdGljList);
+                me.setShowGljList(re.complementaryGljList);
+            }
+            else if(me.radiosSelected === 'stdGljs'){
+               me.setShowGljList(re.stdGljList);
+            }
+            else if(me.radiosSelected === 'complementaryGljs'){
+                me.setShowGljList(re.complementaryGljList);
+            }
+            re.sortGlj(me.showGljList);
+            //重新显示
+            me.showGljItems(me.showGljList, me.gljCurTypeId);
+            //切换radio后更新cache
+            if (me.currentOprParent = 1) {
+                if(re.parentNodeIds["_pNodeId_" + me.gljCurTypeId]){
+                    me.currentCache = me.getParentCache(re.parentNodeIds["_pNodeId_" + me.gljCurTypeId]);
+                }
+                else{
+                    me.currentCache = [];
+                }
+            } else {
+                me.currentCache = me.getCache();
+            }
+        });
+    },
+    //切换分类树时,记住当前分类的选择, value = true、false、null
+    setComponentChecked: function (sheet) {
+        let me = componentOprObj;
+        for(let i = 0; i < sheet.getRowCount(); i ++){
+            if(sheet.getValue(i, 0) === true){//选择了
+                me.preCache[i].isChecked = true;
+            }
+            else if(sheet.getValue(i, 0) === false){//避免value为null
+                me.preCache[i].isChecked = false;
+            }
+        }
+    },
+    //获得选择的组成物
+    getComponents: function () {
+        let rst = [];
+        let me = componentOprObj;
+        for(let i = 0; i < me.showGljList.length; i++){
+
+        }
+    },
+    getParentCache: function (nodes) {
+        let me = componentOprObj, rst = [];
+        for(let i = 0; i < me.showGljList.length; i++){
+            if(nodes.indexOf(me.showGljList[i].gljClass) !== -1){
+                rst.push(me.showGljList[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() {
+        let me = componentOprObj, rst = [];
+        for (let i = 0; i < me.showGljList.length; i++) {
+            if (me.showGljList[i].gljClass == me.gljCurTypeId) {
+                rst.push(me.showGljList[i]);
+            }
+        }
+        return rst;
+    },
+    showGljItems: function(data, type) {
+        let me = componentOprObj, re = repositoryGljObj;
+        if (me.workBook) {
+            let cacheSection = [];
+            let pArr = re.parentNodeIds["_pNodeId_" + type];
+            for (let i = 0; i < data.length; i++) {
+                if (pArr && pArr.indexOf(data[i].gljClass) >= 0) {
+                    cacheSection.push(data[i]);
+                } else if (type == data[i].gljClass) {
+                    cacheSection.push(data[i]);
+                }
+            }
+            sheetOpr.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
+            sheetOpr.showData(me.workBook.getSheet(0), me.setting, cacheSection, re.distTypeTree);
+            cacheSection = null;
+        }
+    }
+};
+
+let componentTypeTreeOprObj = {
+    //todo: 当关闭后,将gljcurTypeId置0
+    onClick: function(event,treeId,treeNode) {
+        let me = componentOprObj, re = repositoryGljObj, that = gljComponentOprObj, gljTypeId = treeNode.ID;
+        if(me.gljCurTypeId !== treeNode.ID){
+            me.gljCurTypeId = treeNode.ID;
+            if(typeof me.currentCache === 'undefined'){
+                if (re.parentNodeIds["_pNodeId_" + treeNode.ID]) {
+                    me.currentOprParent = 1;
+                    me.currentCache = me.getParentCache(re.parentNodeIds["_pNodeId_" + treeNode.ID]);
+                } else {
+                    me.currentCache = me.getCache();
+                }
+                me.preCache = me.currentCache;
+            }
+            else{
+                me.preCache = me.currentCache;
+                if (re.parentNodeIds["_pNodeId_" + treeNode.ID]) {
+                    me.currentOprParent = 1;
+                    me.currentCache = me.getParentCache(re.parentNodeIds["_pNodeId_" + treeNode.ID]);
+                } else {
+                    me.currentCache = me.getCache();
+                }
+            }
+            //切换分类树时,记住当前分类的选择
+            me.setComponentChecked(me.workBook.getSheet(0));
+            me.showGljItems(me.showGljList, gljTypeId);
+        }
+        /*sheetOpr.cleanSheet(that.workBook.getSheet(0), that.setting, 5);
+        that.workBook.getSheet(0).getRange(-1, 0 , -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+        that.workBook.getSheet(0).getRange(-1, 4 , -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+        re.workBook.getSheet(0).getRange(-1, 6 , -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);*/
+        //that.workBook.getSheet(0).options.isProtected = true;
+
+        //sheetOpr.lockCodeCells(re.workBook.getSheet(0), re.currentCache.length);
+        //re.workBook.getSheet(0).setRowCount(re.currentCache.length);
+    }
+}

文件差异内容过多而无法显示
+ 1040 - 0
web/building_saas/complementary_glj_lib/js/glj.js


+ 466 - 0
web/building_saas/complementary_glj_lib/js/gljComponent.js

@@ -0,0 +1,466 @@
+/**
+ * Created by Zhong on 2017/8/15.
+ */
+
+let gljComponentOprObj = {
+    workBook: null,
+    setting: {
+        owner: "gljComponent",
+        header:[
+            {headerName:"编码",headerWidth:80,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
+            {headerName:"名称",headerWidth:120,dataCode:"name", dataType: "String", hAlign: "left", vAlign: "center"},
+            {headerName:"计量单位",headerWidth:80,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"单价",headerWidth:80,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
+            {headerName:"消耗量",headerWidth:80,dataCode:"consumeAmt", dataType: "Number", formatter: "0.000", hAlign: "right", vAlign: "center"}
+        ],
+        view: {
+            lockedCells:[1, 2, 3]
+        }
+    },
+    buildSheet: function(container) {
+        let me = gljComponentOprObj;
+        me.workBook = sheetOpr.buildSheet(container, me.setting, 30, me);
+        me.workBook.getSheet(0).setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
+        me.workBook.getSheet(0).setFormatter(-1, 0, "@", GC.Spread.Sheets.SheetArea.viewport);
+        me.workBook.getSheet(0).options.isProtected = true;
+        sheetOpr.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
+
+        me.onContextmenuOpr();
+        /*me.gljComponentDelOpr();
+        me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
+        me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
+        me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditStarting, me.onCellEditStart);
+        me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);*/
+
+    },
+    getRowData: function (sheet, row, setting) {
+        let rst = {};
+        for(let i = 0; i < setting.header.length; i++){
+            rst[setting.header[i].dataCode] = sheet.getValue(row, i);
+        }
+        return rst;
+    },
+    getComponent: function (sheet, rowCount) {
+        let component = [];
+        for(let row = 0; row < rowCount; row++){
+            let obj = {};
+            obj.consumeAmt = sheet.getValue(row, 4);
+            obj.ID = sheet.getTag(row, 0);
+            component.push(obj);
+        }
+        return component;
+    },
+    onContextmenuOpr: function () {
+        let me = gljComponentOprObj, that = repositoryGljObj, co = componentOprObj;
+        $.contextMenu({
+            selector: '#gljComponentSheet',
+            build: function($triggerElement, e){
+                //控制允许右键菜单在哪个位置出现
+                let clientX = e.originalEvent.clientX,
+                    clientY = e.originalEvent.clientY;
+                let sheet = me.workBook.getSheet(0);
+                let offset = $("#gljComponentSheet").offset(),
+                    x = clientX - offset.left,
+                    y = clientY - offset.top;
+                let target = sheet.hitTest(x, y);
+                if(target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
+                    sheet.setActiveCell(target.row, target.col);
+                    //控制按钮是否可用
+                    let insertDis = false,
+                        delDis = false;
+                    if(me.isLocked){
+                        insertDis = true;
+                        delDis = true;
+                    }
+                    if(typeof that.currentComponent !== 'undefined' && target.row >= that.currentComponent.length){//右键定位在有组成物的行,删除键才显示可用
+                        delDis = true;
+                    }
+                    return {
+                        callback: function(){},
+                        items: {
+                            "insert": {name: "插入", disabled: insertDis, callback: function (key, opt) {
+                                //默认radio所有工料机
+                                co.initRadio();
+                                //默认点击树根节点
+                                if(co.rootNode){
+                                    co.treeObj.selectNode(co.rootNode);
+                                    componentTypeTreeOprObj.onClick(null, 'componentTree', co.rootNode);
+                                }
+                                //弹出窗口
+                                $('#componentBtn').click();
+                            }},
+                            "delete": {name: "删除", disabled: delDis}
+                        }
+                    };
+                }
+                else{
+                    return false;
+                }
+            }
+        });
+    },
+    gljComponentDelOpr: function () {
+        let me = gljComponentOprObj, that = repositoryGljObj, updateArr = [], removeArr = [], isUpdate = false, updateBasePrc= [];
+        me.workBook.commandManager().register('gljComponentDel', function () {
+            let sels = me.workBook.getSheet(0).getSelections();
+            if(sels.length > 0 && that.currentComponent.length > 0){
+                let component = that.currentGlj.component;
+                for(let i = 0; i < sels.length > 0; i++){
+                    if(sels[i].colCount === me.setting.header.length){//可删除
+                        for(let j = 0; j < sels[i].rowCount; j++){
+                            if(sels[i].row + j < that.currentComponent.length){
+                                removeArr.push(that.currentComponent[sels[i].row + j].ID);
+
+                            }
+                        }
+                    }
+                    else if(sels[i].col === 0){
+                            //编码不可为空
+                            alert("编码不可为空!");
+
+                    }
+                    else if(sels[i].col === 4){//消耗量修改为0
+                        if(sels[i].row === -1){//全修改
+                           for(let j = 0; j < that.currentComponent.length; j++){
+                               isUpdate = true;
+                               that.currentComponent[j].consumeAmt = 0;
+                               for(let k = 0; k < component.length; k++){
+                                   if(component[k].ID === that.currentComponent[j].ID){
+                                       component[k].consumeAmt = 0;
+                                       break;
+                                   }
+                               }
+                           }
+                        }
+                        else{//部分修改
+                            for(let j = 0; j < sels[i].rowCount; j++){
+                                if(sels[i].row + j < that.currentComponent.length){
+                                    isUpdate = true;
+                                    that.currentComponent[sels[i].row + j].consumeAmt = 0;
+                                    for(let k = 0; k < component.length; k++){
+                                        if(component[k].ID === that.currentComponent[sels[i].row + j].ID){
+                                            component[k].consumeAmt = 0;
+                                            break;
+                                        }
+                                    }
+
+                                }
+                            }
+                        }
+                    }
+                }
+                if(removeArr.length > 0 || isUpdate){
+                    for(let i = 0; i < removeArr.length; i++){
+                        for(let j = 0; j < that.currentComponent.length; j++){
+                            if(that.currentComponent[j].ID === removeArr[i]){
+                                that.currentComponent.splice(j--, 1);
+                            }
+                        }
+                        for(let j = 0; j < component.length; j++){
+                            if(component[j].ID === removeArr[i]){
+                                component.splice(j--, 1);
+                            }
+                        }
+                    }
+                    //重新计算工料机
+                    let gljBasePrc = me.reCalGljBasePrc(that.currentComponent);
+                    if(gljBasePrc !== that.currentGlj.basePrice){
+                        that.currentGlj.basePrice = gljBasePrc;
+                        that.reshowGljBasePrc(that.currentGlj);
+                        updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                    }
+                    updateArr.push(that.currentGlj);
+                    me.updateComponent(updateArr);
+                    if(updateBasePrc.length > 0){
+                        that.updateRationBasePrcRq(updateBasePrc);
+                    }
+                }
+            }
+        });
+        me.workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
+        me.workBook.commandManager().setShortcutKey('gljComponentDel', GC.Spread.Commands.Key.del, false, false, false, false);
+    },
+    onCellEditStart: function(sender, args) {
+        let me = gljComponentOprObj, that = repositoryGljObj;
+        let rObj = me.getRowData(args.sheet, args.row, me.setting);
+        me.currentEditingComponent = rObj;
+    },
+    onCellEditEnd: function (sender, args) {
+        let me = gljComponentOprObj, that = repositoryGljObj, updateBasePrc = [];
+        let gljList = that.gljList, updateArr = [], materialComponent = [202, 203, 204], machineComponent = [302, 303];
+        if(args.editingText !== me.currentEditingComponent.code){
+            if(args.col === 0 && args.editingText && args.editingText.trim().length > 0){
+                let component = that.currentGlj.component, hasCode = false;
+                for(let i = 0; i < gljList.length; i++){
+                    if(gljList[i].code === args.editingText){//有效的组成物
+                        hasCode = true;
+                        if((materialComponent.indexOf(that.currentGlj.gljType) !== -1 && gljList[i].gljType === 201)
+                            || (that.currentGlj.gljType === 301 && machineComponent.indexOf(gljList[i].gljType) !== -1 )){//普通材料
+                            //是否与原有组成物不同
+                            let isExist = false;
+                            for(let j = 0; j < component.length; j++){
+                                if(component[j].ID === gljList[i].ID){
+                                    isExist = true;
+                                    break;
+                                }
+                            }
+                            if(!isExist){
+                                let rObj = {};
+                                rObj.ID = gljList[i].ID;
+                                //rObj.basePrice = gljList[i].basePrice;
+                                if(typeof that.currentComponent[args.row] !== 'undefined'){
+                                    rObj.consumeAmt = that.currentComponent[args.row].consumeAmt;
+                                    let index;
+                                    for(let j = 0; j < component.length; j++){
+                                        if(component[j].ID === that.currentComponent[args.row].ID){
+                                            index = j;
+                                            break;
+                                        }
+                                    }
+                                    component.splice(index, 1);
+                                    component.splice(index, 0, rObj);
+                                    //计算工料机单价
+                                    let gljBasePrc = me.reCalGljBasePrc(that.getCurrentComponent(component));
+                                    if(gljBasePrc !== that.currentGlj.basePrice){
+                                        that.currentGlj.basePrice = gljBasePrc;
+                                        that.reshowGljBasePrc(that.currentGlj);
+                                        //工料机单价改变,重算引用了该工料机的定额单价
+                                        updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                                    }
+                                    updateArr.push(that.currentGlj);
+                                }
+                                else{
+                                    rObj.consumeAmt = 0;
+                                    component.push(rObj);
+                                    //计算工料机单价
+                                    let gljBasePrc = me.reCalGljBasePrc(that.getCurrentComponent(component));
+                                    if(gljBasePrc !== that.currentGlj.basePrice){
+                                        that.currentGlj.basePrice = gljBasePrc;
+                                        that.reshowGljBasePrc(that.currentGlj);
+                                        //工料机单价改变,重算引用了该工料机的定额单价
+                                        updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                                    }
+                                    updateArr.push(that.currentGlj);
+                                }
+                                break;
+                            }
+                            else{
+                                //已存在
+                                alert("已存在!");
+                                args.sheet.setValue(args.row, args.col, me.currentEditingComponent[me.setting.header[args.col].dataCode] ?
+                                    me.currentEditingComponent[me.setting.header[args.col].dataCode]: '');
+                            }
+
+                        }
+                        else{
+                            if(materialComponent.indexOf(that.currentGlj.gljType) === 1){
+                                alert("该组成物只能是普通材料!");
+                            }
+                            else if(that.currentGlj.gljType === 301){
+                                alert("该组成物只能是机械组成物或机上人工!")
+                            }
+                            args.sheet.setValue(args.row, args.col, me.currentEditingComponent[me.setting.header[args.col].dataCode] ?
+                                me.currentEditingComponent[me.setting.header[args.col].dataCode]: '');
+                            //无效
+                        }
+                    }
+                }
+                if(!hasCode){
+                    alert("不存在此工料机,请先添加!");
+                    args.sheet.setValue(args.row, args.col, me.currentEditingComponent[me.setting.header[args.col].dataCode] ?
+                        me.currentEditingComponent[me.setting.header[args.col].dataCode] : '');
+                    //不存在
+                }
+            }
+            else if(args.col === 4 && me.currentEditingComponent.code && args.editingText && args.editingText.trim().length > 0){//消耗量
+                let consumeAmt = parseFloat(args.editingText);
+                if(!isNaN(consumeAmt) && consumeAmt !== me.currentEditingComponent.consumeAmt){
+                    let roundCons = me.round(consumeAmt, 3);
+                    let component = that.currentGlj.component;
+                    for(let i = 0; i < component.length; i++){
+                        if(component[i].ID === that.currentComponent[args.row].ID){
+                            component[i].consumeAmt = roundCons;
+                        }
+                    }
+                    that.currentComponent[args.row].consumeAmt = roundCons;
+                    //计算工料机单价
+                    let gljBasePrc = me.reCalGljBasePrc(that.currentComponent);
+                    if(gljBasePrc !== that.currentGlj.basePrice){
+                        that.currentGlj.basePrice = gljBasePrc;
+                        that.reshowGljBasePrc(that.currentGlj);
+                        //工料机单价改变,重算引用了该工料机的定额单价
+                        updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                    }
+                    updateArr.push(that.currentGlj);
+                }
+                else{
+                    //只能输入数值
+                    args.sheet.setValue(args.row, args.col, me.currentEditingComponent[me.setting.header[args.col].dataCode] ?
+                        me.currentEditingComponent[me.setting.header[args.col].dataCode]: 0);
+
+                }
+            }
+            else{
+                args.sheet.setValue(args.row, args.col, '');
+            }
+        }
+        if(updateArr.length > 0){
+            me.updateComponent(updateArr);
+            if(updateBasePrc.length > 0){
+                that.updateRationBasePrcRq(updateBasePrc)
+            }
+        }
+    },
+    onClipboardPasting: function (sender, info) {
+        let me = gljComponentOprObj;
+        let maxCol = info.cellRange.col + info.cellRange.colCount - 1;
+        //复制的列数超过正确的列数,不可复制
+        if(maxCol >= me.setting.header.length){
+            args.cancel = true;
+        }
+    },
+    onClipboardPasted: function (sender, info) {
+        let me = gljComponentOprObj, that = repositoryGljObj, updateArr = [] ,materialComponent = [202, 203, 204], machineComponent = [302, 303],
+            component = that.currentGlj.component, newComponent = [], concatComponent = [], isChange = false, updateBasePrc = [];
+        let items = sheetOpr.analyzePasteData(me.setting, info);
+        let gljCache = that.gljList;
+        if(info.cellRange.col === 0){
+            for(let i = 0; i < items.length; i++){
+                for(let j = 0; j < gljCache.length; j++){
+                    if(items[i].code === gljCache[j].code){
+                        if((materialComponent.indexOf(that.currentGlj.gljType) !== -1 && gljCache[j].gljType === 201)
+                            || (that.currentGlj.gljType === 301 && machineComponent.indexOf(gljCache[j].gljType) !== -1 )){
+                            //是否与原有组成物不同
+                            let isExist = false;
+                            for(let k = 0; k < component.length; k++){
+                                if(component[k].ID === gljCache[j].ID){
+                                    isExist = true;
+                                    me.workBook.getSheet(0).setValue(info.cellRange.row + i, info.cellRange.col,
+                                        typeof that.currentComponent[info.cellRange.row + i] !== 'undefined'? that.currentComponent[info.cellRange.row + i].code : '');
+                                    break;
+                                }
+                            }
+                            if(!isExist){
+                                isChange = true;
+                                let obj = {};
+                                obj.ID = gljCache[j].ID;
+                                if(typeof that.currentComponent[info.cellRange.row + i] !== 'undefined'){//更新
+                                    obj.consumeAmt = that.currentComponent[info.cellRange.row + i].consumeAmt;
+                                    let index;
+                                    for(let k = 0; k < component.length; k++){
+                                        if(that.currentComponent[info.cellRange.row + i].ID === component[k].ID){
+                                            index = k;
+                                            break;
+                                        }
+                                    }
+                                    component.splice(index, 1);
+                                    component.splice(index, 0, obj);
+                                }
+                                else{//新增
+                                    obj.consumeAmt = 0;
+                                    component.push(obj);
+                                }
+                                break;
+                            }
+
+                        }
+                        else{
+                            me.workBook.getSheet(0).setValue(info.cellRange.row + i, info.cellRange.col,
+                            typeof that.currentComponent[info.cellRange.row + i] !== 'undefined'? that.currentComponent[info.cellRange.row + i].code : '');
+
+                        }
+
+                    }
+                    else{
+                        me.workBook.getSheet(0).setValue(info.cellRange.row + i, info.cellRange.col,
+                            typeof that.currentComponent[info.cellRange.row + i] !== 'undefined'? that.currentComponent[info.cellRange.row + i].code : '');
+                    }
+                }
+            }
+            if(isChange){
+                //计算工料机单价
+                let gljBasePrc = me.reCalGljBasePrc(that.getCurrentComponent(component));
+                if(gljBasePrc !== that.currentGlj.basePrice){
+                    that.currentGlj.basePrice = gljBasePrc;
+                    that.reshowGljBasePrc(that.currentGlj);
+                    updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                }
+                updateArr.push(that.currentGlj);
+            }
+        }
+        else if(info.cellRange.col === 4){
+            let items = sheetOpr.analyzePasteData(me.setting, info);
+            let row = info.cellRange.row;
+            for(let i = 0; i < items.length; i++){
+                if(row + i < that.currentComponent.length){
+                    let currentObj = that.currentComponent[row + i];
+                    if(items[i].consumeAmt.trim().length > 0 && items[i].consumeAmt !== currentObj.consumeAmt){
+                        let roundCons = me.round(items[i].consumeAmt, 3);
+                        isChange = true;
+                        currentObj.consumeAmt = roundCons;
+                        for(let j = 0; j < component.length; j++){
+                            if(component[j].ID === currentObj.ID){
+                                component[j].consumeAmt = currentObj.consumeAmt;
+                                break;
+                            }
+                        }
+                    }
+                    else{
+                        me.workBook.getSheet(0).setValue(row + i, info.cellRange.col, currentObj.consumeAmt);
+                    }
+                }
+                else{
+                    me.workBook.getSheet(0).setValue(row + i, info.cellRange.col, '');
+                }
+            }
+            if(isChange){
+                //计算工料机单价
+                let gljBasePrc = me.reCalGljBasePrc(that.currentComponent);
+                if(gljBasePrc !== that.currentGlj.basePrice){
+                    that.currentGlj.basePrice = gljBasePrc;
+                    that.reshowGljBasePrc(that.currentGlj);
+                    updateBasePrc.push({gljId: that.currentGlj.ID, gljType: that.currentGlj.gljType, basePrice: that.currentGlj.basePrice});
+                }
+                updateArr.push(that.currentGlj);
+            }
+        }
+        if(updateArr.length > 0){
+            me.updateComponent(updateArr);
+            if(updateBasePrc.length > 0){
+                that.updateRationBasePrcRq(updateBasePrc);
+            }
+        }
+    },
+    updateComponent: function (updateArr) {
+        let me = gljComponentOprObj, that = repositoryGljObj;
+        $.ajax({
+            type: 'post',
+            url: 'api/updateComponent',
+            data: {libId: pageOprObj.gljLibId, updateArr: updateArr, oprtor: userAccount},
+            dataType: 'json',
+            success: function (result) {
+                if(result.data.length > 0){
+                    if(result.data[0]){
+                        that.currentComponent =  that.getCurrentComponent(result.data[0].component);
+                        sheetOpr.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
+                        sheetOpr.showData(me.workBook.getSheet(0), me.setting, that.currentComponent);
+                    }
+                }
+            }
+        })
+    },
+    round: function (v, e) {
+        let t=1;
+        for(;e>0;t*=10,e--);
+        for(;e<0;t/=10,e++);
+        return Math.round(v*t)/t;
+    },
+    reCalGljBasePrc: function (component) {
+        let me = gljComponentOprObj, gljBasePrc = 0;
+        for(let i = 0; i < component.length; i++){
+            let roundBasePrc = me.round(component[i].basePrice, 2);
+            gljBasePrc += me.round(roundBasePrc * component[i].consumeAmt, 2);
+        }
+        return gljBasePrc;
+    }
+};

+ 354 - 0
web/building_saas/complementary_glj_lib/js/sheetOpr.js

@@ -0,0 +1,354 @@
+/**
+ * Created by Zhong on 2017/8/24.
+ */
+let sheetOpr = {
+    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;
+    },
+
+    initSheet: function(sheet, setting, rowCount) {
+        var me = this;
+        var spreadNS = GC.Spread.Sheets;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        sheet.setRowCount(1, spreadNS.SheetArea.colHeader);
+        sheet.setColumnCount(setting.header.length, spreadNS.SheetArea.viewport);
+        sheet.options.colHeaderAutoTextIndex = 1;
+        sheet.options.colHeaderAutoText = spreadNS.HeaderAutoText.numbers;
+        sheet.showRowOutline(false);
+        me.buildHeader(sheet, setting);
+        if (rowCount > 0) sheet.setRowCount(rowCount);
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    },
+
+    buildSheet: function(container, setting, rowCount) {
+        var me = this;
+        var spreadBook = new GC.Spread.Sheets.Workbook(container, { sheetCount: 1 });
+        spreadBook.options.tabStripVisible = false;
+        spreadBook.options.showHorizontalScrollbar = false;
+        spreadBook.options.scrollbarMaxAlign = true;
+        spreadBook.options.allowCopyPasteExcelStyle = false;
+        spreadBook.options.allowExtendPasteRange = true;
+        var spreadNS = GC.Spread.Sheets;
+        var sheet = spreadBook.getSheet(0);
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        //Set rowHeader count and columnHeader count.
+        sheet.setRowCount(1, spreadNS.SheetArea.colHeader);
+        sheet.setColumnCount(setting.header.length, spreadNS.SheetArea.viewport);
+        sheet.options.colHeaderAutoTextIndex = 1;
+        sheet.options.colHeaderAutoText = spreadNS.HeaderAutoText.numbers;
+        sheet.showRowOutline(false);
+        //setup column header
+        me.buildHeader(sheet, setting);
+        //setup cells
+        if (rowCount > 0) sheet.setRowCount(rowCount);
+        sheet.resumeEvent();
+        sheet.resumePaint();
+        return spreadBook;
+    },
+    buildHeader: function(sheet, setting){
+        var me = this, ch = GC.Spread.Sheets.SheetArea.colHeader;
+        for (var i = 0; i < setting.header.length; i++) {
+            sheet.setValue(0, i, setting.header[i].headerName, ch);
+            sheet.setColumnWidth(i, setting.header[i].headerWidth?setting.header[i].headerWidth:100);
+        }
+    },
+    cleanSheet: function(sheet, setting, rowCount) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        sheet.clear(-1, 0, -1, setting.header.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
+        if (rowCount > 0) sheet.setRowCount(rowCount);
+        sheet.clearSelection();
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    },
+    setAreaAlign: function(area, hAlign, vAlign){
+        if (!(hAlign) || hAlign === "left") {
+            area.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+        } else if (hAlign === "right") {
+            area.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+        } else if (hAlign === "center") {
+            area.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
+        } else {
+            area.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+        }
+        if (!(vAlign) || vAlign === "center") {
+            area.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+        } else if (vAlign === "top") {
+            area.vAlign(GC.Spread.Sheets.VerticalAlign.top);
+        } else if (vAlign === "bottom") {
+            area.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
+        } else {
+            area.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+        }
+    },
+    showData: function(sheet, setting, data, distTypeTree) {
+        var me = this, ch = GC.Spread.Sheets.SheetArea.viewport;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        let checkBoxType = new GC.Spread.Sheets.CellTypes.CheckBox();
+        if(typeof setting.owner !== 'undefined' && setting.owner === 'gljComponent'){
+            sheet.setRowCount(data.length + 5);
+        }
+        else{
+            sheet.setRowCount(typeof repositoryGljObj !== 'undefined' && repositoryGljObj.currentOprParent === 1 ? data.length : data.length + 10);
+        }
+        if(data.length === 0){
+            for(let i = 0; i < sheet.getRowCount(); i++){
+                sheet.getCell(i, 4, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+            }
+        }
+        for (var col = 0; col < setting.header.length; col++) {
+            var hAlign = "left", vAlign = "center";
+            if (setting.header[col].hAlign) {
+                hAlign = setting.header[col].hAlign;
+            } else if (setting.header[col].dataType !== "String"){
+                hAlign = "right";
+            }
+            vAlign = setting.header[col].vAlign?setting.header[col].vAlign:vAlign;
+            me.setAreaAlign(sheet.getRange(-1, col, -1, 1), hAlign, vAlign);
+            if (setting.header[col].formatter) {
+                sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
+            }
+            for (var row = 0; row < data.length; row++) {
+                //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);
+                if(setting.header[col].dataCode === 'gljType' && data[row].gljType){
+                    if(typeof repositoryGljObj !== 'undefined' && typeof repositoryGljObj.allowComponent !== 'undefined' && repositoryGljObj.allowComponent.indexOf(data[row].gljType) !== -1){
+                        sheet.getCell(row, 4, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+                    }
+                    else if(typeof repositoryGljObj !== 'undefined' && typeof repositoryGljObj.allowComponent !== 'undefined' && repositoryGljObj.allowComponent.indexOf(data[row].gljType) === -1){
+                        sheet.getCell(row, 4, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+                    }
+                    let distTypeVal =  distTypeTree.distTypes[distTypeTree.prefix + data[row].gljType].data.fullName;
+                    sheet.setValue(row, col, distTypeVal, ch);
+                }
+                else {
+                    sheet.setValue(row, col, data[row][setting.header[col].dataCode], ch);
+                    sheet.setTag(row, 0, data[row].ID, ch);
+                }
+                //复选框
+                if(setting.header[col].dataCode === 'isComplementary'){
+                    sheet.setCellType(row, col, checkBoxType);
+                    sheet.getCell(row, col).value(1);
+                }
+                //新增组成物表,选择
+                if(setting.header[col].dataCode === 'select'){
+                    sheet.setCellType(row, col, checkBoxType);
+                    sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+                    if(data[row].isChecked === true){
+                        console.log(1);
+                        sheet.getCell(row, col).value(1);
+                    }
+                    else if(data[row].isChecked === false){
+                        console.log(2);
+                        sheet.getCell(row, col).value('');
+                    }
+                }
+            }
+            for(let i = data.length; i < sheet.getRowCount(); i++){
+                sheet.setCellType(i, 6, null);
+                sheet.getCell(i, 4, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+            }
+        }
+        sheet.resumeEvent();
+        sheet.resumePaint();
+        //me.shieldAllCells(sheet);
+    },
+    analyzePasteData: function(setting, pastedInfo) {
+        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 = pastedInfo.cellRange.col;
+                preStrIdx = i + 1;
+                rst.push(itemObj);
+                if (i < pastedInfo.pasteData.text.length - 1) {
+                    itemObj = {};
+                }
+            } else if (pastedInfo.pasteData.text[i] === "\t" || pastedInfo.pasteData.text[i] === "\r") {
+                itemObj[setting.header[propId].dataCode] = pastedInfo.pasteData.text.slice(preStrIdx, i);
+                propId++;
+                preStrIdx = i + 1;
+                //if the last copied-cell were empty, should check whether the end of text
+                if (i == pastedInfo.pasteData.text.length - 1) {
+                    itemObj[setting.header[propId].dataCode] = pastedInfo.pasteData.text.slice(preStrIdx);
+                    rst.push(itemObj);
+                }
+            } else if (i == pastedInfo.pasteData.text.length - 1) {
+                itemObj[setting.header[propId].dataCode] = pastedInfo.pasteData.text.slice(preStrIdx);
+                rst.push(itemObj);
+            }
+        }
+        return rst;
+    },
+    combineRowData: function(sheet, setting, row, repositoryGljObj) {
+        let me = this;
+        var rst = {};
+        let comboBoxCellType = sheet.getCellType(row, 5);
+        let items = comboBoxCellType.items();
+        for (var col = 0; col < setting.header.length; col++) {
+            if(setting.header[col].dataCode === 'gljType'){
+                items.forEach(function(item){
+                    if(sheet.getValue(row, col) === item.text){
+                        rst[setting.header[col].dataCode] = item.value;
+                        if(repositoryGljObj){
+                            rst.shortName = repositoryGljObj.distTypeTree.distTypes[repositoryGljObj.distTypeTree.prefix + item.value].data.shortName;
+                        }
+                    }
+                });
+            }
+            else if (setting.header[col].dataCode === 'code'){
+                if(repositoryGljObj){
+                    let gljList = repositoryGljObj.gljList,
+                        orgCode = repositoryGljObj.orgCode,
+                        isExist = false;
+                    for(let i=0; i< gljList.length; i++){
+                        if(gljList[i].code === sheet.getValue(row, col) && sheet.getValue(row, col)!== orgCode){
+                            me.lockAllCells(sheet);
+                            $('#alertText').text("输入的编号已存在,请重新输入!");
+                            $('#codeAlertBtn').click();
+                            $('#codAleConfBtn').click(function () {
+                                // me.reLockSomeCodes(sheet, 0, repositoryGljObj.currentCache.length);
+                                me.unLockAllCells(sheet);
+                                me.reLockSomeCodes(sheet, 0, repositoryGljObj.currentCache.length);
+                                sheet.setValue(row, 0, orgCode);
+                                sheet.setActiveCell(row, 0);
+                            });
+                            $('#codAleClose').click(function () {
+                                //me.reLockSomeCodes(sheet, 0, repositoryGljObj.currentCache.length);
+                                me.unLockAllCells(sheet);
+                                me.reLockSomeCodes(sheet, 0, repositoryGljObj.currentCache.length);
+                                sheet.setValue(row, 0, orgCode);
+                                sheet.setActiveCell(row, 0);
+                            });
+                            // sheet.setValue(row, col, orgCode);
+                            isExist = true
+                        }
+                    }
+                    if(!isExist){
+                        rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+                    }
+                }
+                else{
+                    rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+                }
+            }
+            else{
+                rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+            }
+        }
+        return rst;
+    },
+    combineRationRowData: function(sheet, setting, row) {
+        var rst = {};
+        for (var col = 0; col < setting.header.length; col++) {
+            rst[setting.header[col].dataCode] = sheet.getValue(row, col);
+        }
+        return rst;
+    },
+    shieldAllCells: function(sheet) {
+        sheet.options.isProtected = true;
+    },
+    unShieldAllCells: function(sheet) {
+        sheet.options.isProtected = false;
+    },
+    reLockSomeCodes: function (sheet, beginRow, endRow) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        let unLockStyle = new GC.Spread.Sheets.Style();
+        unLockStyle.locked = false;
+        let lockStyle = new GC.Spread.Sheets.Style();
+        lockStyle.locked = true;
+        for(let row = beginRow; row < endRow; row++){
+            sheet.setStyle(row, 0, lockStyle);
+        }
+        for(let row = endRow; row < sheet.getRowCount(); row++){
+            sheet.setStyle(row, 0, unLockStyle);
+        }
+        sheet.options.isProtected = true;
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    unLockAllCells: function (sheet) {
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        sheet.setStyle(-1, 0, defaultStyle);
+        sheet.options.isProtected = false;
+    },
+    lockAllCells: function (sheet) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = true;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        for(let i = 0; i < sheet.getRowCount(); i++){
+            sheet.setStyle(i, 0, defaultStyle);
+        }
+        sheet.options.isProtected = true;
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    lockSomeCodes: function (sheet, beginRow, endRow) {
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        let style = new  GC.Spread.Sheets.Style();
+        style.locked = true;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        for(let i = beginRow; i < endRow; i++){
+            sheet.setStyle(i, 0, style);
+        }
+        sheet.options.isProtected = true;
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    lockCodeCells: function (sheet, rowCount) {
+        let sheetRowCount = sheet.getRowCount();
+        let defaultStyle = new GC.Spread.Sheets.Style();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
+        let style = new GC.Spread.Sheets.Style();
+        style.locked = true;
+        sheet.setStyle(-1, 0, style);
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        for(let i =rowCount; i<sheetRowCount; i++){
+            sheet.setStyle(i, -1, style);
+        }
+        sheet.options.isProtected = true;
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    lockCells: function(sheet, setting){
+        if (setting && setting.view.lockColumns && setting.view.lockColumns.length > 0) {
+            sheet.options.isProtected = true;
+            sheet.getRange(-1, 0, -1, setting.header.length, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+            for (var i = 0; i < setting.view.lockColumns.length; i++) {
+                sheet.getRange(-1,setting.view.lockColumns[i] , -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+            }
+        }
+    },
+    chkIfEmpty: function(rObj, setting) {
+        var rst = true;
+        if (rObj) {
+            for (var i = 0; i < setting.header.length; i++) {
+                if (rObj[setting.header[i].dataCode]) {
+                    rst = false;
+                    break;
+                }
+            }
+        }
+        return rst;
+    }
+}

文件差异内容过多而无法显示
+ 487 - 451
web/building_saas/pm/html/project-management.html


文件差异内容过多而无法显示
+ 706 - 467
web/building_saas/pm/js/pm_main.js


+ 629 - 0
web/building_saas/pm/js/pm_main_bak.js

@@ -0,0 +1,629 @@
+/**
+ * Created by Mai on 2017/2/24.
+ */
+
+var Tree = null, movetoZTree = null, copytoZTree = null;
+var ProjTreeSetting = {
+    tree: {
+        id: 'ID',
+        pid: 'ParentID',
+        nid: 'NextSiblingID',
+        btnColumn: 1,
+        nullId: -1
+    },
+    columns: [
+        {
+            head: '',
+            data: '',
+            width: '40',
+            event: {}
+        },
+        {
+            head: '工程列表',
+            data: 'name',
+            width: '78%',
+            event: {
+                getText: function (html, node, text) {
+                    html.push((node && node.data && node.data.projType === 'Folder') ? '&nbsp;' : '');
+                    html.push('<a ');
+                    if (node && node.data && node.data.projType === 'Tender') {
+                        //html.push('href="/main?project=', node.id(), '"');
+                        html.push('href="javacript:void(0);"');
+                    }
+                    html.push('>', text, '<a>');
+                },
+                getIcon: function (html, node) {
+                    if (node.data.projType === 'Folder') {
+                        html.push('<i class ="tree-icon fa fa-folder-open-o"></i>');
+                    } else {
+                        html.push('<span class="poj-icon">└</span>');
+                    }
+                },
+                tdBindEvent: function (td, node) {
+                    if (node.data.projType === 'Tender') {
+                        $('a:eq(1)', td).bind('click', function () {
+                            BeforeOpenProject(node.id(), {'fullFolder': GetFullFolder(node.parent)}, function () {
+                                window.location.href = '/main?project=' + node.id();
+                            });
+                            return false;
+                        });
+                    }
+                }
+            }
+        },
+        {
+            head: '最近使用',
+            data: 'lastDateTime',
+            width: '10%',
+            event: {
+                getText: function (html, node, text) {
+                    if (node.data.projType === 'Tender') {
+                        html.push(text ? new Date(text).Format('yyyy-MM-dd') : '');
+                    }
+                }
+            }
+        },
+        {
+            head: '创建日期',
+            data: 'createDateTime',
+            width: '10%',
+            event: {
+                getText: function (html, node, text) {
+                    if (node.data.projType === 'Tender') {
+                        html.push(text ? new Date(text).Format('yyyy-MM-dd') : '');
+                    }
+                }
+            }
+        }
+    ],
+    viewEvent: {
+        beforeSelect: function (node) {
+            if (node && node.row) {
+                $('td:eq(0)', node.row).children().remove();
+            }
+        },
+        onSelectNode: function (node) {
+            // 新建文件夹 是否可见
+            if (node.data.projType === 'Tender') {
+                $('#addFolderBtn').hide();
+            } else {
+                $('#addFolderBtn').show();
+            }
+            // 重命名可见
+            $('#renameBtn').show();
+            // 删除可见
+            $('#delBtn').show();
+            // 移动到、复制到、共享、协同 是否可见
+            if (node.data.projType === 'Tender') {
+                $('#movetoBtn').show();
+                $('#copytoBtn').show();
+                $('#shareBtn').show();
+                $('#cooperateBtn').show();
+            } else {
+                $('#movetoBtn').hide();
+                $('#copytoBtn').hide();
+                $('#shareBtn').hide();
+                $('#cooperateBtn').hide();
+            }
+            $('td:eq(0)', node.row).append($('<i class="fa fa-sort" data-toggle="tooltip" data-placement="top" title="长安拖动"></i>'));
+        }
+    }
+}
+// 从服务器拉取数据
+var LoadProjTree = function () {
+    var table = $('#ProjTree');
+    $('thead', table).remove();
+    $('tbody', table).remove();
+    GetAllProjectData(function (data) {
+        Tree = $.fn.treeTable.init(table, ProjTreeSetting, data);
+    });
+};
+
+var GetNeedUpdatePreNode = function (parent, next) {
+    if (next) {
+        return next.preSibling();
+    } else if (parent) {
+        return parent.firstChild();
+    } else {
+        return null;
+    }
+    /*if (parent && parent.id() !== -1) {
+        if (next && next.preSibling()) {
+            return next.preSibling();
+        } else {
+            return parent.lastChild();
+        }
+    } else {
+        return null;
+    }*/
+};
+var GetPreNodeUpdateData = function (pre, nid) {
+    var data = {};
+    data['updateType'] = 'update';
+    data['updateData'] = {};
+    data.updateData[Tree.setting.tree.id] = pre.id();
+    data.updateData[Tree.setting.tree.id] = nid;
+    return data;
+}
+// 获取新建项目数据
+var GetAddProjUpdateData = function (parent, next, name, newId) {
+    var datas = [], updateData, pre;
+    updateData = {};
+    updateData['updateType'] = 'new';
+    updateData['updateData'] = {};
+    updateData['updateData'][Tree.setting.tree.id] = newId;
+    updateData['updateData'][Tree.setting.tree.pid] = parent ? parent.id() : -1;
+    updateData['updateData'][Tree.setting.tree.nid] = next ? next.id() : -1;
+    updateData['updateData']['name'] = name;
+    updateData['updateData']['projType'] = 'Tender';
+    datas.push(updateData);
+    return datas;
+};
+var GetAddFolderProjUpdateData = function (parent, next, folderName1, folderName2, name, newId) {
+    var datas = [], updateData, folderData1, folderData2, pre;
+    var addUpdateData = function (parentId, nextId, name, projType) {
+        var data = {};
+        data['updateType'] = 'new';
+        data['updateData'] = {};
+        data['updateData'][Tree.setting.tree.id] = newId;
+        data['updateData'][Tree.setting.tree.pid] = parentId;
+        data['updateData'][Tree.setting.tree.nid] = nextId;
+        data['updateData']['name'] = name;
+        data['updateData']['projType'] = projType;
+        newId += 1;
+        datas.push(data);
+        return data;
+    }
+    folderData1 = addUpdateData(parent.id(), next ? next.id() : -1, folderName1, 'Folder');
+    folderData2 = addUpdateData(folderData1.updateData[Tree.setting.tree.id], -1, folderName2, 'Folder');
+    addUpdateData(folderData2.updateData[Tree.setting.tree.id], -1, name, 'Tender');
+    return datas;
+};
+// 获取新建文件夹数据
+var GetAddForlderUpdateData = function (parent, next, folderName, newId) {
+    var datas = [], updateData, pre;
+    updateData = {};
+    updateData['updateType'] = 'new';
+    updateData['updateData'] = {};
+    updateData['updateData'][Tree.setting.tree.id] = newId;
+    updateData['updateData'][Tree.setting.tree.pid] = parent ? parent.id() : -1;
+    updateData['updateData'][Tree.setting.tree.nid] = next ? next.id() : -1;
+    updateData['updateData']['name'] = folderName;
+    updateData['updateData']['projType'] = 'Folder';
+    datas.push(updateData);
+
+    pre = GetNeedUpdatePreNode(parent, next);
+    if (pre) {
+        datas.push(GetPreNodeUpdateData(pre, newId));
+    }
+    return datas;
+};
+
+var GetNextChangeUpdateData = function (datas, node, next) {
+    var data = null;
+    if (node && node.id() !== -1) {
+        data = {};
+        data['updateType'] = 'update';
+        data['updateData'] = {};
+        data['updateData'][Tree.setting.tree.id] = node.id();
+        data['updateData'][Tree.setting.tree.nid] = next ? next.id() : -1;
+        datas.push(data);
+    }
+    return data;
+}
+var GetFullFolder = function (node) {
+    var fullFolder = [],
+        cur = node;
+    while (cur && cur.data) {
+        fullFolder.unshift(cur.data.name);
+        cur = cur.parent;
+    }
+    return fullFolder;
+}
+var GetDeleteUpdateData = function (node) {
+    var datas = [], updateData,
+        pre = node.preSibling(),
+        deleteNodeData = function (node) {
+            var data = {};
+            data['updateType'] = 'delete';
+            data['updateData'] = {};
+            data['updateData'][Tree.setting.tree.id] = node.id();
+            if (node.data.projType === 'Tender') {
+                data['updateData']['FullFolder'] = GetFullFolder(node.parent);
+            }
+            return data;
+        },
+        addDeleteChildren = function (children) {
+            children.forEach(function(child){
+                datas.push(deleteNodeData(child));
+                addDeleteChildren(child.children);
+            });
+        };
+    if (pre && pre.id() !== -1) {
+        updateData = {};
+        updateData['updateType'] = 'update';
+        updateData['updateData'] = {};
+        updateData['updateData'][Tree.setting.tree.id] = pre.id();
+        updateData['updateData'][Tree.setting.tree.nid] = node ? node.nid() : -1;
+        datas.push(updateData);
+    }
+    datas.push(deleteNodeData(node));
+    addDeleteChildren(node.children);
+    return datas;
+};
+
+var GetMoveUpdateData = function (node, parent, next) {
+    var datas = [], updateData;
+    updateData = GetNextChangeUpdateData(datas, node.preSibling(), node.nextSibling);
+    if (next) {
+        updateData = GetNextChangeUpdateData(datas, next.preSibling(), node);
+    }
+    updateData = {};
+    updateData['updateType'] = 'update';
+    updateData['updateData'] = {};
+    updateData['updateData'][Tree.setting.tree.id] = node.id();
+    updateData['updateData'][Tree.setting.tree.pid] = parent ? parent.id() : -1;
+    updateData['updateData'][Tree.setting.tree.nid] = next ? next.id() : -1;
+    datas.push(updateData);
+    return datas;
+};
+
+var GetCopyUpdateData = function (node, parent, next, newId){
+    var datas = [], updateData, pre;
+    updateData = {};
+    updateData['updateType'] = 'copy';
+    updateData['srcProjectId'] = node.id();
+    updateData['updateData'] = {};
+    updateData['updateData'][Tree.setting.tree.id] = newId + 1;
+    updateData['updateData'][Tree.setting.tree.pid] = parent ? parent.id() : -1;
+    updateData['updateData'][Tree.setting.tree.nid] = next ? next.id() : -1;
+    updateData['updateData']['name'] = node.data.name;
+    updateData['updateData']['projType'] = node.data.projType;
+    datas.push(updateData);
+
+    pre = GetNeedUpdatePreNode(parent, next);
+    if (pre) {
+        updateData = {};
+        updateData['updateType'] = 'update';
+        updateData['updateData'] = {};
+        updateData['updateData'][Tree.setting.tree.id] = pre.id();
+        updateData['updateData'][Tree.setting.tree.nid] = node.tree.maxNodeId() + 1;
+        datas.push(updateData);
+    }
+    return datas;
+}
+
+var ConvertTreeToZtree = function (Tree, zTreeObj, filterNode) {
+    var setting = {
+            data: {
+                simpleData: {
+                    enable:true,
+                    idKey: "id",
+                    pIdKey: "pId",
+                    rootPId: "-1"
+                }
+            }},
+        zTreeData = [],
+        exportNodesData = function (nodes) {
+            nodes.forEach(function (node) {
+                if (node !== filterNode) {
+                    var data = {};
+                    data['id'] = node.data[Tree.setting.tree.id];
+                    data['pId'] = node.pid();
+                    data['name'] = node.data['name'];
+                    data['isParent'] = node.data.projType === 'Folder';//(node.data.projType === 'Folder' && node.children.length === 0);
+                    data['open'] = node.data.projType === 'Folder';//node.children.length !== 0;
+                    zTreeData.push(data);
+                    exportNodesData(node.children);
+                }
+            })
+        };
+    exportNodesData(Tree._root.children);
+    return $.fn.zTree.init(zTreeObj, setting, zTreeData);
+};
+var GetTargetTreeNode = function (zTreeObj) {
+    var ztree_selected;
+    if (zTreeObj && Tree) {
+        ztree_selected = zTreeObj.getSelectedNodes().length === 0 ? null : zTreeObj.getSelectedNodes()[0];
+        return ztree_selected ? Tree.findNode(ztree_selected.id) : null;
+    } else {
+        return null;
+    }
+};
+
+var AddFolderChildValid = function (node) {
+    if (node.data.projType === 'Folder') {
+        if (node.children.length === 0) {
+            return true;
+        } else {
+            return (node.firstChild().data.projType === 'Folder');
+        }
+    } else {
+        return false;
+    }
+};
+var AddTenderChildValid = function (node) {
+    if (node.data.projType === 'Folder') {
+        if (node.children.length === 0) {
+            return true;
+        } else {
+            return (node.firstChild().data.projType === 'Tender');
+        }
+    } else {
+        return false;
+    }
+};
+
+LoadProjTree();
+$('#movetoBtn').hide();
+$('#copytoBtn').hide();
+$('#shareBtn').hide();
+$('#cooperateBtn').hide();
+
+// 新建文件夹
+$('#addFolderBtn').click(function () {
+    if (Tree) {
+        $('#addFolder').modal('show');
+    }
+});
+$('#addFolderOk').click(function () {
+    var form = $('#addFolder');
+    var name = $('#folder-name-input').val();
+    var parent, next;
+    if (name) {
+        if (Tree.selected()) {
+            if (Tree.selected().children.length === 0 || Tree.selected().firstChild().data.projType === 'Folder') {
+                parent = Tree.selected();
+                next = Tree.selected().firstChild();
+            } else {
+                parent = Tree.selected().parent;
+                next = Tree.selected().nextSibling;
+            }
+        } else {
+            parent = Tree._root;
+            next = Tree.firstNode();
+        }
+
+        CommonAjax.post('/pm/api/getNewProjectID', {count: 1}, function (IDs) {
+            var updateData = GetAddForlderUpdateData(parent, next, name, IDs.lowID);
+            Tree.maxNodeId(IDs.lowID - 1);
+            UpdateProjectData(updateData, function(datas){
+                datas.forEach(function (data) {
+                    if (data.updateType === 'new') {
+                        Tree.addNodeData(data.updateData, parent, next);
+                    }
+                });
+                form.modal('hide');
+            });
+        });
+    }
+});
+
+// 新建工程
+var AddProj = function () {
+    var name = $('#tenderName').val();
+    if (name !== '') {
+        // if (Tree.selected()){
+        //     if (Tree.selected().data.projType === 'Tender') {
+        //         parent = Tree.selected().parent;
+        //         next = Tree.selected().next;
+        //     } else {
+        //         if (Tree.selected().firstNode.data.projType === 'Tender') {
+        //             parent = Tree.selected();
+        //             next = Tree.selected().firstNode();
+        //         } else {
+        //             return;
+        //         }
+        //     }
+        // } else {
+        //     parent = Tree._root();
+        //     next = Tree.firstNode();
+        // }
+        CommonAjax.post('/pm/api/getNewProjectID', {count: 1}, function (IDs) {
+            var updateData = GetAddProjUpdateData(Tree._root, Tree.firstNode(), name, IDs.lowID);
+            Tree.maxNodeId(IDs.lowID - 1);
+            UpdateProjectData(updateData, function (datas) {
+                datas.forEach(function (data) {
+                    var parent, next;
+                    if (data.updateType === 'new') {
+                        parent = data.updateData.parentId === -1 ?  Tree._root : Tree.findNode(data.updateData.parentId);
+                        next = data.updateData.nextId === -1 ? null : Tree.findNode(data.updateData.nextId);
+                        Tree.addNodeData(data.updateData, parent, next);
+                    }
+                });
+                $('#addProj').modal('hide');
+            });
+        });
+    }
+}
+var AddFolderProj = function () {
+    var nameB = $('#buildName').val(), nameX = $('#xiangName').val(), name = $('#tenderName').val();
+    if (nameB !== '' && nameX !== '' && name !== '') {
+        CommonAjax.post('/pm/api/getNewProjectID', {count: 3}, function (IDs) {
+            var updateData = GetAddFolderProjUpdateData(Tree._root, Tree.firstNode(), nameB, nameX, name, IDs.lowID);
+            Tree.maxNodeId(IDs.lowID - 1);
+            UpdateProjectData(updateData, function (datas) {
+                datas.forEach(function (data) {
+                    var parent, next;
+                    if (data.updateType === 'new') {
+                        parent = data.updateData[Tree.setting.tree.pid] === -1 ?  Tree._root : Tree.findNode(data.updateData[Tree.setting.tree.pid]);
+                        next = data.updateData[Tree.setting.tree.nid] === -1 ? null : Tree.findNode(data.updateData[Tree.setting.tree.nid]);
+                        Tree.addNodeData(data.updateData, parent, next);
+                    }
+                });
+                $('#addProj').modal('hide');
+            });
+        });
+    }
+}
+$('#addProjBtn').click(function () {
+    if (Tree) {
+        $('#addProj').modal('show');
+    }
+});
+$('#addProjOk').click(function () {
+    var hasFolder = $('#isAddFolder>input').is(':checked');
+    if (hasFolder) {
+        AddFolderProj();
+    } else {
+        AddProj();
+    }
+});
+$('#isAddFolder').change(function () {
+    if ($('input',this).is(':checked')) {
+        $('#moreinfo').collapse('show');
+    } else {
+        $('#moreinfo').collapse('hide');
+    }
+});
+
+// 重命名
+$('#renameBtn').click(function() {
+    if (Tree && Tree.selected()) {
+        $('#rename').modal('show');
+    }
+})
+$('#rename').on('show.bs.modal', function () {
+    $('#newName').attr('placeholder', Tree.selected().data.name);
+});
+$('#renameOk').click(function () {
+    var select = Tree.selected(),
+        newName = $('#newName').val(),
+        form = $('#rename');
+    if (select && newName !== select.data.name) {
+        RenameProject(select.id(), newName, function () {
+            form.modal('hide');
+            select.data.name = newName;
+            Tree.refreshNodesDom([select]);
+        });
+    } else {
+        form.modal('hide');
+    }
+});
+
+// 删除
+$('#delBtn').click(function() {
+    if (Tree && Tree.selected()) {
+        $('#del').modal('show');
+    }
+});
+$('#del').on('show.bs.modal', function() {
+    var hasTenderChild = function (children) {
+        var i;
+        for (i = 0; i < children.length; i++) {
+            if (children[i].children.length === 0) {
+                if (children[i].data.projType === 'Tender') {
+                    return true;
+                }
+            } else if (hasTenderChild(children[i].children)) {
+                return true;
+            }
+        }
+        return false;
+    };
+    if (Tree.selected().children.length == 0) {
+        $('#tenderHint').show();
+        $('#tenderHint').text('删除 "' + Tree.selected().data.name +'" ?');
+        $('#folderHint').hide();
+    } else {
+        $('#tenderHint').hide();
+        $('#folderHint').show();
+        $('#folderHint').text('删除 "'+ Tree.selected().data.name +'" 以及它包含的子项?');
+    }
+    if (hasTenderChild([Tree.selected()])) {
+        $('#restoreHint').show();
+    } else {
+        $('#restoreHint').hide();
+    }
+});
+$('#deleteProjOk').click(function () {
+    var updateData, form = $('#del');
+    if (Tree) {
+        updateData = GetDeleteUpdateData(Tree.selected());
+        UpdateProjectData(updateData, function () {
+            form.modal('hide');
+            Tree.removeNode(Tree.selected());
+        });
+    }
+});
+
+// 移动至
+$('#movetoBtn').click(function () {
+    if (Tree && Tree.selected()) {
+        $('#moveto').modal('show');
+    }
+});
+$('#moveto').on('show.bs.modal', function () {
+    movetoZTree = ConvertTreeToZtree(Tree, $('#treeDemo'), Tree.selected());
+});
+$('#movetoOk').click(function () {
+    var updateData, form = $('#moveto'),
+        target = GetTargetTreeNode($.fn.zTree.getZTreeObj('treeDemo')),
+        parent, next, cur = Tree.selected();
+    if (target) {
+        if (target.data.projType === 'Tender') {
+            parent = target.parent;
+            next = target.nextSibling;
+        } else {
+            parent = target;
+            next = target.firstChild();
+        }
+
+        if (parent !== cur.parent || (next !== cur && next !== cur.nextSibling)){
+            updateData = GetMoveUpdateData(Tree.selected(), parent, next);
+            UpdateProjectData(updateData, function (data) {
+                form.modal('hide');
+                Tree.move(Tree.selected(), parent, next);
+            });
+        } else {
+            form.modal('hide');
+        }
+    } else {
+        form.modal('hide');
+    }
+})
+
+// 复制到
+$('#copytoBtn').click(function () {
+    if (Tree && Tree.selected()) {
+        $('#copyto').modal('show');
+    }
+});
+$('#copyto').on('show.bs.modal', function () {
+    copytoZTree = ConvertTreeToZtree(Tree, $('#treeDemo2'));
+});
+$('#copytoOk').click(function() {
+    var form = $('#copyto'),
+        target = GetTargetTreeNode($.fn.zTree.getZTreeObj('treeDemo2')),
+        parent, next, cur = Tree.selected();
+    if (target && (target.data.projType === 'Tender' || target.children.length === 0 || target.firstChild().data.projType === 'Tender')) {
+        if (target.data.projType === 'Tender') {
+            parent = target.parent;
+            next = target.nextSibling;
+        } else {
+            parent = target;
+            next = target.firstChild();
+        }
+
+        if (parent !== cur.parent || (next !== cur && next !== cur.nextSibling)){
+            CommonAjax.post('/pm/api/getNewProjectID', {count: 1}, function (IDs) {
+                var updateData = GetCopyUpdateData(cur, parent, next, IDs.lowID);
+                Tree.maxNodeId(IDs.lowID - 1);
+                CommonAjax.post('/pm/api/copyProjects', {updateData: updateData}, function (data) {
+                    form.modal('hide');
+                    data.forEach(function (nodeData) {
+                        if (nodeData.updateType === 'copy') {
+                            Tree.addNodeData(nodeData.updateData, parent, next);
+                        }
+                    });
+                }, function () {
+                    form.modal('hide');
+                });
+            });
+        } else {
+            form.modal('hide');
+        }
+    } else {
+        form.modal('hide');
+    }
+});