Forráskód Böngészése

分享相关、初始选择计价规则

zhongzewei 7 éve
szülő
commit
7cd701f316

+ 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);
+        }
     }
 };

+ 3 - 2
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;
     }
 

+ 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);

+ 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);

+ 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 );
 

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

@@ -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>

+ 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">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a id="copyShare_confirm" href="javascript:void(0);" class="btn btn-primary">确定拷贝</a>
+            </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();
 });