Sfoglia il codice sorgente

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

TonyKang 7 anni fa
parent
commit
d7789643bd
34 ha cambiato i file con 1123 aggiunte e 398 eliminazioni
  1. 43 42
      modules/glj/models/glj_list_model.js
  2. 1 1
      modules/glj/models/unit_price_model.js
  3. 13 0
      modules/main/controllers/project_controller.js
  4. 19 1
      modules/main/facade/project_facade.js
  5. 1 0
      modules/main/routes/project_route.js
  6. 46 6
      modules/pm/controllers/pm_controller.js
  7. 4 3
      modules/pm/facade/pm_facade.js
  8. 1 1
      modules/pm/models/templates/bills_template_model.js
  9. 1 0
      modules/pm/routes/pm_route.js
  10. 1 1
      modules/ration_glj/facade/ration_glj_facade.js
  11. 15 0
      modules/users/controllers/user_controller.js
  12. 1 0
      modules/users/routes/user_route.js
  13. 9 1
      web/building_saas/css/custom.css
  14. 1 0
      web/building_saas/js/global.js
  15. 8 1
      web/building_saas/main/html/calc_program_manage.html
  16. 2 2
      web/building_saas/main/html/main.html
  17. 1 9
      web/building_saas/main/html/tender_price.html
  18. 17 5
      web/building_saas/main/js/models/calc_program.js
  19. 4 0
      web/building_saas/main/js/models/project.js
  20. 1 1
      web/building_saas/main/js/models/ration.js
  21. 2 1
      web/building_saas/main/js/models/ration_glj.js
  22. 64 5
      web/building_saas/main/js/views/glj_col.js
  23. 10 153
      web/building_saas/main/js/views/glj_view.js
  24. 7 0
      web/building_saas/main/js/views/main_tree_col.js
  25. 5 42
      web/building_saas/main/js/views/project_glj_view.js
  26. 3 0
      web/building_saas/main/js/views/project_view.js
  27. 0 2
      web/building_saas/main/js/views/sub_fee_rate_views.js
  28. 36 28
      web/building_saas/main/js/views/sub_view.js
  29. 5 1
      web/building_saas/main/js/views/tender_price_view.js
  30. 102 33
      web/building_saas/pm/html/project-management-share.html
  31. 4 3
      web/building_saas/pm/html/project-management.html
  32. 0 29
      web/building_saas/pm/js/pm_gc.js
  33. 29 13
      web/building_saas/pm/js/pm_newMain.js
  34. 667 14
      web/building_saas/pm/js/pm_share.js

+ 43 - 42
modules/glj/models/glj_list_model.js

@@ -250,9 +250,19 @@ class GLJListModel extends BaseModel {
             };
             let projectGljData = await this.findDataByCondition(condition);
             let isAddProjectGLJ = false;
+
+            // 获取标段对应的单价文件id
+            let unitPriceFileId = unitFileId?unitFileId:await ProjectModel.getUnitPriceFileId(data.project_id);
+            if (unitPriceFileId <= 0) {
+                throw '没有对应的单价文件';
+            }
+
+            let unitPriceModel = new UnitPriceModel();
+
+            // 新增单条记录 (两个操作本来应该是事务操作,然而mongodb事务支持比较弱,就当作是都可以顺利执行)
+
             // 如果找不到数据则新增
             if (!projectGljData) {
-                // 新增单条记录 (两个操作本来应该是事务操作,然而mongodb事务支持比较弱,就当作是都可以顺利执行)
                 let gljInsertData = await this.add(data);
                 if (!gljInsertData) {
                     throw '新增项目工料机失败!';
@@ -261,14 +271,7 @@ class GLJListModel extends BaseModel {
                 projectGljData = gljInsertData;
             }
 
-            // 获取标段对应的单价文件id
-
-            let unitPriceFileId = unitFileId?unitFileId:await ProjectModel.getUnitPriceFileId(data.project_id);
-            if (unitPriceFileId <= 0) {
-                throw '没有对应的单价文件';
-            }
             let CompositionGLJ=[];
-            let unitPriceModel = new UnitPriceModel();
             // 判断类型,如果是混凝土、砂浆、配合比或者主材则查找对应的组成物(前提是没有对应的项目工料机数据)
             if(this.ownCompositionTypes.indexOf(data.type)!=-1) {
                 //如果是新增
@@ -288,7 +291,6 @@ class GLJListModel extends BaseModel {
                 }
             }
             projectGljData.subList=CompositionGLJ;
-
             // 新增单价文件
             let [unitPriceInsertData, isAdd] = await unitPriceModel.addUnitPrice(data, unitPriceFileId);
 
@@ -573,36 +575,31 @@ class GLJListModel extends BaseModel {
                 throw '组成物插入单价数据失败!';
             }
         }
-        let pglj_length = projectGljList instanceof Array ? projectGljList.length:Object.getOwnPropertyNames(projectGljList).length;
-        // 如果已经存在则后续操作停止
-        if(pglj_length === compositionGljList.length) {
-            return
-        }
+        let unitPriceModel = new UnitPriceModel();
+        let unitPriceList = await unitPriceModel.model.find({unit_price_file_id:unitPriceFileId});//查找按文件id查找单价文件数据,用来判断单价文件信息是否已存在
 
         // 整理插入的数据
         let gljInsertData = [];
         let unitPriceInsertData = [];
         for(let tmp of compositionGljList) {
             let key = this.getIndex(tmp,['code','name','specs','unit','gljType']);
-            if (projectGljList[key] !== undefined) {
-                continue;
+            if (projectGljList[key] === undefined) {
+                // 项目工料机插入的数据
+                let gljData = {
+                    glj_id: tmp.ID,
+                    project_id: projectId,
+                    code: tmp.code,
+                    name: tmp.name,
+                    specs: tmp.specs,
+                    unit: tmp.unit === undefined ? '' : tmp.unit,
+                    type: tmp.gljType,
+                    adjCoe:tmp.adjCoe,
+                    original_code:tmp.code,
+                    materialType: tmp.materialType,   //三材类别
+                    materialCoe: tmp.materialCoe
+                };
+                gljInsertData.push(gljData);
             }
-            // 项目工料机插入的数据
-            let gljData = {
-                glj_id: tmp.ID,
-                project_id: projectId,
-                code: tmp.code,
-                name: tmp.name,
-                specs: tmp.specs,
-                unit: tmp.unit === undefined ? '' : tmp.unit,
-                type: tmp.gljType,
-                adjCoe:tmp.adjCoe,
-                original_code:tmp.code,
-                materialType: tmp.materialType,   //三材类别
-                materialCoe: tmp.materialCoe
-            };
-            gljInsertData.push(gljData);
-
             let basePrice = scMathUtil.roundTo(tmp.basePrice,-6);
             // 单价文件插入的数据
             let unitPriceData = {
@@ -622,19 +619,17 @@ class GLJListModel extends BaseModel {
             if(tmp.from=='cpt'){
                 unitPriceData.is_add = 1;
             }
-            unitPriceInsertData.push(unitPriceData);
+           if(!unitPriceModel.isPropertyInclude(unitPriceList,['code','name','specs','unit','type'],unitPriceData)){
+               unitPriceInsertData.push(unitPriceData);
+           }
         }
         // 整理完后开始插入数据
-        let addResult = await this.add(gljInsertData);
-        if (!addResult) {
-            throw '组成物插入项目工料机失败!';
-        }
+
         // 插入单价数据表
-        let unitPriceModel = new UnitPriceModel();
-        let addUnitPriceResult = await unitPriceModel.add(unitPriceInsertData);
-        if (!addUnitPriceResult) {
-            throw '组成物插入单价数据失败!';
-        }
+        if(unitPriceInsertData.length >0) await unitPriceModel.add(unitPriceInsertData);
+       //插入项目工料机
+        if(gljInsertData.length > 0) await this.add(gljInsertData);
+
 
         return
     }
@@ -719,6 +714,12 @@ class GLJListModel extends BaseModel {
 
     async getCompositionGLJByData(glj,unitPriceFileId){
         let [gljData,mixRatioData,unitPriceData] = await this.getCompositionListByGLJ(glj,unitPriceFileId);
+        let priceNum = unitPriceData?Object.getOwnPropertyNames(unitPriceData).length:0;
+        let mixNum = mixRatioData?Object.getOwnPropertyNames(mixRatioData).length:0;
+        if(priceNum !==mixNum){//检查组成物数据是否一致
+            console.log("组成物数据有误,组成物单价文件个数:"+priceNum+",    组成物个数:"+mixNum);
+            return []
+        }
         gljData = this.combineData(gljData, unitPriceData, [], mixRatioData);
         return gljData;
     }

+ 1 - 1
modules/glj/models/unit_price_model.js

@@ -184,7 +184,7 @@ class UnitPriceModel extends BaseModel {
         }
         if(pops instanceof  Array){
             for(let p of pops){
-                if(obj[p]){
+                if(obj[p]!==undefined && obj[p]!==undefined!=null){
                     condition[p]=obj[p]
                 }
             }

+ 13 - 0
modules/main/controllers/project_controller.js

@@ -123,5 +123,18 @@ module.exports = {
             result.message = err.message;
         }
         res.json(result);
+    },
+    saveProperty: function(req, res){
+        let result = {error: 0, message: '', data: null};
+        let data = JSON.parse(req.body.data);
+        project_facade.saveProperty(data, function (err, data) {
+            if (err == ''){
+                result.data = data;
+            }else{
+                result.error = 1;
+                result.message = err;
+            }
+            res.json(result);
+        })
     }
 };

+ 19 - 1
modules/main/facade/project_facade.js

@@ -2,6 +2,7 @@
  * Created by zhang on 2018/1/26.
  */
 let mongoose = require('mongoose');
+let logger = require("../../../logs/log_helper").logger;
 let  projectsModel = mongoose.model('projects');
 let async_n = require("async");
 let _ = require('lodash');
@@ -19,7 +20,8 @@ module.exports = {
     markUpdateProject:markUpdateProject,
     removeProjectMark:removeProjectMark,
     updateNodes:updateNodes,
-    calcInstallationFee:calcInstallationFee
+    calcInstallationFee:calcInstallationFee,
+    saveProperty: saveProperty
 };
 
 async function calcInstallationFee(data) {
@@ -233,4 +235,20 @@ function generateMarkTask(value,projectID) {
         }
     };
     return task
+}
+
+// {projectID: 5, propertyName: 'aaa', propertyValue: 1}
+function saveProperty(data, callback){
+    let obj = {};
+    let pn = 'property.' + data.propertyName;
+    obj[pn] = data.propertyValue;
+    projectsModel.update({"ID": data.projectID}, obj, function (err) {
+        if (err) {
+            logger.err(pn + ' save error: ' + err);
+            callback(err, null)
+        } else {
+            logger.info(pn + ' saved.');
+            callback('', null);
+        }}
+    );
 }

+ 1 - 0
modules/main/routes/project_route.js

@@ -13,6 +13,7 @@ module.exports = function (app) {
     projectRouter.post('/removeProjectMark', projectController.removeProjectMark);
     projectRouter.post('/updateNodes', projectController.updateNodes);
     projectRouter.post('/calcInstallationFee', projectController.calcInstallationFee);
+    projectRouter.post('/saveProperty', projectController.saveProperty);
 
     app.use('/project',projectRouter);
 };

+ 46 - 6
modules/pm/controllers/pm_controller.js

@@ -454,6 +454,34 @@ module.exports = {
         try {
             let userID = req.session.sessionUser.id;
             let rst = {receive: [], share: []}//接收的、由我分享的
+            let shareProjects = await projectModel.find({userID: userID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], 'shareInfo.0': {$exists: true}});
+            //项目类型为分享给别人
+            let shareToUserIDs = [];
+            for(let proj of shareProjects){
+                proj._doc.shareType = 'shareTo';
+                 for(let shareToUser of proj.shareInfo){
+                     shareToUserIDs.push(shareToUser.userID);
+                 }
+            }
+            shareToUserIDs = Array.from(new Set(shareToUserIDs));
+            let shareToObjIDs = [];
+            for(let userID of shareToUserIDs){
+                shareToObjIDs.push(mongoose.Types.ObjectId(userID));
+            }
+            let shareToUsers = await userModel.find({_id: {$in: shareToObjIDs}});
+            for(let shareToUser of shareToUsers){
+                for(let proj of shareProjects){
+                    for(let user of proj.shareInfo){
+                        if(user.userID === shareToUser._id.toString()){
+                            user._doc.company = shareToUser.company;
+                            user._doc.email = shareToUser.email;
+                            user._doc.name = shareToUser.real_name;
+                            user._doc.mobile = shareToUser.mobile;
+                        }
+                    }
+                }
+            }
+            rst.share = shareProjects;
             let receiveProjects = await projectModel.find({$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], 'shareInfo.userID': userID});
             //设置原项目用户信息
             if(receiveProjects.length > 0){
@@ -468,21 +496,33 @@ module.exports = {
                 }
                 let orgUsersInfo = await userModel.find({_id: {$in : userObjIDs}});
                 for(let proj of receiveProjects){
-                    for(let userInfo of orgUsersInfo){
-                        if(proj.userID == userInfo._id.toString()){
-                            let userInfo = {name: userInfo.name, mobile: userInfo.mobile, company: userInfo.company};
-                            proj._doc.userInfo = userInfo
+                    //设置项目类型为来自别人分享
+                    proj._doc.shareType = 'receive';
+                    for(let userData of orgUsersInfo){
+                        if(proj.userID == userData._id.toString()){
+                            let userInfo = {name: userData.real_name, mobile: userData.mobile, company: userData.company, email: userData.email};
+                            proj._doc.userInfo = userInfo;
                         }
                     }
                 }
             }
             rst.receive = receiveProjects;
-            let shareProjects = await projectModel.find({$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], 'shareInfo.0': {$exists: true}});
-            rst.share = shareProjects;
             callback(req, res, 0, 'success', rst);
         }
         catch (err){
             callback(req, res, 1, err, null);
         }
+    },
+    getProjectsByQuery: async function (req, res) {
+        try{
+            let data = JSON.parse(req.body.data);
+            let query = data.query;
+            let options = data.options;
+            let projects = await projectModel.find(query, options);
+            callback(req, res, 0, 'success', projects);
+        }
+        catch (err){
+            callback(req, res, 1, err, null);
+        }
     }
 };

+ 4 - 3
modules/pm/facade/pm_facade.js

@@ -24,6 +24,7 @@ let rationCoeModel = mongoose.model('ration_coe');
 let rationInstallationModel = mongoose.model('ration_installation');
 let quantityDetailModel = mongoose.model('quantity_detail');
 import CounterModel from "../../glj/models/counter_model";
+import moment from 'moment';
 
 
 module.exports={
@@ -45,13 +46,13 @@ async function copyProject(userID, compilationID,data) {
     //费率文件、单价文件重名检查
     let feeRate =  await feeRateFileModel.findOne({rootProjectID:originalProperty.rootProjectID,name:originalProperty.feeFile.name,deleteInfo:null});
     if(feeRate){//存在重名的文件
-        newFeeName = originalProperty.feeFile.name + '(' + new Date().Format('MM-dd hh:mm:ss') + '复制)';
+        newFeeName = originalProperty.feeFile.name + '(' + moment(Date.now()).format('MM-DD HH:mm:ss') + '复制)';
         projectMap['copy'].document.property.feeFile.name = newFeeName;
     }
 
     let unitPriceFile =  await unitPriceFileModel.findOne({root_project_id: originalProperty.rootProjectID,name:originalProperty.unitPriceFile.name,deleteInfo: null});
     if(unitPriceFile){//存在重名的文件
-        newUnitName = originalProperty.unitPriceFile.name + '(' + new Date().Format('MM-dd hh:mm:ss') + '复制)';
+        newUnitName = originalProperty.unitPriceFile.name + '(' + moment(Date.now()).format('MM-DD HH:mm:ss') + '复制)';
         projectMap['copy'].document.property.unitPriceFile.name = newUnitName;
     }
 
@@ -229,7 +230,7 @@ async function copyUnitPriceFile(newProjectID,rootProjectID,userID,originaluUnit
         let rList = [];
         for(let m of mList){
             m._doc.unit_price_file_id = newFID;
-            m._doc.id = await getCounterID('mix_ratio');
+            m._doc.id = await getCounterID(model.modelName);
             rList.push(m._doc);
         }
         await insertMany(rList,model)

+ 1 - 1
modules/pm/models/templates/bills_template_model.js

@@ -40,7 +40,7 @@ class BillsTemplateModel extends BaseModel {
      */
     async getTemplateDataForNewProj (valuationId, engineering) {
         // 筛选字段
-        let field = {_id: 0, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1,type:1, calcBase: 1};
+        let field = {_id: 0, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1,type:1, calcBase: 1,feeRateID:1};
         let data = await this.findDataByCondition({valuationId: valuationId, engineering: engineering}, field, false);
 
         return data === null ? [] : data;

+ 1 - 0
modules/pm/routes/pm_route.js

@@ -38,6 +38,7 @@ module.exports = function (app) {
      req.body = {data: '{user_id: user_id, updateData: [{updateType, updateData}]}'}
      data.updateData.updateType: 1 of ['update', 'copy']
      */
+    pmRouter.post('/getProjectsByQuery', pmController.getProjectsByQuery);
     pmRouter.post('/copyProjects', pmController.copyProjects);
     pmRouter.post('/renameProject', pmController.rename);
     pmRouter.post('/beforeOpenProject', pmController.beforeOpenProject);

+ 1 - 1
modules/ration_glj/facade/ration_glj_facade.js

@@ -168,7 +168,7 @@ function createNewRecord(ration_glj) {
     newRecoed.type = ration_glj.type;
     newRecoed.repositoryId = ration_glj.repositoryId;
     newRecoed.projectGLJID = ration_glj.projectGLJID;
-    newRecoed.adjCoe = ration_glj.adjCoe
+    newRecoed.adjCoe = ration_glj.adjCoe;
     return newRecoed
 }
 

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

@@ -14,6 +14,7 @@ import SettingType from "../../common/const/setting_type_const";
 import CompilationModel from "../models/compilation_model";
 import mongoose from "mongoose";
 import moment from "moment";
+const userData = mongoose.model('user');
 
 class UserController extends BaseController {
 
@@ -278,6 +279,20 @@ class UserController extends BaseController {
             res.json({error: 1, msg: err, data: null});
         }
     }
+    async getUsers(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let userObjIDs = [];
+            for(let userID of data.userIDs){
+                userObjIDs.push(mongoose.Types.ObjectId(userID));
+            }
+            let users = await userData.find({_id: {$in: userObjIDs}});
+            res.json({error: 0, msg: 'success', data: users});
+        }
+        catch (err){
+            res.json({error: 1, msg: err, data: null});
+        }
+    }
 
 }
 

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

@@ -20,6 +20,7 @@ module.exports = function (app) {
     router.post('/save-preferences', userController.init, userController.savePreferences);
     router.post('/info', userController.init, userController.saveData);
     router.post('/getUserByMobile', userController.init, userController.getUserByMobile);
+    router.post('/getUsers', userController.init, userController.getUsers);
 
     router.post('/getVersionInfo', userController.init, userController.getVersionInfo);
     app.use('/user',router);

+ 9 - 1
web/building_saas/css/custom.css

@@ -46,4 +46,12 @@ legend.legend{
     padding: 8px;
     padding-top: 7px;
     padding-bottom: 7px;
-}
+}
+
+#gljPriceTenderCoe::-webkit-outer-spin-button,
+#gljPriceTenderCoe::-webkit-inner-spin-button {
+         -webkit-appearance: none;
+     }
+#gljPriceTenderCoe {
+    -moz-appearance: textfield;
+}

+ 1 - 0
web/building_saas/js/global.js

@@ -28,6 +28,7 @@ function autoFlashHeight(){
     $(".side-content").height($(window).height()-headerHeight );
     $(".poj-list").height($(window).height()-headerHeight-toolsbarHeight);
     $(".gc-list").height($(window).height()-headerHeight-toolsbarHeight-40);
+    $(".share-list").height($(window).height()-headerHeight-toolsbarHeight-40);
     $(".form-view").height($(window).height()-headerHeight-ftoolsbarHeight);
     $(".form-list").height($(window).height()-headerHeight-50 );
 

+ 8 - 1
web/building_saas/main/html/calc_program_manage.html

@@ -16,8 +16,15 @@
     <div class="container-fluid">
         <div class="row">
             <div class="col-lg-2 p-0">
-                <div class="main-data-not" id="mainSpread">
+                <div id="divSelect" style="text-align:left;height:45px;line-height:45px;">
+                    <!--<label>计算程序文件:</label>-->
+                    <select id='calcProgramFileSelect' style="width:98%;height:30px;">
+                        <option value="none">无</option>
+                        <option value="1" selected>计算程序2013标准</option>
+                        <option value="2">计算程序2018标准</option>
+                    </select>
                 </div>
+                <div class="main-data-not" id="mainSpread"></div>
             </div>
             <div class="col-lg-10 p-0">
                 <div class="main-data-not" id="detailSpread">

+ 2 - 2
web/building_saas/main/html/main.html

@@ -44,7 +44,7 @@
         <div class="main-nav">
             <ul class="nav nav-tabs flex-column" role="tablist">
                 <li class="nav-item"><a class="active" data-toggle="tab" href="#zaojiashu" id="tab_zaojiashu" role="tab">造价书</a></li>
-                <li class="nav-item"><a data-toggle="tab" href="#project_glj" id="tab_project_glj" data-name="tab_project_glj" role="tab">人材机</a></li>
+                <li class="nav-item"><a data-toggle="tab" href="#project_glj" id="tab_project_glj" data-name="tab_project_glj" role="tab">人材机汇总</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#fee_rates" id="tab_fee_rate" role="tab" >费率</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#calc_program_manage" id="tab_calc_program_manage" role="tab">计算程序</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#tender_price" id="tab_tender_price" role="tab">调价</a></li>
@@ -1209,7 +1209,7 @@
                     <div class="alert alert-success mt-3" id="uploadAlert" role="alert" style="display: none;">
                         广东XXXX项目清单.xlsx 准备导入上传
                     </div>
-                    <button type="button" class="btn btn-primary" id="uploadExample">示例</button>
+                    <button style="margin-top: 2px;" type="button" class="btn btn-primary" id="uploadExample">示例</button>
                 </div>
                 <div class="modal-footer">
                     <a href="javascript:void(0);" class="btn btn-primary" id="uploadConfirm">确定导入</a>

+ 1 - 9
web/building_saas/main/html/tender_price.html

@@ -1,12 +1,4 @@
-<!--<style>
-    input::-webkit-outer-spin-button,
-    input::-webkit-inner-spin-button {
-        -webkit-appearance: none;
-    }
-    input[type="number"]{
-        -moz-appearance: textfield;
-    }
-</style>-->
+
 <div class="toolsbar px-1">
     <div class="btn-toolbar py-1">
         <div class="input-group input-group-sm mr-2">

+ 17 - 5
web/building_saas/main/js/models/calc_program.js

@@ -489,7 +489,9 @@ let calcTools = {
             (treeNode.data.type == rationType.gljRation) &&
             ((treeNode.data.subType === gljType.LABOUR && baseName === calcBaseNames.RGFJC) ||
                 (baseMaterialTypes.includes(treeNode.data.subType) && baseName === calcBaseNames.CLFJC) ||
-                (treeNode.data.subType === gljType.GENERAL_MACHINE && baseName === calcBaseNames.JXFJC))
+                (treeNode.data.subType === gljType.GENERAL_MACHINE && baseName === calcBaseNames.JXFJC) ||
+                (treeNode.data.subType === gljType.MAIN_MATERIAL && baseName === calcBaseNames.ZCFJC) ||
+                (treeNode.data.subType === gljType.EQUIPMENT && baseName === calcBaseNames.SBFJC))
         ) {
             let aprice = me.uiGLJPrice(treeNode.data.adjustPrice);
             let mprice = me.uiGLJPrice(treeNode.data.marketUnitFee);
@@ -778,6 +780,8 @@ const calcBaseNames = {
     RGFJC: '人工费价差',
     CLFJC: '材料费价差',
     JXFJC: '机械费价差',
+    ZCFJC: '主材费价差',
+    SBFJC: '设备费价差',
     ZCF: '主材费',
     SBF: '设备费',
     RGGR: '人工工日',
@@ -822,11 +826,17 @@ const rationCalcBases = {
     '机械费价差': function (node, isTender) {
         return calcTools.rationBaseFee(node, [gljType.GENERAL_MACHINE], priceTypes.ptDiffPrice, isTender);
     },
+    '主材费价差': function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.MAIN_MATERIAL], priceTypes.ptDiffPrice, isTender);
+    },
+    '设备费价差': function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptDiffPrice, isTender);
+    },
     '主材费': function (node, isTender) {
-        return calcTools.rationBaseFee(node, [gljType.MAIN_MATERIAL], priceTypes.ptMarketPrice, isTender);
+        return calcTools.rationBaseFee(node, [gljType.MAIN_MATERIAL], priceTypes.ptBasePrice, isTender);
     },
     '设备费': function (node, isTender) {
-        return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptMarketPrice, isTender);
+        return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptBasePrice, isTender);
     },
     '人工工日': function (node, isTender) {
         if (!node.data.gljList) return 0;
@@ -1548,9 +1558,11 @@ class CalcProgram {
                             rtf = parseFloatPlus(node.data.feesIndex[ft.type].totalFee).toDecimal(decimalObj.bills.totalPrice);
                             rttf = parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee).toDecimal(decimalObj.bills.totalPrice);
                         };
+                        // 取费方式为子目含量,清单行/列的XX单价应 =ROUND( ∑ROUND(定额XX单价*含量,清单单价精度),清单单价精度)
                         if (me.project.property.billsCalcMode === leafBillGetFeeType.rationContent) {
-                            buf = (buf + (ruf * parseFloatPlus(node.data.quantity)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
-                            btuf = (btuf + (rtuf * parseFloatPlus(node.data.tenderQuantity)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
+                            buf = (buf + (ruf * parseFloatPlus(node.data.contain)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
+                            node.data.tenderContaion = (node.data.tenderQuantity / bq).toDecimal(decimalObj.decimal.process);
+                            btuf = (btuf + (rtuf * parseFloatPlus(node.data.tenderContaion)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
                         };
                         sum_rtf = (sum_rtf + rtf).toDecimal(decimalObj.process);
                         sum_rttf = (sum_rttf + rttf).toDecimal(decimalObj.process);

+ 4 - 0
web/building_saas/main/js/models/project.js

@@ -318,6 +318,10 @@ var PROJECT = {
             CommonAjax.post("/project/markUpdateProject",{updateInfo:data,type:type});
         };
 
+        project.prototype.saveProperty = function (propertyName, propertyValue) {
+            CommonAjax.post("/project/saveProperty", {projectID: this.ID(), propertyName: propertyName, propertyValue: propertyValue});
+        };
+
         project.prototype.projectMarkChecking = function () {
             let  changeMark = projectInfoObj.projectInfo.changeMark;
             if(changeMark&&changeMark!=''){

+ 1 - 1
web/building_saas/main/js/models/ration.js

@@ -600,8 +600,8 @@ var Ration = {
                     newNode.source = newSource;
                     newNode.sourceType = project.Ration.getSourceType();
                     newNode.data = newSource;
-                    ProjectController.syncDisplayNewNode(sheetController, newNode);
                     project.projectGLJ.loadData(function () {
+                        ProjectController.syncDisplayNewNode(sheetController, newNode);
                         project.ration_glj.addToMainTree(data.ration_gljs);
                         projectObj.mainController.refreshTreeNode([newNode], false);
                         project.calcProgram.calcAndSave(newNode,function () {

+ 2 - 1
web/building_saas/main/js/models/ration_glj.js

@@ -121,7 +121,8 @@ var ration_glj = {
                     glj.type = glj.subType;
                 };
 
-                glj.quantity = (glj.quantity / billQuantity).toDecimal(decimalObj.glj.quantity);
+                // glj.quantity = (glj.quantity / billQuantity).toDecimal(decimalObj.glj.quantity);
+                glj.quantity = (glj.quantity / billQuantity).toDecimal(decimalObj.process);  // 广联达这里没有取舍
             };
             return oneBill;
         }

+ 64 - 5
web/building_saas/main/js/views/glj_col.js

@@ -25,12 +25,71 @@ let gljCol = {
         // 工料机类型是混凝土、砂浆、配合比、机械台班时,价格不可编辑。
         editedTyep:[GLJTypeConst.MAIN_MATERIAL,GLJTypeConst.EQUIPMENT]//主材设备
     },
+    project_glj_setting:{
+        header: [
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String"},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
+            {headerName: "总消耗量", headerWidth: 130, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
+            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.unitPrice',validator:"number"},
+            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"},
+            {headerName: "是否暂估", headerWidth: 60, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox'},
+            {headerName: "主要材料", headerWidth: 60, dataCode: "is_main_material", hAlign: "center", dataType: "String",cellType:'checkBox'},
+            {headerName: "供货方式", headerWidth: 80, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
+            {headerName: "甲供数量", headerWidth: 100, dataCode: "supply_quantity", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "三材类别", headerWidth: 80, dataCode: "materialType", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:materialComboMap},
+            {headerName: "三材系数", headerWidth: 100, dataCode: "materialCoe", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'material'
+            {headerName: "交货方式", headerWidth: 90, dataCode: "delivery", hAlign: "left", dataType: "String"},
+            {headerName: "送达地点", headerWidth: 100, dataCode: "delivery_address", hAlign: "left", dataType: "String"},
+            {headerName: "不调价", headerWidth: 55, dataCode: "is_adjust_price", dataType: "String",cellType: "checkBox"},
+            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
+        ],
+            view: {
+            lockColumns: [0,1,2,3,4,5,7]
+        }
+    },
+    mixRatio_Setting:{
+        header:[
+            {headerName: "编码", headerWidth: 120, dataCode: "code", dataType: "String"},
+            {headerName: "名称", headerWidth: 120, dataCode: "name", dataType: "String"},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", dataType: "String"},
+            {headerName: "单位", headerWidth: 120, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "类型", headerWidth: 120, dataCode: "short_name", hAlign: "center", dataType: "String"},
+            {headerName: "定额价", headerWidth: 120, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.unitPrice',validator:"number"},
+            {headerName: "调整价", headerWidth: 120, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
+            {headerName: "市场价", headerWidth: 120, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"},
+            {headerName: "消耗量", headerWidth: 120, dataCode: "consumption", hAlign: "right", dataType: "Number",decimalField:"glj.quantity",validator:"number"}
+        ],
+        view: {
+            lockColumns: [0,1,2,3,4,5,6,7]
+        }
+    },
     removeCol:function (dataCode,setting) {
-       // let colIndex =
-
-
-
+        let colIndex = _.findIndex(setting.header,{'dataCode':dataCode});
+        if(colIndex != -1){
+            setting.header.splice(colIndex,1);//去掉列;
+            let newArray = [];
+            for(let l of setting.view.lockColumns){
+                if(l == colIndex)  continue;
+                if(l > colIndex)  l = l -1;
+                newArray.push(l);
+            }
+            setting.view.lockColumns = newArray;
+        }
+    },
+    initGljCol:function (showAdjustPrice) {
+        let me = gljCol;
+        if(showAdjustPrice !== true){
+            me.removeCol('adjustPrice',me.ration_glj_setting);
+            me.removeCol('adjustPrice',me.project_glj_setting);
+            me.removeCol('adjustPrice',me.mixRatio_Setting);
+        }
+        gljOprObj.setting = me.ration_glj_setting;
+        projectGljObject.projectGljSetting = me.project_glj_setting;
+        projectGljObject.mixRatioSetting = me.mixRatio_Setting;
     }
 
-
 };

+ 10 - 153
web/building_saas/main/js/views/glj_view.js

@@ -14,96 +14,12 @@ var gljOprObj = {
     selectedGLJClass: null,
     parentNodeIds: {},
     activeTab: '#linkGLJ',
-    setting: {
-        header: [
-            {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String", formatter: "@"},
-            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
-            {headerName: "规格型号", headerWidth: 90, dataCode: "specs", dataType: "String", hAlign: "left"},
-            {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center"},
-            {headerName: "类型", headerWidth: 45, dataCode: "shortName", dataType: "String", hAlign: "center"},
-            {
-                headerName: "定额消耗",
-                headerWidth: 80,
-                dataCode: "rationItemQuantity",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.quantity"
-            },    // dataType: "Number", formatter: "0.00"
-            {
-                headerName: "自定消耗",
-                headerWidth: 80,
-                dataCode: "customQuantity",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.quantity"
-            },
-            {
-                headerName: "消耗量",
-                headerWidth: 80,
-                dataCode: "quantity",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.quantity"
-            },
-            {
-                headerName: "总消耗量",
-                headerWidth: 80,
-                dataCode: "totalQuantity",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.quantity"
-            },
-            {
-                headerName: "定额价",
-                headerWidth: 80,
-                dataCode: "basePrice",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.unitPrice"
-            },
-            {
-                headerName: "调整价",
-                headerWidth: 80,
-                dataCode: "adjustPrice",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.unitPrice"
-            },
-            {
-                headerName: "市场价",
-                headerWidth: 80,
-                dataCode: "marketPrice",
-                dataType: "Number",
-                hAlign: "right",
-                decimalField: "glj.unitPrice"
-            },
-            {
-                headerName: "是否暂估",
-                headerWidth: 65,
-                dataCode: "isEstimate",
-                dataType: "String",
-                hAlign: "center",
-                vAlign: "center",
-                cellType: "checkBox"
-            }
-        ],
-        view: {
-            lockColumns: [0, 4, 5, 7, 8, 10, 12]
-        },
-        // 工料机类型是混凝土、砂浆、配合比、机械台班时,价格不可编辑。
-        editedTyep:[GLJTypeConst.MAIN_MATERIAL,GLJTypeConst.EQUIPMENT]//主材设备
-    },
+    setting: {},
     detailSetting: {
         header: [
             {headerName: "名称", headerWidth: 100, dataCode: "name", dataType: "String"},
             {headerName: "计算式", headerWidth: 120, dataCode: "regex", dataType: "String"},
-            {
-                headerName: "结果(C)",
-                headerWidth: 120,
-                dataCode: "result",
-                dataType: "Number",
-                decimalField: "quantity_detail"
-            },
+            {headerName: "结果(C)", headerWidth: 120, dataCode: "result", dataType: "Number", decimalField: "quantity_detail"},
             {headerName: "累加", headerWidth: 120, dataCode: "isSummation", dataType: "String", cellType: "checkBox"}
         ],
         view: {
@@ -164,73 +80,14 @@ var gljOprObj = {
     gljLibSheetSetting: {
         owner: 'gljTree',
         header: [
-            {
-                headerName: "选择",
-                headerWidth: 40,
-                dataCode: "select",
-                hAlign: "center",
-                vAlign: "center",
-                cellType: "checkBox"
-            },
-            {
-                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: 40,
-                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"
-            },
-            {
-                headerName: "是否新增",
-                headerWidth: 80,
-                dataCode: "isComplementary",
-                dataType: "String",
-                hAlign: "center",
-                vAlign: "center",
-                cellType: "checkBox"
-            }
+            {headerName: "选择", headerWidth: 40, dataCode: "select", hAlign: "center", vAlign: "center", cellType: "checkBox"},
+            {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: 40, 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"},
+            {headerName: "是否新增", headerWidth: 80, dataCode: "isComplementary", dataType: "String", hAlign: "center", vAlign: "center", cellType: "checkBox"}
         ],
         view: {
             lockColumns: [0, 1, 2, 3, 4, 5, 6]

+ 7 - 0
web/building_saas/main/js/views/main_tree_col.js

@@ -52,6 +52,13 @@ let MainTreeCol = {
             if((node.sourceType === projectObj.project.Ration.getSourceType()&&node.data.type!=rationType.ration)||node.sourceType==projectObj.project.ration_glj.getSourceType()){
                 return calcTools.uiGLJPrice(node.data.marketUnitFee);
             }
+        },
+        feeRate:function (node) {
+            if(node.data.feeRateID){
+                let rate = projectObj.project.FeeRate.getFeeRateByID(node.data.feeRateID);
+                if (rate) return rate.rate;
+            }
+            return node.data.feeRate;
         }
     },
     readOnly: {

+ 5 - 42
web/building_saas/main/js/views/project_glj_view.js

@@ -7,52 +7,12 @@ projectGljObject={
     displayType:filterType.ALL,
     mixRatioType: [gljType.CONCRETE, gljType.MORTAR, gljType.MIX_RATIO,gljType.MAIN_MATERIAL],
     machineType: [gljType.GENERAL_MACHINE],
-    projectGljSetting:{
-        header: [
-            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
-            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
-            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String"},
-            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
-            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
-            {headerName: "总消耗量", headerWidth: 130, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
-            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.unitPrice',validator:"number"},
-            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
-            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"},
-            {headerName: "是否暂估", headerWidth: 60, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox'},
-            {headerName: "主要材料", headerWidth: 60, dataCode: "is_main_material", hAlign: "center", dataType: "String",cellType:'checkBox'},
-            {headerName: "供货方式", headerWidth: 80, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
-            {headerName: "甲供数量", headerWidth: 100, dataCode: "supply_quantity", hAlign: "right", dataType: "Number",validator:"number"},
-            {headerName: "三材类别", headerWidth: 80, dataCode: "materialType", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:materialComboMap},
-            {headerName: "三材系数", headerWidth: 100, dataCode: "materialCoe", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'material'
-            {headerName: "交货方式", headerWidth: 90, dataCode: "delivery", hAlign: "left", dataType: "String"},
-            {headerName: "送达地点", headerWidth: 100, dataCode: "delivery_address", hAlign: "left", dataType: "String"},
-            {headerName: "不调价", headerWidth: 55, dataCode: "is_adjust_price", dataType: "String",cellType: "checkBox"},
-            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
-        ],
-        view: {
-            lockColumns: [0,1,2,3,4,5,7]
-        }
-    },
+    projectGljSetting:{},
     projectGljSpread:null,
     projectGljSheet:null,
     materialTreeSheet:null,
     projectGljSheetData:[],
-    mixRatioSetting:{
-        header:[
-            {headerName: "编码", headerWidth: 120, dataCode: "code", dataType: "String"},
-            {headerName: "名称", headerWidth: 120, dataCode: "name", dataType: "String"},
-            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", dataType: "String"},
-            {headerName: "单位", headerWidth: 120, dataCode: "unit", hAlign: "center", dataType: "String"},
-            {headerName: "类型", headerWidth: 120, dataCode: "short_name", hAlign: "center", dataType: "String"},
-            {headerName: "定额价", headerWidth: 120, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.unitPrice',validator:"number"},
-            {headerName: "调整价", headerWidth: 120, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
-            {headerName: "市场价", headerWidth: 120, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"},
-            {headerName: "消耗量", headerWidth: 120, dataCode: "consumption", hAlign: "right", dataType: "Number",decimalField:"glj.quantity",validator:"number"}
-        ],
-        view: {
-            lockColumns: [0,1,2,3,4,5,6,7]
-        }
-    },
+    mixRatioSetting:{},
     materialTreeSetting:{
         "emptyRows":0,
         "headRows":1,
@@ -245,6 +205,7 @@ projectGljObject={
         let data = null, setting=null;
         let sheet = me.projectGljSpread.getActiveSheet();
         if(sheet.name() ==  'projectGljSheet'){
+            if(row>=me.projectGljSheetData.length) return false;
             data = me.projectGljSheetData[row];
             setting = me.projectGljSetting;
         }else if(sheet.name() ==  'materialTreeSheet'){
@@ -841,6 +802,7 @@ projectGljObject={
         let prowData = parentSheet.name() == 'projectGljSheet'?me.projectGljSheetData[prow]:me.materialTree.items[prow].data;
         let updateData = {id: deleteRecode.mix_ratio_id, field: 'mix_ratio.consumption' , value: 0, market_price: parentMarketPrice, base_price: parentBasePrice};
         projectObj.project.composition.deleteComposition(updateData,deleteRecode,prowData.id,function () {
+            _.remove(me.mixRatioData,{"mix_ratio_id":deleteRecode.mix_ratio_id});
             me.refreshParentData(prow,prowData.id);
             me.mixRatioSheet.deleteRows(row,1);
             me.onUnitFileChange(deleteRecode);
@@ -865,6 +827,7 @@ projectGljObject={
         parentMarketPrice = parentMarketPrice.toDecimal(getDecimal("glj.unitPrice"));
         parentBasePrice = parentBasePrice.toDecimal(getDecimal("glj.unitPrice"));
         return [parentMarketPrice, parentBasePrice];
+        
     },
     onProjectGLJValueChange:function (e,info) {//me.projectGljSetting
         let projectGLJ = projectObj.project.projectGLJ;

+ 3 - 0
web/building_saas/main/js/views/project_view.js

@@ -602,6 +602,9 @@ var projectObj = {
             console.log(`get data时间——${mTime - startTime}`);
             if (!err) {
                 that.project.projectGLJ.calcQuantity(true);//计算分部分项和技术措施项目消耗量;
+                gljCol.initGljCol(that.project.projSetting.glj_col?that.project.projSetting.glj_col.showAdjustPrice:false);
+                subObj.initSubSpread();//初始化主界面下方的表格
+
                 let quantityTime = +new Date();
                 console.log(`计算quantity时间——${quantityTime - mTime}`);
                 that.project.property = projectInfoObj.projectInfo.property;

+ 0 - 2
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -93,8 +93,6 @@ var subRateObject={
         }
         subRateObject.datas = projectObj.project.FeeRate.getSubViewData(item);
         subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
-        console.log(subRateObject.datas);
-        console.log(subRateObject.valueMap);
         subRateObject.showSubRateData();
         disableRightMenu("subRate",this.subRateSpread);
     },

+ 36 - 28
web/building_saas/main/js/views/sub_view.js

@@ -6,33 +6,41 @@
 //特征及内容spread,解决不能正确显示spread
 
 //zhang 5-31  删除附注条件、辅助定额tab,增加子目换算tab
-contentOprObj.buildSheet($("#jobSpread")[0]);
-characterOprObj.buildSheet($("#itemSpread")[0]);
-$("#tzjnrCon").hide();
-$("#subSpread").show();
-var subSpread = sheetCommonObj.createSpread($("#subSpread")[0], 4);
-subSpread.options.allowUserDragDrop = false;
-subSpread.options.allowUserDragFill = false;
-subSpread.getSheet(2).name('JSCX');
-
-pageCCOprObj.active = false;
-
-// 工料机
-gljOprObj.initSheet(subSpread.getSheet(0));
-//sheetCommonObj.shieldAllCells(subSpread.getSheet(0), gljOprObj.setting);
-SheetDataHelper.protectdSheet(subSpread.getSheet(0));
-// assistOprObj.initSheet(subSpread.getSheet(1));
-// sheetCommonObj.shieldAllCells(subSpread.getSheet(1), assistOprObj.setting);
-
-
-//工程量明细
-gljOprObj.initDetailSheet(subSpread.getSheet(1));
-SheetDataHelper.protectdSheet(subSpread.getSheet(1));
-
-//安装增加费
-installationFeeObj.initRationInstallSheet(subSpread.getSheet(3));
-SheetDataHelper.protectdSheet(subSpread.getSheet(3));
-gljContextMenu.loadGLJSpreadContextMenu();
+
+let subSpread = null;
+let subObj = {
+  initSubSpread:function () {
+      contentOprObj.buildSheet($("#jobSpread")[0]);
+      characterOprObj.buildSheet($("#itemSpread")[0]);
+      $("#tzjnrCon").hide();
+      $("#subSpread").show();
+      subSpread = sheetCommonObj.createSpread($("#subSpread")[0], 4);
+      subSpread.options.allowUserDragDrop = false;
+      subSpread.options.allowUserDragFill = false;
+      subSpread.getSheet(2).name('JSCX');
+
+      pageCCOprObj.active = false;
+
+       // 工料机
+      gljOprObj.initSheet(subSpread.getSheet(0));
+        //sheetCommonObj.shieldAllCells(subSpread.getSheet(0), gljOprObj.setting);
+      SheetDataHelper.protectdSheet(subSpread.getSheet(0));
+        // assistOprObj.initSheet(subSpread.getSheet(1));
+        // sheetCommonObj.shieldAllCells(subSpread.getSheet(1), assistOprObj.setting);
+
+
+        //工程量明细
+      gljOprObj.initDetailSheet(subSpread.getSheet(1));
+      SheetDataHelper.protectdSheet(subSpread.getSheet(1));
+
+        //安装增加费
+      installationFeeObj.initRationInstallSheet(subSpread.getSheet(3));
+      SheetDataHelper.protectdSheet(subSpread.getSheet(3));
+      gljContextMenu.loadGLJSpreadContextMenu();
+  }
+};
+
+
 
 $("#linkGLJ").click(function(){
     $("#subItems").children().hide();//控制显示subSpread,隐藏特征及内容spread
@@ -309,7 +317,7 @@ function refreshSubSpread(){
         characterOprObj.workBook.refresh();
     }
     else{
-        subSpread.refresh();
+        subSpread?subSpread.refresh():'';
     }
 }
 

+ 5 - 1
web/building_saas/main/js/views/tender_price_view.js

@@ -401,7 +401,10 @@ let tender_obj={
     doTenderCalc: function(tender){
         if (tender != tenderTypes.ttCalc)
             tender_obj.cleanCacheCoes();
-        let callback = function () { tender_obj.showTenderData() };
+        let callback = function () {
+            projectObj.project.saveProperty('hasTender', true);
+            tender_obj.showTenderData();
+        };
         projectObj.project.calcProgram.calcAllNodesAndSave(calcAllType.catAll, callback, tender);
     }
 };
@@ -436,6 +439,7 @@ $(function () {
             }
         }
         datas.push({type:ModuleNames.project,data:{'ID' : projectObj.project.ID(),'property.tenderSetting.gljPriceTenderCoe':1}});//恢复人材机单价调整系数为1。
+        datas.push({type:ModuleNames.project,data:{'ID' : projectObj.project.ID(),'property.hasTender': false}});
         me.updateTenderData(datas,function () {
             me.refreshTenderTreeByDatas(datas);
         });

+ 102 - 33
web/building_saas/pm/html/project-management-share.html

@@ -2,37 +2,106 @@
     <legend class="m-0 pb-1">分享</legend>
 </div>
 <div class="share-list" id="shareSpread">
-    <table class="table table-hover table-sm mb-5">
-        <thead>
-        <tr>
-            <th width="40%">工程列表</th>
-            <th width="10%">由...分享</th>
-            <th width="10%">分享给...</th>
-            <th width="10%">操作</th>
-        </tr>
-        </thead>
-        <tbody>
-        <!--别人共享给我有拷贝权限-->
-        <tr>
-            <td class="in-1">&nbsp;<a href="#">建筑工程2</a></td>
-            <td>由 <a href="javacript:void(0);" data-toggle="modal" data-target="#userinfo">张三</a> 分享</td>
-            <td>分享给 我</td>
-            <td><a href="javacript:void(0);" data-toggle="modal" data-target="#copytomy">拷贝工程</a></td>
-        </tr>
-        <!--别人共享给我无拷贝权限-->
-        <tr>
-            <td class="in-1">&nbsp;<a href="#">建筑工程2</a></td>
-            <td>由 <a href="javacript:void(0);" data-toggle="modal" data-target="#userinfo">张三</a> 分享</td>
-            <td>分享给 我</td>
-            <td></td>
-        </tr>
-        <!--我分享给别人-->
-        <tr>
-            <td class="in-1">&nbsp;<a href="#">建筑工程2</a></td>
-            <td>由 我 分享</td>
-            <td>分享给 <a href="javacript:void(0);" data-toggle="modal" data-target="#userinfo2">张三 <i class="fa fa-files-o"></i></a>、<a href="javacript:void(0);" data-toggle="modal" data-target="#userinfo2">王五</a></td>
-            <td><a href="javacript:void(0);" data-toggle="modal" data-target="#share">添加分享</a></td>
-        </tr>
-        </tbody>
-    </table>
+</div>
+<!--弹出账号信息-->
+<div class="modal fade" id="userinfo" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">用户信息</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="card">
+                    <div class="card-body">
+                        <h4 class="card-title">张三</h4>
+                        <h6 class="card-subtitle mb-2 text-muted">珠海纵横创新软件有限公司</h6>
+                    </div>
+                    <ul class="list-group list-group-flush">
+                        <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="通行账号手机"><i class="fa fa-tablet"></i> 15812644017</li>
+                        <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="通行账号邮箱"><i class="fa fa-envelope-o "></i> 0756-3850891</li>
+                    </ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--弹出拷贝工程-->
+<div class="modal fade" id="copyShare" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">拷贝工程</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>建设项目</label>
+                    <select id="copyShare_selectProj" class="form-control"><option>请选择建设项目</option></select>
+                    <span style="display: none" id="copyShareProj-info" class="form-text text-danger">建设项目不可为空</span>
+                </div>
+                <div class="form-group">
+                    <label>单项项目</label>
+                    <select id="copyShare_selectEng" class="form-control"><option>请选择单项工程</option></select>
+                    <span style="display: none" id="copyShareEng-info" class="form-text text-danger">单项工程不可为空</span>
+                </div>
+                <div class="form-group">
+                    <p id="copyShare_name">拷贝后,工程将重命名为 "<b>建筑工程2(张三共享)</b>"</p>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <a id="copyShare_confirm" href="javascript:void(0);" class="btn btn-primary">确定拷贝</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--弹出分享给交互-->
+<div class="modal fade" id="shareTo" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content" style="width: 750px;">
+            <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 modal-fixed-height">
+           <!--     <p>勾选需要恢复的文件,点“确定”按钮,确认从回收站中恢复。</p>-->
+                <table class="table table-hover table-sm mb-5">
+                    <thead>
+                    <tr style="display: block;">
+                        <th width="106px">姓名</th>
+                        <th width="146px">公司</th>
+                        <th width="146px">手机</th>
+                        <th width="156px">邮箱</th>
+                        <th width="70px">允许拷贝</th>
+                        <th width="70px">取消分享</th>
+                    </tr>
+                    </thead>
+                    <tbody id="shareToInfo" style="display:block; height: 300px; overflow: auto;">
+                    <tr>
+                        <td width="106px;">钟泽伟</td>
+                        <td width="146px;">珠海纵横创新软件有限公司</td>
+                        <td width="146px;">13160675110</td>
+                        <td width="156px;">707820685@qq.com</td>
+                        <td width="70px;" style="text-align: center"><input type="checkbox"></td>
+                        <td width="70px;" style="text-align: center"><input type="checkbox"></td>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <a href="javascript:void(0);" class="btn btn-primary" id="shareToConfirm" data-dismiss="modal">确定</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
 </div>

+ 4 - 3
web/building_saas/pm/html/project-management.html

@@ -306,7 +306,7 @@
                         <label>计价方式</label>
                         <div style="margin-left: 5px; border-radius: .25rem;"  class="row">
                             <label class="custom-control custom-radio" style="margin-left: 20px;">
-                                <input name="valuation_type" id="radioBill" value="bill" type="radio" class="custom-control-input">
+                                <input name="valuation_type" checked id="radioBill" value="bill" type="radio" class="custom-control-input">
                                 <label class="custom-control-label" for="radioBill">清单计价</label>
                             </label>
                           <!--  <label class="custom-control custom-radio" style="margin-left: 5px;">
@@ -465,8 +465,8 @@
                 <p class="">删除后,你可以在回收站找到它。</p>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="fileDelCancel">取消</button>
                 <a href="javascript:void(0);" class="btn btn-danger" id="fileDelConfirm">删除</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="fileDelCancel">取消</button>
             </div>
         </div>
     </div>
@@ -508,8 +508,8 @@
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 <a id="share-confirm" href="javascript:void(0);" class="btn btn-primary">确定分享</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
             </div>
         </div>
     </div>
@@ -531,6 +531,7 @@
 <script src="/web/building_saas/pm/js/pm_ajax.js"></script>
 <script src="/web/building_saas/pm/js/pm_newMain.js"></script>
 <script src="/web/building_saas/pm/js/pm_gc.js"></script>
+<script src="/web/building_saas/pm/js/pm_share.js"></script>
 <!-- zTree -->
 <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
 <script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>

+ 0 - 29
web/building_saas/pm/js/pm_gc.js

@@ -127,35 +127,6 @@ const gcTreeObj = {
         if(newSel){
             me.setSelStyle(newSel, projTreeObj.setting.style.selectedColor);
         }
-        $(".tools-btn > a").not(".disabled").addClass("disabled");
-        $("#add-engineering-btn").addClass("disabled");
-        $('#add-tender-btn').removeClass('disabled');
-        if(node){
-            switch(node.data.projType) {
-                case projectType.project:
-                    $("#del-btn").removeClass("disabled");
-                    $("#add-engineering-btn").removeClass("disabled");
-                    break;
-                case projectType.folder:
-                    if(!node.children || node.children.length === 0){
-                        $("#del-btn").removeClass("disabled");
-                    }
-                    break;
-                case projectType.engineering:
-                    $("#del-btn").removeClass("disabled");
-                    $("#add-engineering-btn").removeClass("disabled");
-                    break;
-                case projectType.tender:
-                    $("#add-engineering-btn").removeClass("disabled");
-                    $("#move-to-btn").removeClass("disabled");
-                    $("#copy-to-btn").removeClass("disabled");
-                    $("#share-btn").removeClass("disabled");
-                    $("#cooperate-btn").removeClass("disabled");
-                    $("#del-btn").removeClass("disabled");
-                    break;
-            }
-            $("#rename-btn").removeClass("disabled");
-        }
     },
     onSelectionChanging: function (sender, args) {
         let me = gcTreeObj;

+ 29 - 13
web/building_saas/pm/js/pm_newMain.js

@@ -319,7 +319,7 @@ const projTreeObj = {
         me.tree.selected = node;
         shareSeleted = node;
         me.preSelection = newSel;
-        $(".tools-btn > a").not(".disabled").addClass("disabled");
+       /* $(".tools-btn > a").not(".disabled").addClass("disabled");
         $("#add-engineering-btn").addClass("disabled");
         $('#add-tender-btn').removeClass('disabled');
         if(node){
@@ -347,7 +347,7 @@ const projTreeObj = {
                     break;
             }
             $("#rename-btn").removeClass("disabled");
-        }
+        }*/
     },
     onSelectionChanging: function (sender, args) {
         let me = projTreeObj;
@@ -992,6 +992,7 @@ $(document).ready(function() {
     $(window).resize(function () {
         autoPmWdith(projTreeObj.workBook, projTreeObj.setting.header);
         autoPmWdith(gcTreeObj.workBook, gcTreeObj.setting.header);
+        autoPmWdith(pmShare.spreadObj.workBook, pmShare.headers)
 
     });
 
@@ -1057,14 +1058,19 @@ $(document).ready(function() {
         let type = $(this).val();
         let targetData = type === 'bill' ? JSON.parse(billValuation) : JSON.parse(rationValuation);
         let html = '<option value="">请选择计价规则</option>';
-        for(let valuation of targetData) {
+        for(let i = targetData.length - 1; i >=0; i--){
+            let valuation = targetData[i];
             if (valuation === null) {
                 continue;
             }
-            html += '<option value="'+ valuation._id +'">'+ valuation.name +'</option>';
+            html += `<option ${i === targetData.length -1 ? 'selected' : ''} value="${valuation._id}">${valuation.name}</option>`;
         }
         $("#valuation").html(html);
-        $("#tender-engineering").html('<option value="">请选择对应的工程专业</option>');
+        //$("#tender-engineering").html('<option value="">请选择对应的工程专业</option>');
+        let engineeringList = getEngineeringList();
+        let engineeringHtml = getEngineeringHtml(engineeringList);
+        $("#tender-engineering").html(engineeringHtml);
+        changeEngineering();
     });
 
     //选择计价规则
@@ -1073,6 +1079,7 @@ $(document).ready(function() {
         let engineeringHtml = getEngineeringHtml(engineeringList);
         $("#tender-engineering").html(engineeringHtml);
         $('#valuation-info').hide();
+        changeEngineering();
     });
 
     // 新增单项项目点击
@@ -1362,11 +1369,11 @@ $(document).ready(function() {
         projectData['ParentID'] = parent.id();
         projectData['NextSiblingID'] = nextID;
         projectData['property']['rootProjectID'] = parent.pid();
+        projectData['shareInfo'] = [];
         let rename = projTreeObj.projectNameChecking(parent,originalNode,"复制");//重名检查
         rename? projectData['name'] = rename:'';
         projectMap['copy'] = {document:projectData};
         $("#copy-to-dialog").modal('hide');
-
         $.bootstrapLoading.start();
         CommonAjax.post('/pm/api/copyProjects',{projectMap:projectMap,user_id: userID},function (result) {
             console.log(result);
@@ -1377,15 +1384,13 @@ $(document).ready(function() {
         })
 
     });
-
-    // 选择工程专业后动态更改费率文件等数据
-    $("#tender-engineering").change(function() {
+    function changeEngineering(){
         $('#engineering-info').hide();
         let engineeringList = getEngineeringList();
         if(engineeringList.length === 0){
             return false;
         }
-        let selectedEngineering = $(this).val();
+        let selectedEngineering = $("#tender-engineering").val();
         selectedEngineering = parseInt(selectedEngineering);
         let currentLib = {};
         for(let engineering of engineeringList) {
@@ -1401,7 +1406,11 @@ $(document).ready(function() {
         if (currentLib.fee_lib !== undefined && currentLib.fee_lib.length > 0) {
             $("#tender-fee-rate").children("option").first().val("newFeeRate-"+currentLib.fee_lib[0].id);
         }
-        $(this).parent().siblings('.hidden-area').slideDown('fast');
+        $("#tender-engineering").parent().siblings('.hidden-area').slideDown('fast');
+    }
+    // 选择工程专业后动态更改费率文件等数据
+    $("#tender-engineering").change(function() {
+        changeEngineering()
     });
 });
 
@@ -2436,12 +2445,19 @@ function getEngineeringHtml(engineeringList) {
         engineeringObject[tmp.value] = tmp.name;
     }
 
-    for(let tmp of engineeringList) {
+    for(let i = 0; i < engineeringList.length; i++){
+        let tmp = engineeringList[i];
         if (engineeringObject[tmp.engineering] !== undefined) {
-            result += '<option value="'+ tmp.engineering +'">'+ engineeringObject[tmp.engineering] +'</option>';
+            result += `<option ${i === 0 ? 'selected' : ''} value="${tmp.engineering}">${engineeringObject[tmp.engineering]}</option>`;
         }
     }
 
+    /*for(let tmp of engineeringList) {
+        if (engineeringObject[tmp.engineering] !== undefined) {
+            result += '<option value="'+ tmp.engineering +'">'+ engineeringObject[tmp.engineering] +'</option>';
+        }
+    }*/
+
     return result;
 }
 

+ 667 - 14
web/building_saas/pm/js/pm_share.js

@@ -10,10 +10,22 @@
 
 const pmShare = (function () {
     const spreadDom = $('#shareSpread');
-    let spread = null;
+    let spreadObj = {workBook: null, sheet: null};
+    //项目分享类型,由别人分享给自己的,和自己分享给别人的
+    const shareType = {receive: 'receive', shareTo: 'shareTo'};
+    let tree = null;
+    const treeSetting = {
+        tree: {
+            id: 'ID',
+            pid: 'ParentID',
+            nid: 'NextSiblingID',
+            rootId: -1,
+            autoUpdate: false
+        }
+    };
     const headers = [
         {name: '工程列表', dataCode: 'name', width: 0.55, vAlign: 'center', hAlign: 'left'},
-        {name: '由...分享', dataCode: 'from', width: 0.15, vAlign: 'center', hAlign: 'right'},
+        {name: '由...分享', dataCode: 'from', width: 0.15, vAlign: 'center', hAlign: 'left'},
         {name: '分享给...', dataCode: 'to', width: 0.15, vAlign: 'center', hAlign: 'left'},
         {name: '操作', dataCode: 'operation', width: 0.15, vAlign: 'center', hAlign: 'left'},
     ];
@@ -33,7 +45,38 @@ const pmShare = (function () {
             clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
         }
     };
-
+    const spreadEvents = {
+        SelectionChanging: function (sender, info) {
+            initSelection(info.newSelections[0], info.oldSelections[0]);
+        }
+    };
+    //设置选中行底色
+    //@param
+    function setSelStyle(sel, backColor,sheet) {
+        sel.row = sel.row === -1 ? 0 : sel.row;
+        renderSheetFunc(sheet, function () {
+            let style = projTreeObj.getSelStyle(backColor);
+            for(let i = 0; i < sel.rowCount; i++){
+                let row = i + sel.row;
+                sheet.setStyle(row, -1, style);
+            }
+        });
+    }
+    //初始化焦点
+    //@param {Object}newSel {Object}oldSel @return {void}
+    function initSelection(newSel, oldSel = null) {
+        let node = tree.items[newSel.row];
+        tree.selected = node;
+        shareSeleted = node;
+        //恢复底色
+        if(oldSel){
+            setSelStyle(oldSel, projTreeObj.setting.style.defalutBackColor, spreadObj.sheet);
+        }
+        //设置选中行底色
+        if(newSel){
+            setSelStyle(newSel, projTreeObj.setting.style.selectedColor, spreadObj.sheet);
+        }
+    }
     //渲染时方法,停止渲染
     //@param {Object}sheet {Function}func @return {void}
     function renderSheetFunc(sheet, func){
@@ -61,9 +104,10 @@ const pmShare = (function () {
         let fuc = function () {
             sheet.setColumnCount(headers.length);
             sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            let spreadWidth = getWorkBookWidth();
             for(let i = 0, len = headers.length; i < len; i++){
                 sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
-                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, spreadWidth * headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
                 if(headers[i].formatter){
                     sheet.setFormatter(-1, i, headers[i].formatter);
                 }
@@ -87,22 +131,631 @@ const pmShare = (function () {
     //建表
     //
     function buildSheet(){
-        if(spread){
-            spread.destroy();
+        spreadObj.workBook = new GC.Spread.Sheets.Workbook(spreadDom[0], {sheetCount: 1});
+        spreadObj.sheet = spreadObj.workBook.getActiveSheet();
+        setSpreadOptions(spreadObj.workBook, spreadOpts);
+        bindEvent(spreadObj.workBook, spreadEvents);
+        buildHeader(spreadObj.sheet, headers);
+        //全表不可编辑
+        spreadObj.sheet.getRange(-1, -1, -1, -1).locked(true);
+
+    }
+    //此项目是否可以拷贝
+    //@param {String}userID {Object}project @return {Boolean}
+    function isAllowCopy(userID, project){
+        for(let shareData of project.shareInfo){
+            if(shareData.userID === userID){
+                return shareData.allowCopy;
+            }
+        }
+        return false;
+    }
+    //
+    //
+    function getTreeNodeCell(tree){
+        let indent = 20;
+        let levelIndent = -5;
+        let halfBoxLength = 5;
+        let halfExpandLength = 3;
+        let imgWidth = 18;
+        let imgHeight = 14;
+        let TreeNodeCellType = function () {
+        };
+        TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
+        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            if (style.backColor) {
+                ctx.save();
+                ctx.fillStyle = style.backColor;
+                ctx.fillRect(x, y, w, h);
+                ctx.restore();
+            } else {
+                ctx.clearRect(x, y, w, h);
+            }
+            let drawLine = function (canvas, x1, y1, x2, y2, color) {
+                ctx.save();
+                ctx.translate(0.5, 0.5);
+                ctx.beginPath();
+                ctx.moveTo(x1, y1);
+                ctx.lineTo(x2, y2);
+                ctx.strokeStyle = color;
+                ctx.stroke();
+                ctx.restore();
+            };
+            let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
+                let rect = {}, h1, h2, offset = 1;
+                rect.top = centerY - halfBoxLength;
+                rect.bottom = centerY + halfBoxLength;
+                rect.left = centerX - halfBoxLength;
+                rect.right = centerX + halfBoxLength;
+
+                if (rect.left < x + w) {
+                    rect.right = Math.min(rect.right, x + w);
+
+                    ctx.save();
+                    ctx.translate(0.5, 0.5);
+                    ctx.strokeStyle = 'black';
+                    ctx.beginPath();
+                    ctx.moveTo(rect.left, rect.top);
+                    ctx.lineTo(rect.left, rect.bottom);
+                    ctx.lineTo(rect.right, rect.bottom);
+                    ctx.lineTo(rect.right, rect.top);
+                    ctx.lineTo(rect.left, rect.top);
+                    ctx.stroke();
+                    ctx.fillStyle = 'white';
+                    ctx.fill();
+                    ctx.restore();
+
+                    // Draw Horizontal Line
+                    h1 = centerX - halfExpandLength;
+                    h2 = Math.min(centerX + halfExpandLength, x + w);
+                    if (h2 > h1) {
+                        drawLine(ctx, h1, centerY, h2, centerY, 'black');
+                    }
+                    // Draw Vertical Line
+                    if (!expanded && (centerX < x + w)) {
+                        drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
+                    }
+                }
+
+            }
+            let node = tree.items[options.row];
+            let showTreeLine = true;
+            if (!node) { return; }
+
+            let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2;
+            let x1 = centerX + indent / 2;
+            let centerY = Math.floor((y + (y + h)) / 2);
+            let y1;
+            // Draw Sibling Line
+            if (showTreeLine) {
+                // Draw Horizontal Line
+                if (centerX < x + w) {
+                    drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray');
+                    let img;
+                    if(node.data.projType === projectType.folder){
+                        img = document.getElementById('folder_open_pic');
+                        imgWidth = 15;
+                    }
+                    else if(node.data.projType === projectType.project){
+                        img = document.getElementById('proj_pic');
+                        imgWidth = 18;
+                    }
+                    else if(node.data.projType === projectType.engineering){
+                        img = document.getElementById('eng_pic');
+                        imgWidth = 14;
+                    }
+                    else if(node.data.projType === projectType.tender){
+                        img = document.getElementById('tender_pic');
+                        imgWidth = 14;
+                    }
+                    ctx.drawImage(img, centerX+indent/2+3, centerY - 7, imgWidth,imgHeight);
+                }
+                // Draw Vertical Line
+                if (centerX < x + w) {
+                    y1 = node.isLast() ? centerY : y + h;
+                    if (node.isFirst() && !node.parent.parent) {
+                        drawLine(ctx, centerX, centerY, centerX, y1, 'gray');
+                    } else {
+                        drawLine(ctx, centerX, y, centerX, y1, 'gray');
+                    }
+                }
+            }
+            // Draw Expand Box
+            if (node.children.length > 0) {
+                drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
+            }
+            // Draw Parent Line
+            if (showTreeLine) {
+                var parent = node.parent, parentCenterX = centerX - indent - levelIndent;
+                while (parent.parent) {
+                    if (!parent.isLast()) {
+                        if (parentCenterX < x + w) {
+                            drawLine(ctx, parentCenterX, y, parentCenterX, y + h, 'gray');
+                        }
+                    }
+                    parent = parent.parent;
+                    parentCenterX -= (indent + levelIndent);
+                }
+            };
+            // Draw Text
+            arguments[2] = x + (node.depth() + 1) * indent +  node.depth() * levelIndent + imgWidth + 3;
+            arguments[4] = w - (node.depth() + 1) * indent - node.depth() * levelIndent - imgWidth - 3;
+            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
+        };
+        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            let info = {x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea};
+            let node = tree.items[info.row];
+            let offset = -1;
+            let centerX = info.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
+            let text = context.sheet.getText(info.row, info.col);
+            let value = context.sheet.getValue(info.row, info.col);
+            let acStyle = context.sheet.getActualStyle(info.row, info.col),
+                zoom = context.sheet.zoom();
+            let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: context.sheet, row: info.row, col: info.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
+            if(info.x > centerX + halfBoxLength && info.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength){
+                info.isReservedLocation = true;
+            }
+            return info;
+        };
+        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
+            let offset = -1;
+            let node = tree.items[hitinfo.row];
+            tree.selected = node;
+            let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
+            let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;;
+            if (!node || node.children.length === 0) { return; }
+
+            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+                node.setExpanded(!node.expanded);
+                TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
+                    let iCount = node.posterityCount(), i, child;
+                    for (i = 0; i < iCount; i++) {
+                        child = tree.items[hitinfo.row + i + 1];
+                        hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
+                    }
+                    hitinfo.sheet.invalidateLayout();
+                });
+                hitinfo.sheet.repaint();
+            }
+        };
+        return new TreeNodeCellType();
+    }
+    //
+    //
+    function getInteractionCell() {
+        let InteractionCell = function () {
+        };
+        InteractionCell.prototype = new GC.Spread.Sheets.CellTypes.Text();
+        InteractionCell.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea,
+                isReservedLocation: true
+            };
+        };
+        InteractionCell.prototype.processMouseDown = function (hitinfo) {
+            let dataCode = headers[hitinfo.col]['dataCode'];
+            let node = tree.items[hitinfo.row];
+            let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
+            let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
+            let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
+                zoom = hitinfo.sheet.zoom();
+            let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
+            if(hitinfo.x - hitinfo.cellRect.x > 0 && hitinfo.x - hitinfo.cellRect.x < textLength){
+                //由..分享,弹出分享者信息
+                if(dataCode === 'from'){
+                    if(node.data.shareType === shareType.receive){
+                        $('#userinfo').find('h4').text(node.data.userInfo.name);
+                        $('#userinfo').find('h6').text(node.data.userInfo.company);
+                        let mobileHtml = `<i class="fa fa-tablet"> ${node.data.userInfo.mobile ? node.data.userInfo.mobile : ''}</i>`;
+                        $('#userinfo').find('li:first-child').html(mobileHtml);
+                        let emailHtml = `<i class="fa fa-envelope-o"> ${node.data.userInfo.email ? node.data.userInfo.email : ''}</i>`;
+                        $('#userinfo').find('li:last-child').html(emailHtml);
+                        $('#userinfo').modal('show');
+                    }
+                }
+                //分享给
+                else if(dataCode === 'to'){
+                    if(node.data.shareType === shareType.shareTo){
+                        setShareToModal(node);
+                        $('#shareTo').modal('show');
+                    }
+                }
+                //操作
+                else if(dataCode === 'operation'){
+                    if(node.data.operation === '添加分享'){
+                        $('#sharePhone').val('');
+                        $('#share-info').hide();
+                        $('#share').find('.card').hide();
+                        $('#share').modal('show');
+                        $('#allowCopy').prop('checked', false);
+                        $('#allowCopyHint').hide();
+                    }
+                    else if(node.data.operation === '拷贝工程'){
+                        $('#copyShare').modal('show');
+                    }
+                    else {
+                        return;
+                    }
+                }
+                //清除
+                else if(dataCode === 'delete'){
+                    gcTreeObj.oprProj('#delPoj', node)
+                }
+                //恢复单价文件
+                else if(dataCode === 'unitPriceFile'){
+                    gcTreeObj.recoveryUnitPrc(node);
+                }
+                //清除单价文件
+                else if(dataCode === 'unitPriceFile_delete'){
+                    gcTreeObj.deleteUnitPrc(node);
+                }
+                //恢复费率文件
+                else if(dataCode === 'feeRateFile'){
+                    gcTreeObj.recoveryFeeRate(node);
+                }
+                //清除费率文件
+                else if(dataCode === 'feeRateFile_delete'){
+                    gcTreeObj.deleteFeeRate(node);
+                }
+            }
+        };
+        InteractionCell.prototype.processMouseMove = function (hitInfo) {
+            let dataCode = headers[hitInfo.col]['dataCode'];
+            let node = tree.items[hitInfo.row];
+            let sheet = hitInfo.sheet;
+            let div = sheet.getParent().getHost();
+            let canvasId = div.id + "vp_vp";
+            let canvas = $(`#${canvasId}`)[0];
+            //改变鼠标图案
+            let text = hitInfo.sheet.getText(hitInfo.row, hitInfo.col);
+            let value = hitInfo.sheet.getValue(hitInfo.row, hitInfo.col);
+            let acStyle = hitInfo.sheet.getActualStyle(hitInfo.row, hitInfo.col),
+                zoom = hitInfo.sheet.zoom();
+            let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitInfo.sheet, row: hitInfo.row, col: hitInfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
+            if (sheet && hitInfo.x - hitInfo.cellRect.x >  0 && hitInfo.x - hitInfo.cellRect.x < textLength) {
+                canvas.style.cursor='pointer';
+                return true;
+            }else{
+                canvas.style.cursor='default';
+            }
+            return false;
+        };
+        return new InteractionCell();
+    }
+    //设置分享给界面数据
+    //@param {Object}selected @return {void}
+    function setShareToModal(selected){
+        $('#shareToInfo').empty();
+        if(!selected){
             return;
         }
-        spread = new GC.Spread.Sheets.Workbook(spreadDom[0], {sheetCount: 1});
-        setSpreadOptions(spread, spreadOpts);
-        const sheet = spread.getActiveSheet();
-        buildHeader(sheet, headers);
-        //全表不可编辑
-        sheet.getRange(-1, -1, -1, -1).locked(true);
+        let userIDs = [];
+        for(let user of selected.data.shareInfo){
+            userIDs.push(user.userID);
+        }
+        CommonAjax.post('/user/getUsers', {userIDs: userIDs}, function (rstData) {
+            for(let userInfo of rstData){
+                for(let user of selected.data.shareInfo){
+                    if(user.userID === userInfo._id){
+                        user.name = userInfo.real_name;
+                        user.company = userInfo.company;
+                        user.mobile = userInfo.mobile;
+                        user.email = userInfo.email;
+                    }
+                }
+            }
+            let infoArr = [];
+            for(let user of selected.data.shareInfo){
+                let infoHtml = `<tr>
+                                          <td style="width: 106px;">${user.name}</td>
+                                          <td style="width: 146px;">${user.company}</td>
+                                          <td style="width: 146px;">${user.mobile}</td>
+                                          <td style="width: 156px;">${user.email}</td>
+                                          <td style="width: 70px;text-align: center"><input value="allowCopy" ${user.allowCopy ? 'checked' : ''} type="checkbox"></td>
+                                          <td style="width: 70px;text-align: center"><input value="cancelShare" type="checkbox"></td>
+                               </tr>`;
+                infoArr.push(infoHtml);
+            }
+            let infoHtml = infoArr.join('');
+            $('#shareToInfo').html(infoHtml);
+        });
+    }
+    //更新项目分享信息
+    //@param {Object}selected
+    function updateShareInfo(selected){
+        if(!selected){
+            return;
+        }
+        let usersTr = $('#shareToInfo').find('tr');
+        let newShareInfo = [];
+        for(let i = 0; i < usersTr.length; i++){
+            let userTr = usersTr[i];
+            let allowCopy = $(userTr).find('input:first').prop('checked');
+            let cancelShare = $(userTr).find('input:last').prop('checked');
+            selected.data.shareInfo[i].allowCopy = allowCopy;
+            if(!cancelShare){
+                newShareInfo.push(selected.data.shareInfo[i]);
+            }
+        }
+        CommonAjax.post('/pm/api/updateProjects', {user_id: userID, updateData: [{updateType: 'update', updateData: {ID: selected.data.ID, shareInfo: newShareInfo}}]}, function () {
+            selected.data.shareInfo = newShareInfo;
+            if(newShareInfo.length === 0){
+                renderSheetFunc(spreadObj.sheet, function () {
+                    let rIdx = selected.serialNo();
+                    tree.removeNode(selected);
+                    spreadObj.sheet.deleteRows(rIdx, 1);
+                    spreadObj.sheet.setRowCount(tree.items);
+                    initSelection({row: spreadObj.sheet.getActiveRowIndex(), rowCount: 1},null);
+
+                });
+            }
+        });
+    }
+    const foreColor = '#007bff';
+    //显示树结构数据
+    //@param {Array}nodes {Array}headers @return {void}
+    function showTreeData(nodes, headers){
+        let sheet = spreadObj.workBook.getActiveSheet();
+        let fuc = function(){
+            sheet.setRowCount(nodes.length);
+            for(let i = 0; i < nodes.length; i++){
+                let treeNodeCell = getTreeNodeCell(tree);
+                sheet.getCell(i, 0).cellType(treeNodeCell);
+                for(let j = 0; j < headers.length; j++){
+                    sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
+                    sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
+                    let dataCode = headers[j].dataCode;
+                    if(dataCode === 'operation'){
+                        let style = new GC.Spread.Sheets.Style();
+                        style.foreColor = foreColor;
+                        sheet.setStyle(i, j, style);
+                        sheet.getCell(i, j).cellType(getInteractionCell());
+                    }
+                    else if(dataCode === 'from'){
+                        if(nodes[i].data.shareType && nodes[i].data.shareType === shareType.receive){
+                            let style = new GC.Spread.Sheets.Style();
+                            style.foreColor = foreColor;
+                            sheet.setStyle(i, j, style);
+                            sheet.getCell(i, j).cellType(getInteractionCell());
+                        }
+                    }
+                    else if(dataCode === 'to'){
+                        if(nodes[i].data.shareType && nodes[i].data.shareType === shareType.shareTo){
+                            let style = new GC.Spread.Sheets.Style();
+                            style.foreColor = foreColor;
+                            sheet.setStyle(i, j, style);
+                            sheet.getCell(i, j).cellType(getInteractionCell());
+                        }
+                    }
+                   /* else if(dataCode === 'delete' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile_delete'){
+                        let style = new GC.Spread.Sheets.Style();
+                        style.foreColor = me.setting.style.delForeColor;
+                        sheet.setStyle(-1, j, style);
+                    }*/
+                    sheet.setValue(i, j, nodes[i].data[dataCode] ? nodes[i].data[dataCode] : '');
+                    //me.setCellValue({row: i, col: j}, nodes[i]);
+                }
+            }
+        };
+        renderSheetFunc(sheet, fuc);
+    }
+    //将数据转换为可成树的数据,因为获取的数据不来自同一棵树
+    //@param {Array}datas
+    function buildTreeDatas(datas){
+        let IDMap = {};
+        for(let i = 0; i < datas.length; i++){
+            let data = datas[i];
+            let nextData = datas[i + 1];
+            data.NextSiblingID = nextData ? nextData.ID : -1;
+            data.ParentID = -1;
+            IDMap[data.ID] = data;
+            if(data.shareType === shareType.receive){
+                if(data.userInfo){
+                    data.from = `由 ${data.userInfo.name} 分享`;
+                    data.to = '分享给 我';
+                    data.operation = isAllowCopy(userID, data) ? '拷贝工程' : '';
+                }
+            }
+            else {
+                data.from = '由 我 分享';
+                data.to = '分享给...';
+                data.operation = '添加分享';
+            }
+        }
+    }
+    //建立树
+    //@return void
+    function initShareTree(){
+        $.bootstrapLoading.start();
+        //获取分享数据
+        CommonAjax.post('/pm/api/getShareProjects', {user_id: userID}, function (rstData) {
+            let projDatas = rstData.receive.concat(rstData.share);
+            buildTreeDatas(projDatas);
+            tree = pmTree.createNew(treeSetting, projDatas);
+            console.log(tree);
+            tree.selected = tree.items[0];
+            showTreeData(tree.items, headers);
+            //初始选择
+            let initSel = spreadObj.sheet.getSelections()[0] ? spreadObj.sheet.getSelections()[0] : {row: 0, rowCount: 1};
+            initSelection(initSel);
+            autoFlashHeight();
+            spreadObj.workBook.refresh();
+            $.bootstrapLoading.end();
+        });
+    }
+    //初始化视图
+    //@return void
+    function initView(){
+        if(tree){
+            tree = null;
+        }
+        if(spreadObj.workBook){
+            spreadObj.workBook.destroy();
+            spreadObj.workBook = null;
+        }
+        buildSheet();
+        initShareTree();
+    }
+    //根据建设项目获取单项工程
+    //@param {Number}projID @return {void}
+    function setEng(projID){
+        let engQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], projType: projectType.engineering, userID: userID, ParentID: projID};
+        CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: engQuery, options: '-_id -property'}, function (rstData) {
+            $('#copyShare_selectEng').empty();
+            for(let eng of rstData){
+                let opt = $('<option>').val(eng.ID).text(eng.name);
+                $('#copyShare_selectEng').append(opt);
+            }
+        });
+    }
+    //设置拷贝工程下拉选择
+    //@return {void}
+    function setCopyModal(){
+        //获取建设项目
+        let projQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], projType: projectType.project, userID: userID};
+        CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: projQuery, options: '-_id -property'}, function (rstData) {
+            $('#copyShare_selectProj').empty();
+            for(let proj of rstData){
+                let opt = $('<option>').val(proj.ID).text(proj.name);
+                $('#copyShare_selectProj').append(opt);
+            }
+            //初始选择
+            if(rstData.length > 0){
+                setEng(rstData[0].ID);
+            }
+        });
+    }
+    //拷贝分享的工程
+    //@param {Object}selected {Number}parentID @return {void}
+    function copyShareProject(selected, projID, engID){
+        if(!engID || !selected){
+            return;
+        }
+        let copyMap = {copy: null, update: null};
+        let newName = `${selected.data.name} (${selected.data.userInfo.name}共享)`;
+        //获取单项工程的最末单位工程
+        let tenderQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], userID: userID, ParentID: engID};
+        CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: tenderQuery, options: '-_id -property'}, function (rstData) {
+            let updateTender = null;
+            for(let tender of rstData){
+                if(tender.name === newName){
+                    $('#copyShare_name').text('已存在此单位工程。');
+                    $('#copyShare_name').addClass('text-danger');
+                    return;
+                }
+                if(tender.NextSiblingID == -1){
+                    updateTender = tender;
+                }
+            }
+            //更新前节点
+            if(updateTender){
+                copyMap.update = {query: {ID: updateTender.ID}};
+            }
+            //拷贝
+            let copyData = {
+                userID: userID,
+                ID: selected.data.ID,
+                NextSiblingID: -1,
+                ParentID: engID,
+                name: newName,
+                shareInfo: [],
+                compilation: selected.data.compilation,
+                createDateTime: selected.data.createDateTime,
+                fileVer: selected.data.fileVer ? selected.data.fileVer : '',
+                projType: selected.data.projType,
+                property: selected.data.property,
+                recentDateTime: selected.data.recentDateTime,
+                fullFolder: selected.data.fullFolder
+            };
+            copyData.property.rootProjectID = projID;
+            copyMap.copy = {document: copyData};
+            $('#copyShare').modal('hide');
+            $.bootstrapLoading.start();
+            CommonAjax.post('/pm/api/copyProjects', {projectMap: copyMap, user_id: userID}, function (rstData) {
+                $.bootstrapLoading.end();
+            }, function () {
+                $.bootstrapLoading.end();
+            });
+        });
 
     }
+    //事件监听器
+    //@return void
+    function eventListener(){
+        //tab
+        $('#tab_pm_share').on('shown.bs.tab', function () {
+            projTreeObj.tree = null;
+            if(projTreeObj.workBook){
+                projTreeObj.workBook.destroy();
+                projTreeObj.workBook = null;
+            }
+            gcTreeObj.tree = null;
+            if(gcTreeObj.workBook){
+                gcTreeObj.workBook.destroy();
+                gcTreeObj.workBook = null;
+            }
+            initView();
+        });
+        //关闭拷贝工程
+        $('#copyShare').on('hidden.bs.modal', function () {
+            $('#copyShareProj-info').hide();
+            $('#copyShareEng-info').hide();
+        });
+        //打开拷贝工程
+        $('#copyShare').on('shown.bs.modal', function () {
+            setCopyModal();
+            //更改显示名称
+            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}共享)`;
+            $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
+            $('#copyShare_name').removeClass('text-danger');
+        });
+        //拷贝工程改变选择建设项目
+        $('#copyShare_selectProj').change(function () {
+            //更改显示名称
+            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}共享)`;
+            $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
+            $('#copyShare_name').removeClass('text-danger');
+            $('#copyShareProj-info').hide();
+            $('#copyShareEng-info').hide();
+            let curSelID = $(this).select().val();
+            setEng(parseInt(curSelID));
+        });
+        //拷贝工程改变选择单项工程
+        $('#copyShare_selectEng').change(function () {
+            //更改显示名称
+            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}共享)`;
+            $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
+            $('#copyShare_name').removeClass('text-danger');
+        });
+        //确认拷贝
+        $('#copyShare_confirm').click(function () {
+            let selProj = $('#copyShare_selectProj').select().val();
+            if(!selProj){
+                $('#copyShareProj-info').show();
+                return;
+            }
+            let selEng = $('#copyShare_selectEng').select().val();
+            if(!selEng){
+                $('#copyShareEng-info').show();
+                return;
+            }
+            copyShareProject(tree.selected, parseInt(selProj), parseInt(selEng));
+        });
+        //分享给...界面确认
+        $('#shareToConfirm').click(function () {
+            updateShareInfo(tree.selected);
+        });
+    }
 
-    return {buildSheet}
+    return {spreadObj, headers, initView, eventListener}
 })();
 
 $(document).ready(function () {
-
+    pmShare.eventListener();
 });