Browse Source

feat: 分享定额库相关

vian 4 years ago
parent
commit
239a038e92
49 changed files with 581 additions and 187 deletions
  1. 3 0
      config/gulpConfig.js
  2. 1 0
      modules/all_models/ration.js
  3. 18 0
      modules/all_models/share_lib.js
  4. 2 1
      modules/complementary_ration_lib/controllers/compleRationController.js
  5. 2 1
      modules/complementary_ration_lib/controllers/compleSectionTreeController.js
  6. 31 15
      modules/complementary_ration_lib/controllers/compleViewController.js
  7. 7 1
      modules/complementary_ration_lib/models/compleRationModel.js
  8. 27 16
      modules/complementary_ration_lib/models/searchModel.js
  9. 4 4
      modules/complementary_ration_lib/routes/routes.js
  10. 1 0
      modules/main/controllers/ration_controller.js
  11. 14 0
      modules/main/facade/ration_facade.js
  12. 79 4
      modules/pm/controllers/pm_controller.js
  13. 65 9
      modules/pm/facade/pm_facade.js
  14. 3 0
      modules/pm/routes/pm_route.js
  15. 9 1
      public/common_constants.js
  16. 28 0
      public/web/sheet/sheet_common.js
  17. 5 0
      web/building_saas/complementary_ration_lib/html/dinge.html
  18. 6 2
      web/building_saas/complementary_ration_lib/js/coe.js
  19. 68 2
      web/building_saas/complementary_ration_lib/js/init.js
  20. 5 5
      web/building_saas/complementary_ration_lib/js/installation.js
  21. 2 2
      web/building_saas/complementary_ration_lib/js/jobContent.js
  22. 11 5
      web/building_saas/complementary_ration_lib/js/ration.js
  23. 3 1
      web/building_saas/complementary_ration_lib/js/ration_assist.js
  24. 2 2
      web/building_saas/complementary_ration_lib/js/ration_coe.js
  25. 3 3
      web/building_saas/complementary_ration_lib/js/ration_glj.js
  26. 9 9
      web/building_saas/complementary_ration_lib/js/repository_glj.js
  27. 5 2
      web/building_saas/complementary_ration_lib/js/section_tree.js
  28. 2 2
      web/building_saas/main/js/views/calc_program_manage.js
  29. 2 2
      web/building_saas/main/js/views/config_material_view.js
  30. 1 1
      web/building_saas/main/js/views/fee_rate_view.js
  31. 1 1
      web/building_saas/main/js/views/index_view.js
  32. 2 2
      web/building_saas/main/js/views/item_increase_fee_view.js
  33. 1 1
      web/building_saas/main/js/views/main_tree_col.js
  34. 1 1
      web/building_saas/main/js/views/mbzm_view.js
  35. 4 4
      web/building_saas/main/js/views/project_glj_view.js
  36. 1 1
      web/building_saas/main/js/views/project_info.js
  37. 1 1
      web/building_saas/main/js/views/project_property_basicInfo.js
  38. 1 1
      web/building_saas/main/js/views/project_property_bills_quantity_decimal.js
  39. 1 1
      web/building_saas/main/js/views/project_property_labour_coe_view.js
  40. 1 1
      web/building_saas/main/js/views/project_property_projFeature.js
  41. 2 31
      web/building_saas/main/js/views/project_view.js
  42. 17 7
      web/building_saas/main/js/views/std_ration_lib.js
  43. 1 1
      web/building_saas/main/js/views/sub_fee_rate_views.js
  44. 3 3
      web/building_saas/main/js/views/sub_view.js
  45. 3 3
      web/building_saas/main/js/views/zmhs_view.js
  46. 1 1
      web/building_saas/pm/js/pm_newMain.js
  47. 1 1
      web/common/components/share/index.html
  48. 119 34
      web/common/components/share/index.js
  49. 2 2
      web/common/html/header.html

+ 3 - 0
config/gulpConfig.js

@@ -227,6 +227,9 @@ module.exports = {
         'lib/jquery-contextmenu/jquery.ui.position.js',
         'lib/ztree/jquery.ztree.core.js',
         'web/building_saas/complementary_ration_lib/js/global.js',
+        'lib/pinyinjs/pinyin_dict_firstletter.js',
+        'lib/pinyinjs/pinyinUtil.js',
+        'web/common/components/share/index.js',
         'public/web/id_tree.js',
         'public/web/tree_sheet/tree_sheet_controller.js',
         'public/web/tree_sheet/tree_sheet_helper.js',

+ 1 - 0
modules/all_models/ration.js

@@ -54,6 +54,7 @@ let rationSchema = new Schema({
     type: Number,                               // 1 定额、2 量价、3 工料机定额
     subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
     from:{type: String,default:'std'},          //std, cpt  来自标准、补充
+    fromUser: String, // 来自某个用户的定额(分享补充定额)
     isSubcontract: Boolean,                     // 是否分包
     installationKey:String,                   //用来记录安装增加费的关联字段
     // 定额特有属性:

+ 18 - 0
modules/all_models/share_lib.js

@@ -0,0 +1,18 @@
+// 分享库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const shareSchema = new Schema({
+    ID: String,
+    compilationID: String,
+    owner: String, // 拥有者ID
+    receiver: String, // 接收者ID
+    libType: Number, // 1: 定额库; 2: 人材机库; 3: 组件模板库;
+    allowCooperate: {
+        type: Boolean,
+        default: false
+    },
+    shareDate: String,
+    updateDate: String
+}, {versionKey: false});
+
+mongoose.model('share_libs', shareSchema, 'share_libs');

+ 2 - 1
modules/complementary_ration_lib/controllers/compleRationController.js

@@ -90,7 +90,8 @@ class CompleRationController extends BaseController{
             rations = [];
         try {
             if (data.type === libType.complementary) {
-                rations = await compleRationDao.getCompleRationBySection(req.session.sessionUser.id, data.sectionId);
+                const userID = data.owner || req.session.sessionUser.id;
+                rations = await compleRationDao.getCompleRationBySection(userID, data.sectionId);
             }  else {
                 rations = await compleRationDao.getRationGljItemsBySection(data.sectionId);
             }

+ 2 - 1
modules/complementary_ration_lib/controllers/compleSectionTreeController.js

@@ -20,7 +20,8 @@ class CompleSectionTreeController extends BaseController{
 
     getRationTree(req, res){
         let data = JSON.parse(req.body.data);
-        sectionTreeDao.getRationTree(req.session.sessionUser.id, req.session.sessionCompilation._id, data.rationRepId, data.type, function (err, data) {
+        const userID = data.owner || req.session.sessionUser.id;
+        sectionTreeDao.getRationTree(userID, req.session.sessionCompilation._id, data.rationRepId, data.type, function (err, data) {
             callback(req, res, err, '', data);
         });
     }

+ 31 - 15
modules/complementary_ration_lib/controllers/compleViewController.js

@@ -9,6 +9,8 @@ let config = require("../../../config/config.js");
 let compleViewModel = new CompleViewModel();
 const CompleRationDao = require('../models/compleRationModel');
 const compleRationDao = new CompleRationDao();
+const pmFacade = require('../../pm/facade/pm_facade');
+const { ShareLibType } = require('../../../public/common_constants');
 let callback = function (req, res, err, msg, data) {
     res.json({error: err, message: msg, data: data});
 };
@@ -38,13 +40,25 @@ async function getGljLibId(sessionCompilation) {
 
 class CompleViewController extends BaseController{
     async redirectRation(req, res){
+        const { userID } = req.params;
+        const sessionUserID = req.session.sessionUser.id;
+        const compilationID = req.session.sessionCompilation._id;
+        if (userID !== sessionUserID) {
+            const receiveList = await pmFacade.getReceiveLibList(sessionUserID, compilationID, ShareLibType.RATION_LIB);
+            const isValid = !!receiveList.find(user => String(user._id) === userID);
+            if (!isValid) {
+                return res.redirect(`/complementaryRation/ration/${sessionUserID}`);
+            }
+        }
         const gljLibId = await getGljLibId(req.session.sessionCompilation);
-        const redirectGlj = `/complementaryRation/glj`;
-        const redirectCoe = `/complementaryRation/coe`;
-        const redirectInstallation = `/complementaryRation/installation`;
+        const redirectGlj = `/complementaryRation/glj/${userID}`;
+        const redirectCoe = `/complementaryRation/coe/${userID}`;
+        const redirectInstallation = `/complementaryRation/installation/${userID}`;
         const priceProperties = req.session.sessionCompilation.priceProperties || [];
+        const isReadOnly = userID !== sessionUserID;
         res.render('building_saas/complementary_ration_lib/html/dinge.html', {
-            userID: req.session.sessionUser.id,
+            isReadOnly,
+            userID: sessionUserID,
             redirectGlj: redirectGlj,
             redirectCoe: redirectCoe,
             redirectInstallation: redirectInstallation,
@@ -58,10 +72,11 @@ class CompleViewController extends BaseController{
 
     async prepareInitData (req, res) {
         try {
+            const { userID } = req.query;
+            const sessionUserID = req.session.sessionUser.id;
             const gljLibId = await getGljLibId(req.session.sessionCompilation);
-            const userId = req.session.sessionUser.id;
             const compilationId = req.session.sessionCompilation._id;
-            const initData = await compleRationDao.prepareInitData(userId, compilationId, gljLibId);
+            const initData = await compleRationDao.prepareInitData(sessionUserID, userID, compilationId, gljLibId);
             res.json({error: 0, message: 'success', data: initData});
         } catch (err) {
             res.json({error: 1, message: 'fail', data: null});
@@ -69,10 +84,11 @@ class CompleViewController extends BaseController{
     }
 
     async redirectGljList(req, res){
+        const { userID } = req.params;
         const gljLibId = await getGljLibId(req.session.sessionCompilation);
-        const redirectRation = `/complementaryRation/ration`;
-        const redirectCoe = `/complementaryRation/coe`;
-        const redirectInstallation = `/complementaryRation/installation`;
+        const redirectRation = `/complementaryRation/ration/${userID}`;
+        const redirectCoe = `/complementaryRation/coe/${userID}`;
+        const redirectInstallation = `/complementaryRation/installation/${userID}`;
         res.render('building_saas/complementary_ration_lib/html/gongliao.html', {
             userID: req.session.sessionUser.id,
             redirectRation: redirectRation,
@@ -87,9 +103,9 @@ class CompleViewController extends BaseController{
 
     async redirectCoeList(req, res){
         const gljLibId = await getGljLibId(req.session.sessionCompilation);
-        const redirectRation = `/complementaryRation/ration`;
-        const redirectGlj = `/complementaryRation/glj`;
-        const redirectInstallation = `/complementaryRation/installation`;
+        const redirectRation = `/complementaryRation/ration/${userID}`;
+        const redirectGlj = `/complementaryRation/glj/${userID}`;
+        const redirectInstallation = `/complementaryRation/installation/${userID}`;
         res.render('building_saas/complementary_ration_lib/html/fuzhu.html', {
             userID: req.session.sessionUser.id,
             redirectRation: redirectRation,
@@ -104,9 +120,9 @@ class CompleViewController extends BaseController{
 
     redirectInstallation(req, res){
         const repId = req.query.repository;
-        const redirectRation = `/complementaryRation/ration`;
-        const redirectGlj = `/complementaryRation/glj?repository=${repId}`;
-        const redirectCoe = `/complementaryRation/coe?repository=${repId}`;
+        const redirectRation = `/complementaryRation/ration/${userID}`;
+        const redirectGlj = `/complementaryRation/glj?repository=${repId}/${userID}`;
+        const redirectCoe = `/complementaryRation/coe?repository=${repId}/${userID}`;
         res.render('building_saas/complementary_ration_lib/html/anzhuang.html', {
             userID: req.session.sessionUser.id,
             redirectRation: redirectRation,

+ 7 - 1
modules/complementary_ration_lib/models/compleRationModel.js

@@ -19,6 +19,8 @@ const gljDao = new GljDao();
 let counter = require('../../../public/counter/counter');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 let gljUtil = require('../../../public/gljUtil');
+const { ShareLibType } = require('../../../public/common_constants');
+const pmFacade = require('../../pm/facade/pm_facade');
 
 class CompleRatoinDao {
     async updateRation(userID, compilationId, updateData, callback){
@@ -523,7 +525,9 @@ class CompleRatoinDao {
         return codes;
     }
 
-    async prepareInitData (userId, compilationId, gljLibId) {
+    async prepareInitData (sessionUserID, userId, compilationId, gljLibId) {
+        const receiveLibs = await pmFacade.getReceiveLibList(sessionUserID, compilationId, ShareLibType.RATION_LIB);
+        const shareLibs = await pmFacade.getLibShareList(sessionUserID, compilationId, ShareLibType.RATION_LIB);
         const rationsCodes = await this.getCodes(userId, compilationId);
         const gljDistTypeCache = stdgljutil.getStdGljTypeCacheObj().toArray();
         const installationData = await installFacade.getInstallation(userId, compilationId);
@@ -531,6 +535,8 @@ class CompleRatoinDao {
         const mixedTreeData = await gljDao.getMixedTree(gljLibId, userId, compilationId);
         const mixedGLJData = await gljDao.getGLJDataSync(gljLibId, userId, compilationId);
         return {
+            shareLibs,
+            receiveLibs,
             rationsCodes,
             gljDistTypeCache,
             installationData,

+ 27 - 16
modules/complementary_ration_lib/models/searchModel.js

@@ -16,15 +16,19 @@ class SearchDao{
     async getRationItem(userId, compilationId, rationRepIds, code, ID, callback){
         let ration = null;
         let otherLibs=[];
+        const compleLibUsers = [userId];
         try{
-            let firstLib = rationRepIds[0];//优先取第一个
+            let [firstLib] = rationRepIds[0].split('*');//优先取第一个
             for (let l of rationRepIds){
-                if(l != firstLib && l != compleRationLib){
-                    otherLibs.push(l);
+                const [libID, owner] = l.split('*');
+                if(libID != firstLib && libID != compleRationLib){
+                    otherLibs.push(libID);
+                } else if (libID === compleRationLib && owner && !compleLibUsers.includes(owner)) {
+                    compleLibUsers.push(owner);
                 }
             }
             if(firstLib == compleRationLib){//说明选中的是补充定额库
-                ration = await this.getCompleRation(userId,compilationId,code,ID);
+                ration = await this.getCompleRation(compleLibUsers,compilationId,code,ID);
             }else {
                 firstLib = parseInt(firstLib);
                 let firstQuery = {rationRepId: firstLib, code: code};
@@ -39,7 +43,7 @@ class SearchDao{
                     stdQuery = {ID: ID};
                 }
                 ration = await this.getStdRation(stdQuery);
-                if(ration == null) ration = await this.getCompleRation(userId,compilationId,code,ID);
+                if(ration == null) ration = await this.getCompleRation(compleLibUsers,compilationId,code,ID);
             }
             if(isDef(ration)){
                 if (ration.type === 'std') {
@@ -65,9 +69,9 @@ class SearchDao{
         }
         return ration;
     }
-    async getCompleRation(userId,compilationId,code,ID){
+    async getCompleRation(users,compilationId,code,ID){
         let ration = null;
-        let compleQuery = {userId: userId, compilationId: compilationId, code: code, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]};
+        let compleQuery = {userId: {$in: users}, compilationId: compilationId, code: code, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]};
         if(ID){
             compleQuery.ID = ID;
         }
@@ -95,14 +99,21 @@ class SearchDao{
         let resultCount = 0,
             rst = {data: [], count: null};
         try{
+            let compleLibUsers = new Set();
+            const stdRationLibs = [];
+            rationRepId.forEach(libItem => {
+                const [libID, owner] = libItem.split('*');
+                if (libID === compleRationLib) {
+                    compleLibUsers.add(owner || userId);
+                } else {
+                    stdRationLibs.push(libID);
+                }
+            });
+            compleLibUsers = [...compleLibUsers];
             //是否需要查找补充定额
-            let findCompleRtion = rationRepId.length > 0 && rationRepId.includes(compleRationLib) ? true : false;
-            //剔除补充定额库id
-            if (rationRepId.includes(compleRationLib)) {
-                rationRepId.splice(rationRepId.indexOf(compleRationLib), 1);
-            }
+            let findCompleRtion = compleLibUsers.length > 0;
             let filter = {
-                'rationRepId': {$in: rationRepId},
+                'rationRepId': {$in: stdRationLibs},
                 '$and': [{
                     '$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
                 }, {
@@ -110,7 +121,7 @@ class SearchDao{
                 }]
             };
             let compleFilter = {
-                userId: userId,
+                userId: { $in: compleLibUsers },
                 compilationId: compilationId,
                 '$and': [{
                     '$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
@@ -120,14 +131,14 @@ class SearchDao{
             };
             //结果数
             if (skip && skip.std === 0 && skip.comple === 0) {
-                resultCount += rationRepId.length === 0 ? 0 : await stdRationModel.find(filter).count();
+                resultCount += stdRationLibs.length === 0 ? 0 : await stdRationModel.find(filter).count();
                 resultCount += findCompleRtion ? await compleRationModel.find(compleFilter).count() : 0;
                 rst.count = resultCount;
             }
             //搜索定额
             let stdGljIds = [],
                 comGljIds = [];
-            let stdRations = rationRepId.length === 0 ? [] : await stdRationModel.find(filter).lean().sort({code: 1}).skip(skip.std).limit(limit);
+            let stdRations = stdRationLibs.length === 0 ? [] : await stdRationModel.find(filter).lean().sort({code: 1}).skip(skip.std).limit(limit);
             for(let i = 0, len = stdRations.length; i < len; i++){
                 stdRations[i].type = 'std';
                 for(let glj of stdRations[i].rationGljList){

+ 4 - 4
modules/complementary_ration_lib/routes/routes.js

@@ -17,10 +17,10 @@ let gljController = new GljController();
 let searchController = new SearchController();
 
 module.exports = function (app) {
-    app.get('/complementaryRation/ration', compleViewController.init, compleViewController.redirectRation);
-    app.get('/complementaryRation/glj', compleViewController.init, compleViewController.redirectGljList);
-    app.get('/complementaryRation/coe', compleViewController.init, compleViewController.redirectCoeList);
-    app.get('/complementaryRation/installation', compleViewController.init, compleViewController.redirectInstallation);
+    app.get('/complementaryRation/ration/:userID', compleViewController.init, compleViewController.redirectRation);
+    app.get('/complementaryRation/glj/:userID', compleViewController.init, compleViewController.redirectGljList);
+    app.get('/complementaryRation/coe/:userID', compleViewController.init, compleViewController.redirectCoeList);
+    app.get('/complementaryRation/installation/:userID', compleViewController.init, compleViewController.redirectInstallation);
     router.get('/initData', compleViewController.init, compleViewController.prepareInitData);
 
     router.post('/getRationLib', compleViewController.init, compleViewController.getRationLib);

+ 1 - 0
modules/main/controllers/ration_controller.js

@@ -27,6 +27,7 @@ let controller = {
             data = JSON.stringify(data);
         }
         data = JSON.parse(data);
+        data.sessionUserID = req.session.sessionUser.id;
         let result = await ration_facade.addNewRation(data,req.session.sessionCompilation);
         //合并取项目工料机数据的情求,用于刷新项目工料机数据,当有添加、替换项目工料机的情况,才需要刷新
        /* if(result.ration_gljs && result.ration_gljs.length > 0 && data.newData){

+ 14 - 0
modules/main/facade/ration_facade.js

@@ -57,6 +57,9 @@ async function addNewRation(data,compilation) {
     if(query){
         let searchDao = new SearchDao();
         stdRation = await searchDao.getRationItem(query.userID, compilation._id, [query.rationRepId],query.code, query.ID);
+        if (stdRation && data.sessionUserID !== query.userID) {
+          stdRation.owner = query.userID;
+        }
         //data.newData.code = query.code;
     }
     let stdRationTime = +new Date();
@@ -138,6 +141,10 @@ async function  updateSerialNo(serialNoUpdate){
 async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入新的定额
     let startTime = +new Date();
     if(std){
+        if (std.owner) {
+          // 别人分享的定额
+          newData.fromUser = std.owner;
+        }
         newData.code = std.code;
         newData.name = std.name;
         newData.caption = std.caption;
@@ -181,6 +188,9 @@ async function replaceRations(userID,data,compilation) {
     let recodes = [];
     for(let recode of data.nodeInfo){
         let stdRation = await searchDao.getRationItem(userID,compilation._id,data.libIDs,recode.newCode, null);
+        if (stdRation && stdRation.userId && stdRation.userId !== userID) {
+          stdRation.owner = stdRation.userId;
+        }
         let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation,data.cleanzmhs);
         if(newRecode){
             recodes.push(newRecode);
@@ -958,6 +968,10 @@ async function updateCoeAdjust(data,compilation) {
 async function  updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false) {
     // insertNewRation
     let ration ={};
+    if (std.owner) {
+      // 别人分享的定额
+      ration.fromUser = std.owner;
+    }
     ration.code = std.code;
     ration.name = std.name;
     ration.caption = std.caption;

+ 79 - 4
modules/pm/controllers/pm_controller.js

@@ -634,6 +634,81 @@ module.exports = {
             callback(req, res, 1, err.message, null);
         }
     },
+    getReceiveLibList: async function (req, res) {
+        try {
+            const { libType } = JSON.parse(req.body.data);
+            const userID = req.session.sessionUser.id;
+            const compilationID = req.session.sessionCompilation._id;
+            const list = await pm_facade.getReceiveLibList(userID, compilationID, libType);
+            callback(req, res, 0, 'success', list);
+        } catch (err) {
+            callback(req, res, 1, err.message, null);
+        }
+    },
+    getInitialShareLibData: async function (req, res) {
+        try {
+            const { libType, count } = JSON.parse(req.body.data);
+            const userID = req.session.sessionUser.id;
+            const compilationID = req.session.sessionCompilation._id;
+            // 最近分享
+            const recentUsers = await pm_facade.getRecentShareList(userID, count);
+            // 联系人
+            const contacts = await userModelObj.getContacts(userID);
+            // 分享过的人
+            const sharedUsers = await pm_facade.getLibShareList(userID, compilationID, libType, count);
+            callback(req, res, 0, 'success', { recentUsers, contacts, sharedUsers });
+        } catch (err) {
+            console.log(err);
+            callback(req, res, 1, err.message, null);
+        }
+    },
+    shareLib: async function (req, res) {
+        try {
+            const { type, libType, shareData, count } = JSON.parse(req.body.data);
+            const owner = req.session.sessionUser.id;
+            const compilationID = req.session.sessionCompilation._id;
+            const shareDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
+            shareData.forEach(item => item.shareDate = shareDate);
+            const task = [];
+            // 是否只是单纯的更新分享选项,如果不是,需要重新获取最近分享和联系人
+            let isSimpleUpdate = true;
+            if (type === 'create') {
+                isSimpleUpdate = false;
+                // 生成分享记录
+                const docs = shareData.map(item => ({
+                    compilationID,
+                    owner,
+                    libType,
+                    ID: uuidV1(),
+                    receiver: item.receiver,
+                    allowCooperate: false,
+                    shareDate: item.shareDate,
+                    updateDate: item.shareDate
+                }));
+                task.push(pm_facade.addShareList(docs, true));
+                // 分享即互相添加为联系人
+                task.push(userModelObj.addContact(docs[0].owner, docs[0].receiver));
+            } else if (type === 'cancel') { // 取消分享
+                const cancelReceivers = shareData.map(item => item.receiver);
+                task.push(pm_facade.deleteShareList({ owner, libType, compilationID, receiver: { $in: cancelReceivers } }, true));
+            }
+            await Promise.all(task);
+            const rst = {};
+            if (!isSimpleUpdate) {
+                const rstTask = [
+                    pm_facade.getRecentShareList(owner, count),
+                    userModelObj.getContacts(owner)
+                ];
+                const [recentUsers, contacts] = await Promise.all(rstTask);
+                Object.assign(rst, { recentUsers, contacts });
+            }
+            callback(req, res, 0, 'success', rst);
+        } catch (err) {
+            console.log(err);
+            logger.info(err);
+            callback(req, res, 1, err, null);
+        }
+    },
     share: async function (req, res) {
         try {
             const data = JSON.parse(req.body.data);
@@ -696,15 +771,15 @@ module.exports = {
                 task.push(pm_facade.deleteShareList({ projectID, receiver: { $in: cancelReceivers } }));
             }
             await Promise.all(task);
-            const rstTask = [
-                pm_facade.getRecentShareList(userID, count),
-                userModelObj.getContacts(userID)
-            ];
             // 获取需要广播推送的单位工程
             // shareData数组的形式是以前需求需要,现在的需求下,shareData数组必定只有一个元素
             const emitTenders = await pm_facade.getShareInfoAfterChangePermission(permissionType, shareData[0].userID, projectID);
             let rst = { emitTenders };
             if (!isSimpleUpdate) {
+                const rstTask = [
+                    pm_facade.getRecentShareList(userID, count),
+                    userModelObj.getContacts(userID)
+                ];
                 const [recentUsers, contacts] = await Promise.all(rstTask);
                 Object.assign(rst, { recentUsers, contacts });
             }

+ 65 - 9
modules/pm/facade/pm_facade.js

@@ -17,6 +17,8 @@ module.exports={
     getShareInfoMap,
     getRecentShareList,
     getProjectShareList,
+    getReceiveLibList,
+    getLibShareList,
     getUnreadShareListByCompilation,
     getShareTip,
     getShareState,
@@ -103,6 +105,7 @@ let featureLibModel =  mongoose.model("std_project_feature_lib");
 let importLogsModel = mongoose.model("import_logs");
 const overHeightLibModel = mongoose.model('std_over_height_lib');
 const shareListModel = mongoose.model('share_list');
+const shareLibModel = mongoose.model('share_libs');
 let welcomeModel = mongoose.model("welcome_setting");
 
 let scMathUtil = require('../../../public/scMathUtil').getUtil();
@@ -211,19 +214,23 @@ async function prepareShareList() {
 
 
 // 获取分享列表
-async function getShareList(query) {
-    return await shareListModel.find(query, '-_id').lean();
+async function getShareList(query, isShareLib = false) {
+    const model = isShareLib ? shareLibModel : shareListModel;
+    return await model.find(query, '-_id').lean();
 }
 
-async function addShareList(docs) {
-    await shareListModel.insertMany(docs);
+async function addShareList(docs, isShareLib = false) {
+    const model = isShareLib ? shareLibModel : shareListModel;
+    await model.insertMany(docs);
 }
 
-async function deleteShareList(query) {
-    await shareListModel.deleteMany(query);
+async function deleteShareList(query, isShareLib = false) {
+    const model = isShareLib ? shareLibModel : shareListModel;
+    await model.deleteMany(query);
 }
 
-async function updateShareList(updateData) {
+async function updateShareList(updateData, isShareLib = false) {
+    const model = isShareLib ? shareLibModel : shareListModel;
     const bulks = updateData.map(item => (
         {
             updateOne: {
@@ -233,7 +240,7 @@ async function updateShareList(updateData) {
         }
     ));
     if (bulks.length) {
-        await shareListModel.bulkWrite(bulks);
+        await model.bulkWrite(bulks);
     }
 }
 
@@ -259,7 +266,10 @@ async function getShareInfoMap(projectIDs, shareList = null) {
 
 // 获取最近分享(只算分享出去的记录)
 async function getRecentShareList(userID, count) {
-    const shareList = await getShareList({owner: userID});
+    // 合并分享的项目和库
+    const shareProjectList = await getShareList({owner: userID});
+    const shareLibList = await getShareList({owner: userID}, true);
+    const shareList = [...shareProjectList, ...shareLibList];
     shareList.sort((a, b) => Date.parse(b.shareDate) - Date.parse(a.shareDate));
     const set = new Set();
     for(const item of shareList) {
@@ -275,6 +285,7 @@ async function getRecentShareList(userID, count) {
     return users;
 }
 
+
 // 获取某项目的分享记录
 async function getProjectShareList(projectID, limit = null) {
     const sharedList = limit 
@@ -301,6 +312,51 @@ async function getProjectShareList(projectID, limit = null) {
     return users;
 }
 
+async function getReceiveLibList(receiver, compilationID, libType) {
+    const sharedList = await shareLibModel.find({ receiver, compilationID, libType }).lean().sort({ shareDate: -1 });
+    const userIDs = [];
+    const userMap = {};
+    sharedList.forEach((item, index) => {
+        userIDs.push(item.owner);
+        userMap[item.owner] = item;
+        userMap[item.owner].index = index;
+    });
+    const userObjectIDs = userIDs.map(userID => mongoose.Types.ObjectId(userID));
+    const users = await userModel.find({ _id: { $in: userObjectIDs } }, 'real_name').lean();
+    users.forEach(user => {
+        const matched = userMap[user._id];
+        if (matched) {
+            user.index = matched.index;
+        }
+    });
+    users.sort((a, b) => a.index - b.index);
+    return users;
+}
+
+// 获取某库的分享记录
+async function getLibShareList(owner, compilationID, libType, limit = null) {
+    const sharedList = limit 
+        ? await shareLibModel.find({ owner, compilationID, libType }).lean().sort({ shareDate: -1 }).limit(limit)
+        : await shareLibModel.find({ owner, compilationID, libType }).lean().sort({ shareDate: -1 });
+    const userIDs = [];
+    const userMap = {};
+    sharedList.forEach((item, index) => {
+        userIDs.push(item.receiver);
+        userMap[item.receiver] = item;
+        userMap[item.receiver].index = index;
+    });
+    const userObjectIDs = userIDs.map(userID => mongoose.Types.ObjectId(userID));
+    const users = await userModel.find({_id: {$in: userObjectIDs}}, 'real_name mobile company').lean();
+    users.forEach(user => {
+        const matched = userMap[user._id];
+        if (matched) {
+            user.index = matched.index;
+        }
+    });
+    users.sort((a, b) => a.index - b.index);
+    return users;
+}
+
 // 获取某用户某费用定额的未读的被分享记录
 async function getUnreadShareListByCompilation(userID, compilationID, isGetCount) {
     const fields = isGetCount ? '-_id projectID ' : '-_id';

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

@@ -58,9 +58,12 @@ module.exports = function (app) {
     pmRouter.post('/recGC', pmController.recGC);
     pmRouter.post('/delGC', pmController.delGC);
     //share
+    pmRouter.post('/getReceiveLibList', pmController.getReceiveLibList);
     pmRouter.post('/getProjectShareInfo', pmController.projectShareInfo);
     pmRouter.post('/getInitialShareData', pmController.getInitialShareData);
+    pmRouter.post('/getInitialShareLibData', pmController.getInitialShareLibData);
     pmRouter.post('/share', pmController.share);
+    pmRouter.post('/shareLib', pmController.shareLib);
     pmRouter.post('/receiveProjects', pmController.receiveProjects);
     pmRouter.post('/changeFile', pmController.changeFile);
     pmRouter.post('/exportProject', pmController.exportProject);

+ 9 - 1
public/common_constants.js

@@ -176,6 +176,13 @@
         SHARE_CANCEL: 2,
     };
 
+    // 分享库类型
+    const ShareLibType = {
+        RATION_LIB: 1,
+        GLJ_LIB: 2,
+        BLOCK_LIB: 3,
+    };
+
     return {
         fixedFlag,
         billType,
@@ -191,6 +198,7 @@
         StorageKey,
         SharePermissionChangeType,
         PageTarget,
-        BlankType
+        BlankType,
+        ShareLibType,
     };
 });

+ 28 - 0
public/web/sheet/sheet_common.js

@@ -1497,6 +1497,34 @@ var sheetCommonObj = {
         }
         return result;
     },
+    disableSpread(spread) {
+        spread.unbind(GC.Spread.Sheets.Events.ButtonClicked);
+        let sheetCount = spread.getSheetCount();
+        for(let i = 0; i < sheetCount; i++){
+            let sheet = spread.getSheet(i);
+            sheet.unbind(GC.Spread.Sheets.Events.ButtonClicked);
+            sheet.unbind(GC.Spread.Sheets.Events.EditStarting);
+            sheet.unbind(GC.Spread.Sheets.Events.EditEnded);
+            sheet.unbind(GC.Spread.Sheets.Events.RangeChanged);
+            sheet.unbind(GC.Spread.Sheets.Events.ClipboardChanging);
+            sheet.unbind(GC.Spread.Sheets.Events.ClipboardChanged);
+            sheet.unbind(GC.Spread.Sheets.Events.CellDoubleClick);
+            sheet.unbind(GC.Spread.Sheets.Events.CellClick);
+            sheet.unbind(GC.Spread.Sheets.Events.ValueChanged);
+            sheet.suspendPaint();
+            sheet.suspendEvent();
+            sheet.options.isProtected = true;
+            let rowCount = sheet.getRowCount();
+            let colCount = sheet.getColumnCount();
+            for(let row = 0; row < rowCount; row++){
+                for(let col = 0; col < colCount; col++){
+                    sheet.getCell(row, col).locked(true);
+                }
+            }
+            sheet.resumePaint();
+            sheet.resumeEvent();
+        }
+    },
     // 延迟一段时间刷新表格,因为有的弹窗里面有表格,马上刷新可能会造成,弹窗界面还未完全显示完就完成了表格刷新,导致表格显示不完整
     refreshWorkbookDelDefer(workbook, time) {
         if (workbook) {

+ 5 - 0
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -56,6 +56,7 @@
         }
     </style>
     <script>
+        const isReadOnly = JSON.parse('<%= isReadOnly %>');
         const gljLibId = '<%= gljLibId %>';
         const userID = '<%=userID %>';
         let priceProperties = JSON.parse('<%- priceProperties %>');
@@ -604,6 +605,7 @@
         </div>
     </div>
 </div>
+<%include ../../../common/components/share/index.html %>
 <!-- JS. -->
 <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
 <script>GC.Spread.Sheets.LicenseKey =  '<%- LicenseKey %>';</script>
@@ -613,6 +615,9 @@
 <script type="text/javascript" src="/lib/jquery-contextmenu/jquery.ui.position.js"></script>
 <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
 <script type="text/javascript" src="/web/building_saas/complementary_ration_lib/js/global.js"></script>
+<script src="/lib/pinyinjs/pinyin_dict_firstletter.js"></script>
+<script src="/lib/pinyinjs/pinyinUtil.js"></script>
+<script src="/web/common/components/share/index.js"></script>
 <script type="text/javascript" src="/public/web/id_tree.js"></script>
 <script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_controller.js"></script>
 <script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_helper.js"></script>

+ 6 - 2
web/building_saas/complementary_ration_lib/js/coe.js

@@ -173,6 +173,10 @@ var pageObj = {
         let me = this;
         coeOprObj.buildSheet($('#mainSpread')[0]);
         gljAdjOprObj.buildSheet($('#contentSpread')[0]);
+        if (isReadOnly) {
+            sheetCommonObj.disableSpread(coeOprObj.workBook);
+            sheetCommonObj.disableSpread(gljAdjOprObj.workBook);
+        }
         coeOprObj.getCoeList();
         //gljAdjOprObj.getGljItemsOcc();
 
@@ -454,7 +458,7 @@ let coeOprObj = {
         let me = coeOprObj;
         $.ajax({
             type: 'post',
-            url: 'api/getCoeList',
+            url: '/complementaryRation/api/getCoeList',
             dataType: 'json',
             timeout:20000,
             success: function (result) {
@@ -475,7 +479,7 @@ let coeOprObj = {
         let me = coeOprObj;
         $.ajax({
             type:"POST",
-            url:"api/saveCoeList",
+            url:"/complementaryRation/api/saveCoeList",
             data: {data: JSON.stringify({addArr: addArr, updateArr: updateArr, deleteArr: deleteArr})},
             dataType:"json",
             timeout:5000,

+ 68 - 2
web/building_saas/complementary_ration_lib/js/init.js

@@ -8,9 +8,63 @@
  * @version
  */
 const initialization = (() => {
+    const params = location.href.split('/');
+    const curUserID = params[params.length - 1];
+
+    // 头部按钮相关
+    function initHeaderTools(receiveList, shareList) {
+        // 设置下拉项
+        const selectHtml = `
+        <select class="form-control  form-control-sm" id="ration-libs">
+        </select>`;
+        // 设置分享按钮
+        const shareHtml = `
+        <span id="share-tip" class="ml-2" data-toggle="tooltip" data-placement="bottom" data-original-title="sddsd">
+            <a id="init-share" href="javascript:;" class="btn btn-xs btn-primary"><i class="fa fa-share-alt"></i> 分享</a>
+        </span>`;
+        const html = `
+            <div style="display: flex; align-items: center">
+                ${selectHtml}
+                ${shareHtml}
+            </div>
+        `
+        $('#fullpath').html(html);
+        initShareTip(shareList);
+        $('[data-toggle="tooltip"]').tooltip();
+        initLibOptions(receiveList);
+        // 分享给
+        SHARE_TO.handleEventListener();
+        $('#init-share').click(() => {
+            SHARE_TO.initModal(SHARE_TO.Mode.RATION_LIB);
+            $('#share-tip').tooltip('hide');
+        });
+
+        // 定额库下拉
+        function initShareTip(shareList) {
+            const owners = shareList.map(owner => owner.real_name);
+            const tips = `已分享给 ${owners.join(' ')}`;
+            $('#share-tip').attr('data-original-title', tips);
+        }
+
+        // 定额库下拉
+        function initLibOptions(receiveList) {
+            const libList = [
+                `<option value="${userID}">我的补充定额库</option>`
+            ];
+            const options = receiveList.map(owner => `<option value=${owner._id} ${curUserID === owner._id ? 'selected' : ''}>${owner.real_name}的补充定额库</option>`);
+            libList.push(...options);
+            $('#ration-libs').html(libList.join(''))
+        }
+
+        $('#ration-libs').change(function () {
+            const userID = $(this).val();
+            window.location.href = `/complementaryRation/ration/${userID}`;
+        });
+    }
+
     $(document).ready(function () {
         $.bootstrapLoading.start();
-        CommonAjax.get('/complementaryRation/api/initData', {}, res => {
+        CommonAjax.get('/complementaryRation/api/initData', { userID: curUserID }, res => {
             if (res.error) {
                 alert('数据初始化失败,请重试。');
                 setTimeout(() => {
@@ -18,6 +72,7 @@ const initialization = (() => {
                 }, 1200);
             } else {
                 const data = res.data;
+                initHeaderTools(data.receiveLibs, data.shareLibs);
                 pageOprObj.rationTreeData = data.rationTreeData;
                 pageOprObj.mixedTreeData = data.mixedTreeData;
                 pageOprObj.mixedGLJData = data.mixedGLJData;
@@ -42,7 +97,18 @@ const initialization = (() => {
                 sheetCommonObj.bindEscKey(rdSpread, rdSpreadEscSheets);
                 gljAdjOprObj.gljList = data.mixedGLJData.stdGljs.concat(data.mixedGLJData.complementaryGljs);
                 pageOprObj.initPage();
-
+                if (isReadOnly) {
+                    sheetCommonObj.disableSpread(sectionTreeObj.workBook);
+                    sheetCommonObj.disableSpread(rationOprObj.workBook);
+                    sheetCommonObj.disableSpread(rdSpread);
+                    $('#tree_Insert').addClass('disabled');
+                    $('#tree_remove').addClass('disabled');
+                    $('#tree_upLevel').addClass('disabled');
+                    $('#tree_downLevel').addClass('disabled');
+                    $('#tree_downMove').addClass('disabled');
+                    $('#tree_upMove').addClass('disabled');
+                    $('#init-share').addClass('disabled');
+                }
                 $("#linkGLJ").click(function(){
                     rationGLJOprObj.bindRationGljDelOpr();
                     rdSpread.setActiveSheetIndex(0);

+ 5 - 5
web/building_saas/complementary_ration_lib/js/installation.js

@@ -339,7 +339,7 @@ let feeItemObj = {
     },
     getInstallation: function (callback) {
         let me = this;
-        CommonAjax.post('api/getInstallation', {}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/getInstallation', {}, function (rstData) {
             me.cache = rstData;
             if(callback){
                 callback(rstData);
@@ -348,7 +348,7 @@ let feeItemObj = {
     },
     updateFeeItem: function (updateData, callback) {
         let me = this;
-        CommonAjax.post('api/updateFeeItem', {updateData: updateData}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/updateFeeItem', {updateData: updateData}, function (rstData) {
             if(callback){
                 callback();
             }
@@ -577,7 +577,7 @@ let sectionObj = {
         me.workBook.commandManager().setShortcutKey('sectionDel', GC.Spread.Commands.Key.del, false, false, false, false);
     },
     updateSection: function (updateData, callback) {
-        CommonAjax.post('api/updateInstallSection', {updateData: updateData}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/updateInstallSection', {updateData: updateData}, function (rstData) {
             if(callback){
                 callback();
             }
@@ -1140,7 +1140,7 @@ let batchSectionObj = {
     },
     getSectionTree: function () {
         let me = this;
-        let url = 'api/getRationTree';
+        let url = '/complementaryRation/api/getRationTree';
         //type:0补充定额库,1标准定额库
         let postData = {type: 0};
         let sucFunc = function (rstData) {
@@ -1258,7 +1258,7 @@ let batchSectionObj = {
     },
     //inst: 定额安装费用, rationSection: 定额章节树IDs
     batchUpdate: function (feeItemId, sectionId, rationSection) {
-        CommonAjax.post('api/batchUpdateInst', {inst: {feeItemId: feeItemId, sectionId: sectionId}, rationSection: rationSection}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/batchUpdateInst', {inst: {feeItemId: feeItemId, sectionId: sectionId}, rationSection: rationSection}, function (rstData) {
             $('#sectionTreeModal').modal('hide');
         });
     }

+ 2 - 2
web/building_saas/complementary_ration_lib/js/jobContent.js

@@ -384,7 +384,7 @@ let jobContentOprObj = {
         let me = jobContentOprObj;
         $.ajax({
             type: 'post',
-            url: 'api/updateJobContent',
+            url: '/complementaryRation/api/updateJobContent',
             data: {lastOpr: userAccount, repId: pageOprObj.rationLibId, updateArr: JSON.stringify(updateArr)},
             dataType: 'json',
             success: function (result) {
@@ -399,7 +399,7 @@ let jobContentOprObj = {
         let me = jobContentOprObj;
         $.ajax({
             type: 'post',
-            url: 'api/updateSituation',
+            url: '/complementaryRation/api/updateSituation',
             data: {lastOpr: userAccount, repId: pageOprObj.rationLibId, nodeId: nodeId, situation: situation},
             dataType: 'json',
             success: function (result) {

+ 11 - 5
web/building_saas/complementary_ration_lib/js/ration.js

@@ -617,7 +617,7 @@ let rationOprObj = {
     mixUpdateRequest: function(updateArr, addArr, removeIds, callback) {
         let me = rationOprObj;
         me.saveInString(updateArr);
-        CommonAjax.post('api/mixUpdateRationItems', {sectionId: me.currentSectionId, updateItems: updateArr, addItems: addArr, removeIds: removeIds}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/mixUpdateRationItems', {sectionId: me.currentSectionId, updateItems: updateArr, addItems: addArr, removeIds: removeIds}, function (rstData) {
             let cacheSection = me.updateCache(addArr, updateArr, removeIds, rstData);
             me.sortByCode(cacheSection);
             /*cacheSection.sort(function(a, b){
@@ -673,12 +673,14 @@ let rationOprObj = {
                 //annotation
                 //annotationOprObj.rationAnnotationOpr(me.currentRations["_SEC_ID_" + sectionID]);
                 me.showRationItems(sectionID);
-                sectionTreeObj.removeBtn.removeClass('disabled');
+                if (!isReadOnly) {
+                    sectionTreeObj.removeBtn.removeClass('disabled');
+                }
                 if(callback){
                     callback();
                 }
             } else {
-                CommonAjax.post('api/getRationItems', {sectionId: sectionID}, function (rstData) {
+                CommonAjax.post('/complementaryRation/api/getRationItems', {sectionId: sectionID}, function (rstData) {
                     me.currentRations["_SEC_ID_" + sectionID] = rstData;
                     me.sortByCode(me.currentRations["_SEC_ID_" + sectionID]);
                     //job--
@@ -687,12 +689,16 @@ let rationOprObj = {
                     //annotation
                     //annotationOprObj.rationAnnotationOpr(me.currentRations["_SEC_ID_" + sectionID]);
                     me.showRationItems(sectionID);
-                    sectionTreeObj.removeBtn.removeClass('disabled');
+                    if (!isReadOnly) {
+                        sectionTreeObj.removeBtn.removeClass('disabled');
+                    }
                     if(callback) {
                         callback();
                     }
                 }, function () {
-                    sectionTreeObj.removeBtn.removeClass('disabled');
+                    if (!isReadOnly) {
+                        sectionTreeObj.removeBtn.removeClass('disabled');
+                    }
                 });
             }
         }

+ 3 - 1
web/building_saas/complementary_ration_lib/js/ration_assist.js

@@ -172,7 +172,9 @@ var rationAssistOprObj = {
         me.ration = ration;
 
         sheetCommonObj.cleanData(me.sheet, me.setting, -1);
-        sheetCommonObj.unShieldAllCells(me.sheet);
+        if (!isReadOnly) {
+            sheetCommonObj.unShieldAllCells(me.sheet);
+        }
 
         if (ration == undefined || ration.rationAssList == undefined ||
             ration.rationAssList.length == 0){

+ 2 - 2
web/building_saas/complementary_ration_lib/js/ration_coe.js

@@ -235,7 +235,7 @@ var rationCoeOprObj = {
             }else{
                 $.ajax({
                     type:"POST",
-                    url:"api/getCoeItemsByNos",
+                    url:"/complementaryRation/api/getCoeItemsByNos",
                     data: {"data": JSON.stringify({"coeNos": temp})},
                     dataType:"json",
                     cache:false,
@@ -292,7 +292,7 @@ var rationCoeOprObj = {
                 var data = {"coeIDs": coeIDs};
                 $.ajax({
                     type:"POST",
-                    url:"api/getCoeItemsByIDs",
+                    url:"/complementaryRation/api/getCoeItemsByIDs",
                     data: {"data": JSON.stringify(data)},
                     dataType:"json",
                     cache:false,

+ 3 - 3
web/building_saas/complementary_ration_lib/js/ration_glj.js

@@ -64,7 +64,7 @@ var rationGLJOprObj = {
         let me = this;
         $.ajax({
             type: 'post',
-            url: "api/getGljDistType",
+            url: "/complementaryRation/api/getGljDistType",
             dataType: 'json',
             success: function (result) {
                 if (!result.error && callback) {
@@ -425,7 +425,7 @@ var rationGLJOprObj = {
     },
     addGljItems: function (codes, repId, args) {
         let me = this;
-        CommonAjax.post('api/getGljItemsByCodes', { gljCodes: codes, rationRepId: repId }, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/getGljItemsByCodes', { gljCodes: codes, rationRepId: repId }, function (rstData) {
             if (rstData.length > 0) {
                 if (priceProperties && priceProperties.length > 0) {
                     let priceField = priceProperties[0].price.dataCode;
@@ -612,7 +612,7 @@ var rationGLJOprObj = {
                 idObj.id = rationGljList[i].gljId;
                 gljIds.push(idObj);
             }
-            CommonAjax.post('api/getGljItemsByIds', { ids: gljIds }, function (rstData) {
+            CommonAjax.post('/complementaryRation/api/getGljItemsByIds', { ids: gljIds }, function (rstData) {
                 sheetCommonObj.cleanSheet(me.sheet, me.setting, -1);
                 if (priceProperties && priceProperties.length > 0) {
                     let priceField = priceProperties[0].price.dataCode;

+ 9 - 9
web/building_saas/complementary_ration_lib/js/repository_glj.js

@@ -81,7 +81,7 @@ repositoryGljObj = {
     },
     getGljDistType: function (callback) {
         let me = this;
-        CommonAjax.post('api/getGljDistType', {}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/getGljDistType', {}, function (rstData) {
             me.distTypeTree = me.getComboData(rstData);
             me.workBook.getSheet(0).getCell(-1, 5, GC.Spread.Sheets.SheetArea.viewport).value(me.distTypeTree.comboDatas[0].text);
             if(callback){
@@ -91,7 +91,7 @@ repositoryGljObj = {
     },
     getGljTree: function(gljLibId, callback) {
         var me = this;
-        CommonAjax.post('api/getGljTree', {gljLibId: gljLibId}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/getGljTree', {gljLibId: gljLibId}, function (rstData) {
             zTreeHelper.createTree(rstData, gljSetting, "repositoryTree", me);
             if (rstData && rstData.length > 0) {
                 me.gljCurTypeId = rstData[0].ID;
@@ -103,7 +103,7 @@ repositoryGljObj = {
     },
     getGljItems: function(gljLibId) {
         var me = this;
-        CommonAjax.post('api/getGljItems', {stdGljLibId: gljLibId}, function (rstData) {
+        CommonAjax.post('/complementaryRation/api/getGljItems', {stdGljLibId: gljLibId}, function (rstData) {
             me.gljList = rstData.stdGljs.concat(rstData.complementaryGljs);
             me.workBook.getSheet(0).setRowCount(rstData.length);
             me.sortGlj();
@@ -620,7 +620,7 @@ repositoryGljObj = {
     updateRationBasePrcRq: function (basePrcArr) {
         $.ajax({
             type: 'post',
-            url: 'api/updateRationBasePrc',
+            url: '/complementaryRation/api/updateRationBasePrc',
             data:{data: JSON.stringify({repId: pageOprObj.rationLibId, lastOpr: userAccount, basePrcArr: basePrcArr})},
             dataType: 'json',
             success: function (result) {
@@ -634,7 +634,7 @@ repositoryGljObj = {
         let me = repositoryGljObj;
         $.ajax({
             type: 'post',
-            url: 'api/getRationGljIds',
+            url: '/complementaryRation/api/getRationGljIds',
             data: {data: JSON.stringify({repId: repId})},
             dataType: 'json',
             success: function(result){
@@ -648,7 +648,7 @@ repositoryGljObj = {
         var me = repositoryGljObj;
         $.ajax({
             type:"POST",
-            url:"api/mixUpdateGljItems",
+            url:"/complementaryRation/api/mixUpdateGljItems",
             data:{"repositoryId": me.currentRepositoryId, "lastOpr": userAccount, "updateItems": JSON.stringify(updateArr), "addItems": JSON.stringify(addArr), "removeIds": JSON.stringify(removeIds)},
             dataType:"json",
             cache:false,
@@ -806,7 +806,7 @@ var gljTypeTreeOprObj = {
         }
         $.ajax({
             type:"POST",
-            url:"api/deleteGljNodes",
+            url:"/complementaryRation/api/deleteGljNodes",
             data:{"repId": pageOprObj.rationLibId, "lastOpr": userAccount, "nodes": JSON.stringify(nodeIds), "preNodeId": preNodeId, "preNodeNextId": treeNode.NextSiblingID},
             dataType:"json",
             cache:false,
@@ -845,7 +845,7 @@ var gljTypeTreeOprObj = {
             }
             $.ajax({
                 type:"POST",
-                url:"api/updateGljNodes",
+                url:"/complementaryRation/api/updateGljNodes",
                 data:{"repId": pageOprObj.rationLibId, "lastOpr": userAccount, "nodes": JSON.stringify(reqData)},
                 dataType:"json",
                 cache:false,
@@ -876,7 +876,7 @@ var gljTypeTreeOprObj = {
     addNewNode : function(rawNode, lastNodeId, callback){
         $.ajax({
             type:"POST",
-            url:"api/createNewGljTypeNode",
+            url:"/complementaryRation/api/createNewGljTypeNode",
             data:{"lastOpr": userAccount, "repositoryId": repositoryGljObj.currentRepositoryId,"lastNodeId": lastNodeId, "rawNodeData": JSON.stringify(rawNode)},
             dataType:"json",
             cache:false,

+ 5 - 2
web/building_saas/complementary_ration_lib/js/section_tree.js

@@ -22,7 +22,7 @@ let pageOprObj = {
         annotationOprObj.bindAllEvents($('#fzTxtareaAll'));
     },
     getRationLibInfo: function (rationLibId, callback) {
-        CommonAjax.post('api/getRationLib', {rationRepId: rationLibId}, callback);
+        CommonAjax.post('/complementaryRation/api/getRationLib', {rationRepId: rationLibId}, callback);
     },
 };
 
@@ -239,6 +239,9 @@ let sectionTreeObj = {
     },
     
     refreshBtn: function (selected) {
+        if (isReadOnly) {
+            return;
+        }
         let me = this;
         me.insertBtn.removeClass('disabled');
         me.removeBtn.removeClass('disabled');
@@ -526,7 +529,7 @@ let sectionTreeObj = {
         return updateObj;
     },
     sectionTreeAjax: function (postData, scFunc, errFunc) {
-        CommonAjax.post('api/updateRationSection', {updateData: postData}, scFunc, errFunc);
+        CommonAjax.post('/complementaryRation/api/updateRationSection', {updateData: postData}, scFunc, errFunc);
     },
     initTools: function (node) {
         if(this.isDef(node)){

+ 2 - 2
web/building_saas/main/js/views/calc_program_manage.js

@@ -97,8 +97,8 @@ let calcProgramManage = {
             if(me.detailSetting.view.lockColumns){
                 me.detailSetting.view.lockColumns = null;
             }
-            disableSpread(me.mainSpread);
-            disableSpread(me.detailSpread);
+            sheetCommonObj.disableSpread(me.mainSpread);
+            sheetCommonObj.disableSpread(me.detailSpread);
         }
     },
     getStdCalcProgramFiles: function(){

+ 2 - 2
web/building_saas/main/js/views/config_material_view.js

@@ -77,8 +77,8 @@ let configMaterialObj = {
         materialAdjustObj.initPriceCoeSheet();
         //打开别人分享的项目,只读
         if(projectReadOnly){
-            disableSpread(this.configSpread);
-            disableSpread(this.relatedSpread);
+            sheetCommonObj.disableSpread(this.configSpread);
+            sheetCommonObj.disableSpread(this.relatedSpread);
         }else {
             this.initRightClick();
         }

+ 1 - 1
web/building_saas/main/js/views/fee_rate_view.js

@@ -580,7 +580,7 @@ var feeRateObject={
         disableRightMenu("divFee",this.mainFeeRateSpread,this.rightClickCallback);
         //打开他人分享的项目、只读
         if(projectReadOnly){
-            disableSpread(this.mainFeeRateSpread);
+            sheetCommonObj.disableSpread(this.mainFeeRateSpread);
         }
     },
     rightClickCallback:function (row) {

+ 1 - 1
web/building_saas/main/js/views/index_view.js

@@ -108,7 +108,7 @@ let indexObj= {
         }
        // disableRightMenu("glj_from_sheet",this.spread);
         if(projectReadOnly){
-            disableSpread(this.spread);
+            sheetCommonObj.disableSpread(this.spread);
         }
         sheetCommonObj.refreshWorkbookDelDefer(this.spread, 100);
     },

+ 2 - 2
web/building_saas/main/js/views/item_increase_fee_view.js

@@ -50,7 +50,7 @@ let itemIncreaseFeeObj = {
         this.settingSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onItemValueChange);
         this.settingSheet.name('itemIncreaseFee_sheet');
         if(projectReadOnly){
-            disableSpread(this.settingSpread);
+            sheetCommonObj.disableSpread(this.settingSpread);
         }
     },
     initScopeSpread:function () {
@@ -62,7 +62,7 @@ let itemIncreaseFeeObj = {
         this.scopeSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, this.onScopeCheckBoxClick);
         this.scopeSheet.name('scopeSheet');
         if(projectReadOnly){
-            disableSpread(this.scopeSpread);
+            sheetCommonObj.disableSpread(this.scopeSpread);
         }
     },
     getSelectedItem:function () {

+ 1 - 1
web/building_saas/main/js/views/main_tree_col.js

@@ -755,7 +755,7 @@ $('#poj-set').on('shown.bs.modal', function (e) {
     if (!colSettingObj.settingSpread) {
         colSettingObj.initSettingSpread();
         if(projectReadOnly){
-            disableSpread(colSettingObj.settingSpread);
+            sheetCommonObj.disableSpread(colSettingObj.settingSpread);
         }
     }
     if($('#tab_display_setting').hasClass('active')){

+ 1 - 1
web/building_saas/main/js/views/mbzm_view.js

@@ -61,7 +61,7 @@ let mbzm_obj={
         this.spread.bind(GC.Spread.Sheets.Events.ButtonClicked, installationFeeObj.onPositionButtonClick);//共用一个位置选择器
         this.sheet.name('ration_template');
         if(projectReadOnly){
-            disableSpread(this.spread);
+            sheetCommonObj.disableSpread(this.spread);
         }
     },
     refresh:function () {

+ 4 - 4
web/building_saas/main/js/views/project_glj_view.js

@@ -208,7 +208,7 @@ let projectGljObject = {
     this.getInfoPriceOptions();
 
     if (projectReadOnly) {
-      disableSpread(this.infoPriceSpread);
+      sheetCommonObj.disableSpread(this.infoPriceSpread);
     } else {
       this.initInfoPriceRightClick();
     }
@@ -224,7 +224,7 @@ let projectGljObject = {
     //this.infoClassSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, this.infoClassSelectionChange);
     this.infoClassSheet.bind(GC.Spread.Sheets.Events.CellClick,this.infoClassClick);
     if (projectReadOnly) {
-      disableSpread(this.infoClassSpread);
+      sheetCommonObj.disableSpread(this.infoClassSpread);
     } 
   },
   initSpreads: function () {
@@ -247,7 +247,7 @@ let projectGljObject = {
       if (this.projectGljSetting.view.lockColumns) {
         this.projectGljSetting.view.lockColumns = null;
       }
-      disableSpread(this.projectGljSpread);
+      sheetCommonObj.disableSpread(this.projectGljSpread);
     }
   },
   initProjectGljSheet: function () {
@@ -282,7 +282,7 @@ let projectGljObject = {
       if (this.mixRatioSetting.view.lockColumns) {
         this.mixRatioSetting.view.lockColumns = null;
       }
-      disableSpread(this.mixRatioSpread);
+      sheetCommonObj.disableSpread(this.mixRatioSpread);
     }
   },
   initRelatedRationSheet: function () {

+ 1 - 1
web/building_saas/main/js/views/project_info.js

@@ -88,7 +88,7 @@ var projectInfoObj = {
             $('#fullpath').html(this.getFullPathHtml(data));
             // 分享给
             $('#init-share').click(() => {
-                SHARE_TO.initModal(projectObj.project.ID());
+                SHARE_TO.initModal(SHARE_TO.Mode.PROJECT, projectObj.project.ID());
                 $('#share-tip').tooltip('hide');
             });
             SHARE_TO.handleEventListener();

+ 1 - 1
web/building_saas/main/js/views/project_property_basicInfo.js

@@ -523,7 +523,7 @@ $(document).ready(function () {
         basicInfoView.buildSheet();
         basicInfoView.showData(basicInfoView.datas);
         if(projectReadOnly){
-            disableSpread(basicInfoView.workBook);
+            sheetCommonObj.disableSpread(basicInfoView.workBook);
         }
     });
 

+ 1 - 1
web/building_saas/main/js/views/project_property_bills_quantity_decimal.js

@@ -353,7 +353,7 @@ $(document).ready(function () {
         billsDecimalView.buildSheet();
         billsDecimalView.showData(billsDecimalView.cache);
         if(projectReadOnly){
-            disableSpread(billsDecimalView.workBook);
+            sheetCommonObj.disableSpread(billsDecimalView.workBook);
         }
     });
 

+ 1 - 1
web/building_saas/main/js/views/project_property_labour_coe_view.js

@@ -51,7 +51,7 @@ let labourCoeView = {
         sheet.resumeEvent();
         sheet.resumePaint();
         if(projectReadOnly){
-            disableSpread(me.spread);
+            sheetCommonObj.disableSpread(me.spread);
         }
     },
     loadCrossData(datas){          // 交叉表:树结构转换二维表显示,行列转换

+ 1 - 1
web/building_saas/main/js/views/project_property_projFeature.js

@@ -506,7 +506,7 @@ $(document).ready(function () {
         projFeatureView.buildSheet();
         projFeatureView.showData(projFeatureView.datas);
         if (projectReadOnly) {
-            disableSpread(projFeatureView.workBook);
+            sheetCommonObj.disableSpread(projFeatureView.workBook);
         }
     });
 

+ 2 - 31
web/building_saas/main/js/views/project_view.js

@@ -646,7 +646,7 @@ var projectObj = {
             if(node.data.type != rationType.ration) return ;//只有定额类型才需要自动展开,其它都不用 
             let libID = node.data.libID;
             if (node.data.from === 'cpt') {
-                libID = rationLibObj.compleRationLibId;
+                libID = node.data.fromUser ? `${rationLibObj.compleRationLibId}*${node.data.fromUser}` : rationLibObj.compleRationLibId;
             }
             if(!rationLibObj.tree){
                 if(isDef(libID)) sessionStorage.setItem('stdRationLib', libID);
@@ -1032,7 +1032,7 @@ var projectObj = {
                 let mainTabFocus = sessionStorage.getItem('mainTab') ? sessionStorage.getItem('mainTab') : '#tab_zaojiashu';
                 $(`${mainTabFocus}`).click();
                 if(projectReadOnly){
-                    disableSpread(that.mainSpread);
+                    sheetCommonObj.disableSpread(that.mainSpread);
                 }
 
                 // 检查旧项目是否有调价数据,没有则自动生成 ----- 有种情况不行,如下:
@@ -3515,35 +3515,6 @@ function disableTools(){
     $('#cleanTender').prop('disabled', 'disabled');
     $('#calcTender').prop('disabled', 'disabled');
 }
-//项目只读,表格只读
-function disableSpread(spread){
-    spread.unbind(GC.Spread.Sheets.Events.ButtonClicked);
-    let sheetCount = spread.getSheetCount();
-    for(let i = 0; i < sheetCount; i++){
-        let sheet = spread.getSheet(i);
-        sheet.unbind(GC.Spread.Sheets.Events.ButtonClicked);
-        sheet.unbind(GC.Spread.Sheets.Events.EditStarting);
-        sheet.unbind(GC.Spread.Sheets.Events.EditEnded);
-        sheet.unbind(GC.Spread.Sheets.Events.RangeChanged);
-        sheet.unbind(GC.Spread.Sheets.Events.ClipboardChanging);
-        sheet.unbind(GC.Spread.Sheets.Events.ClipboardChanged);
-        sheet.unbind(GC.Spread.Sheets.Events.CellDoubleClick);
-        sheet.unbind(GC.Spread.Sheets.Events.CellClick);
-        sheet.unbind(GC.Spread.Sheets.Events.ValueChanged);
-        sheet.suspendPaint();
-        sheet.suspendEvent();
-        sheet.options.isProtected = true;
-        let rowCount = sheet.getRowCount();
-        let colCount = sheet.getColumnCount();
-        for(let row = 0; row < rowCount; row++){
-            for(let col = 0; col < colCount; col++){
-                sheet.getCell(row, col).locked(true);
-            }
-        }
-        sheet.resumePaint();
-        sheet.resumeEvent();
-    }
-}
 //根据触发改变计算基数、费率弹出框
 function changeCalcBaseFeeRate(toggle) {
     if(toggle === 'calcBase'){

+ 17 - 7
web/building_saas/main/js/views/std_ration_lib.js

@@ -46,7 +46,7 @@ var rationLibObj = {
             this.resultSpread.refresh();
         }
     },
-    loadStdRationLibs: function () {
+    loadStdRationLibs: async function () {
         let select = $('#stdRationLibSelect');
         select.empty();
         let ration_lib = projectObj.project.projectInfo.engineeringInfo.ration_lib;
@@ -55,6 +55,9 @@ var rationLibObj = {
             id: rationLibObj.compleRationLibId,
             name: '我的补充定额'
         });
+        const receiveList = await ajaxPost('/pm/api/getReceiveLibList', { user_id: userID, libType: commonConstants.ShareLibType.RATION_LIB });
+        const otherCompleLibs = receiveList.map(user => ({ name: `${user.real_name}的补充定额库`, isDefault: false, id: `${rationLibObj.compleRationLibId}*${user._id}`}));
+        ration_lib.push(...otherCompleLibs);
         let selectedRationLib = sessionStorage.getItem('stdRationLib');
         ration_lib.forEach(function (data) {
             let option = $('<option>').val(data.id).text(data.name);
@@ -104,8 +107,9 @@ var rationLibObj = {
         }
         return false;
     },
-    loadStdRation: function (rationLibID) {
+    loadStdRation: function (rationLibIDVal) {
         $.bootstrapLoading.start();
+        const [rationLibID, owner] = rationLibIDVal.split('*');
         rationLibObj.curLibType = rationLibID === rationLibObj.compleRationLibId ? rationLibObj.libType.complementary : rationLibObj.libType.std;
         var that = this;
         var showRationChapterTree = function (datas) {
@@ -139,7 +143,7 @@ var rationLibObj = {
             };
         };
         //type: 0-补充库 1-标准库
-        CommonAjax.post('/complementaryRation/api/getRationTree', {userId: userID, rationRepId: rationLibID, type: rationLibObj.curLibType}, function (datas) {
+        CommonAjax.post('/complementaryRation/api/getRationTree', {owner, userId: userID, rationRepId: rationLibID, type: rationLibObj.curLibType}, function (datas) {
             showRationChapterTree(datas);
             if(that.doAfterGetRationTree){
                 that.doAfterGetRationTree();
@@ -323,7 +327,8 @@ var rationLibObj = {
             }
         } */
         if (sectionID) {
-            CommonAjax.post('/complementaryRation/api/getRationGljItemsBySection', {user_Id: userID, sectionId: sectionID, type: me.curLibType}, function (datas) {
+            const [, owner] = $('#stdRationLibSelect').val().split('*');
+            CommonAjax.post('/complementaryRation/api/getRationGljItemsBySection', {user_Id: userID, sectionId: sectionID, type: me.curLibType, owner}, function (datas) {
                 const sectionItem = rationLibObj.tree.findNode(sectionID);
                 simplifyName(sectionItem, datas);
                 showDatas(datas, rationLibObj.sectionRationsSetting);
@@ -341,7 +346,8 @@ var rationLibObj = {
     onRationSpreadCellDoubleClick: function (sender, args) {
         var select = $('#stdRationLibSelect'), rationCode = args.sheet.getText(args.row, 0);
         if (rationCode !== '' && projectObj.project.Ration.canAdd(projectObj.project.mainTree.selected)) {
-            let query = {userID: userID, rationRepId: select.val(), code: rationCode};
+            const [rationLibID, owner] = select.val().split('*');
+            let query = {userID: owner || userID, rationRepId: rationLibID, code: rationCode};
             //搜索结果全部定额中双击添加定额、有可能同名不同库,更新查询的库ID
             if (rationLibObj.resultCache && rationLibObj.resultCache[args.row]) {
                 query.rationRepId = rationLibObj.resultCache[args.row].type === 'std' ? rationLibObj.resultCache[args.row].rationRepId : rationLibObj.compleRationLibId;
@@ -638,11 +644,15 @@ if($('#stdRationChapter').height() === 0 || $('#stdSectionRations').height() ===
     $('#stdSectionRations').height(270);
 }
 
-$('#stdRationTab').bind('click', function () {
+$('#stdRationTab').bind('click', async function () {
     var select = $('#stdRationLibSelect');
     rationLibObj.checkSpread();
     if (select[0].options.length === 0) {
-        rationLibObj.loadStdRationLibs();
+        try {
+            await rationLibObj.loadStdRationLibs();
+        } catch (err) {
+            alert(err);
+        }
         rationLibObj.loadStdRationContextMenu();
     };
 });

+ 1 - 1
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -100,7 +100,7 @@ var subRateObject={
             if(this.subRateSetting.view.lockColumns){
                 this.subRateSetting.view.lockColumns = null;
             }
-            disableSpread(this.subRateSpread);
+            sheetCommonObj.disableSpread(this.subRateSpread);
         }
     },
     showSubRateData:function () {

+ 3 - 3
web/building_saas/main/js/views/sub_view.js

@@ -60,9 +60,9 @@ let subObj = {
         sheetCommonObj.bindEscKey(subSpread, subEscSheets);
 
         if(projectReadOnly){
-            disableSpread(subSpread);
-            disableSpread(contentOprObj.workBook);
-            disableSpread(characterOprObj.workBook);
+            sheetCommonObj.disableSpread(subSpread);
+            sheetCommonObj.disableSpread(contentOprObj.workBook);
+            sheetCommonObj.disableSpread(characterOprObj.workBook);
         }
     },
     initNavItem:function (node) {

+ 3 - 3
web/building_saas/main/js/views/zmhs_view.js

@@ -146,7 +146,7 @@ let zmhs_obj = {
         }
         this.coeSheetData = coeList;
         if(projectReadOnly){
-            disableSpread(zmhs_obj.coeSpread);
+            sheetCommonObj.disableSpread(zmhs_obj.coeSpread);
         }
         if(preSelections){//定位光标到之前的位置
             this.coeSheet.setSelection(preSelections[0].row,preSelections[0].col,preSelections[0].rowCount,preSelections[0].colCount);
@@ -167,7 +167,7 @@ let zmhs_obj = {
         sheetCommonObj.showData(this.cusSheet, this.cusSetting,cusList);
         this.cusSheet.getRange(cusList.length,-1,this.cusSheet.getRowCount()-cusList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
         if(projectReadOnly){
-            disableSpread(zmhs_obj.cusSpread);
+            sheetCommonObj.disableSpread(zmhs_obj.cusSpread);
         }
     },
 
@@ -194,7 +194,7 @@ let zmhs_obj = {
         this.assSheet.resumePaint();
         this.assSheet.resumeEvent();
         if(projectReadOnly){
-            disableSpread(this.assSpread);
+            sheetCommonObj.disableSpread(this.assSpread);
         }
     },
     getAssList:function (node) {

+ 1 - 1
web/building_saas/pm/js/pm_newMain.js

@@ -363,7 +363,7 @@ const projTreeObj = {
             callback: function (key, opt) {
                 const selected = projTreeObj.tree.selected;
                 if (selected && selected.data.ID) {
-                    SHARE_TO.initModal(selected.data.ID);
+                    SHARE_TO.initModal(SHARE_TO.Mode.PROJECT, selected.data.ID);
                 }
             }
         },

+ 1 - 1
web/common/components/share/index.html

@@ -1,5 +1,5 @@
 <div class="modal fade" id="share" data-backdrop="static">
-    <div class="modal-dialog modal-lg" role="document">
+    <div class="modal-dialog modal-lg" role="document" style="max-width: 800px;">
         <div class="modal-content">
             <div class="modal-header">
                 <h5 class="modal-title">分享给...</h5>

+ 119 - 34
web/common/components/share/index.js

@@ -7,7 +7,21 @@ const SHARE_TO = (() => {
         CANCEL: 'cancel',
     };
 
-    const { SharePermissionChangeType: PermissionType, PageTarget } = commonConstants;
+    const { SharePermissionChangeType: PermissionType, PageTarget, ShareLibType } = commonConstants;
+
+
+    const Mode = {
+        PROJECT: 1,
+        RATION_LIB: 2
+    };
+
+    const ModeToLibType = {
+        [Mode.RATION_LIB]: ShareLibType.RATION_LIB
+    };
+
+    // 当前模式
+    let curMode = Mode.PROJECT;
+
 
     // 当前分享的项目ID
     let curProjectID;
@@ -25,9 +39,13 @@ const SHARE_TO = (() => {
     const rencentCount = 5;
 
     // 获取初始数据:1.最近分享人 2.联系人 3.已分享人
-    async function getInitalData(projectID) {
+    async function getInitialData(projectID) {
         return await ajaxPost('/pm/api/getInitialShareData', { user_id: userID, count: rencentCount, projectID }, false);
+    }
 
+    // 获取分享库的初始数据
+    async function getInitialLibData(libType) {
+        return await ajaxPost('/pm/api/getInitialShareLibData', { user_id: userID, count: rencentCount, libType }, false);
     }
 
     // 获取头像视图html
@@ -122,16 +140,16 @@ const SHARE_TO = (() => {
                         <div class="col-5">${company}</div>
                         <div class="col ml-auto p-0">
                             <div class="d-flex justify-content-end">
-                                <div>
-                                    <div class="custom-control custom-checkbox">
-                                        <input type="checkbox" class="custom-control-input allow-copy" id="${copyLabelFor}" data-user="${user._id}" ${user.allowCopy ? 'checked' : ''}>
-                                        <label class="custom-control-label" for="${copyLabelFor}">允许拷贝</label>
-                                    </div>
-                                    <div class="custom-control custom-checkbox">
-                                        <input type="checkbox" class="custom-control-input allow-edit" id="${editLabelFor}" data-user="${user._id}" ${user.allowCooperate ? 'checked' : ''}>
-                                        <label class="custom-control-label" for="${editLabelFor}">允许编辑</label>
-                                    </div>
-                                </div>
+                            ${curMode === Mode.PROJECT ? `<div>
+                            <div class="custom-control custom-checkbox">
+                                <input type="checkbox" class="custom-control-input allow-copy" id="${copyLabelFor}" data-user="${user._id}" ${user.allowCopy ? 'checked' : ''}>
+                                <label class="custom-control-label" for="${copyLabelFor}">允许拷贝</label>
+                            </div>
+                            <div class="custom-control custom-checkbox">
+                                <input type="checkbox" class="custom-control-input allow-edit" id="${editLabelFor}" data-user="${user._id}" ${user.allowCooperate ? 'checked' : ''}>
+                                <label class="custom-control-label" for="${editLabelFor}">允许编辑</label>
+                            </div>
+                        </div>` : ''}
                                 <div class="ml-3 d-flex align-items-center">
                                     <button class="btn btn-sm btn-outline-danger cancel-share" data-user="${user._id}">取消分享</button>
                                 </div>
@@ -153,7 +171,11 @@ const SHARE_TO = (() => {
         });
         // 取消分享
         $('#shared-list .cancel-share').click(function () {
-            handleShareAction.call(this, ShareType.CANCEL);
+            if (curMode === Mode.PROJECT) {
+                handleShareAction.call(this, ShareType.CANCEL);
+            } else {
+                handleShareLibAction.call(this, ShareType.CANCEL, ModeToLibType[curMode]);
+            }
         });
     }
 
@@ -177,16 +199,16 @@ const SHARE_TO = (() => {
                             <div class="col-5">${company}</div>
                             <div class="col ml-auto p-0">
                                     <div class="d-flex justify-content-end">
-                                        <div>
-                                            <div class="custom-control custom-checkbox">
-                                                <input type="checkbox" class="custom-control-input" id="allow-copy" checked="">
-                                                <label class="custom-control-label" for="allow-copy">允许拷贝</label>
-                                            </div>
-                                            <div class="custom-control custom-checkbox">
-                                                <input type="checkbox" class="custom-control-input" id="allow-edit">
-                                                <label class="custom-control-label" for="allow-edit">允许编辑</label>
-                                            </div>
+                                        ${curMode === Mode.PROJECT ? `<div>
+                                        <div class="custom-control custom-checkbox">
+                                            <input type="checkbox" class="custom-control-input" id="allow-copy" checked="">
+                                            <label class="custom-control-label" for="allow-copy">允许拷贝</label>
                                         </div>
+                                        <div class="custom-control custom-checkbox">
+                                            <input type="checkbox" class="custom-control-input" id="allow-edit">
+                                            <label class="custom-control-label" for="allow-edit">允许编辑</label>
+                                        </div>
+                                    </div>` : ''}
                                         <div class="ml-3 d-flex align-items-center"><button class="btn btn-sm btn-primary" id="share-to" data-user="${user._id}">分享给Ta</button></div>
                                     </div>
                                 </div>
@@ -204,7 +226,11 @@ const SHARE_TO = (() => {
             });
             // 分享给事件
             $('#share-to').click(function () {
-                handleShareAction.call(this, ShareType.CREATE, user);
+                if (curMode === Mode.PROJECT) {
+                    handleShareAction.call(this, ShareType.CREATE, user);
+                } else {
+                    handleShareLibAction.call(this, ShareType.CREATE, ModeToLibType[curMode], user);
+                }
             });
         }
     }
@@ -219,6 +245,52 @@ const SHARE_TO = (() => {
         }
     }
 
+    async function handleShareLibAction(shareType, libType, user) {
+        try {
+            $.bootstrapLoading.start();
+            const receiver = $(this).data('user');
+            let shareData;
+            if (shareType === ShareType.CREATE) {
+                shareData = [{ receiver }];
+            } else if (shareType === ShareType.CANCEL) {
+                shareData = [{ receiver, isCancel: true }];
+            }
+            const postData = {
+                type: shareType,
+                user_id: userID,
+                count: rencentCount,
+                libType,
+                shareData
+            };
+            const rst = await ajaxPost('/pm/api/shareLib', postData);
+            // 请求成功后刷新视图
+            if (shareType === ShareType.CREATE || shareType === ShareType.CANCEL) {
+                if (shareType === ShareType.CREATE) {
+                    curSharedUsers.unshift(user);
+                    $('#share-phone').val('');
+                    initSearchResultView();
+                } else {
+                    curSharedUsers = curSharedUsers.filter(user => user._id !== receiver);
+                }
+                if (Array.isArray(rst.recentUsers)) {
+                    initRecentView(rst.recentUsers);
+                }
+                if (Array.isArray(rst.contacts)) {
+                    initContactsView(rst.contacts)
+                }
+                initSharedView(curSharedUsers);
+                refreshShareTip(curSharedUsers);
+                refreshTreeView();
+            }
+        } catch (err) {
+            console.log(err);
+            alert(`${String(err)} 请重试。`);
+            initSharedView(curSharedUsers);
+        } finally {
+            $.bootstrapLoading.end();
+        }
+    }
+
     // 添加分享、编辑分享、取消分享的动作
     async function handleShareAction(shareType, user) {
         try {
@@ -470,25 +542,37 @@ const SHARE_TO = (() => {
     }
 
     // 初始化分享给的页面
-    async function initModal(projectID) {
+    // mode: 模式,分享项目、分享库
+    async function initModal(mode, projectID) {
         try {
-            curProjectID = projectID;
+            curMode = mode;
             $.bootstrapLoading.start();
             // 恢复
             $('#share-phone').val('');
             initSearchResultView();
             $('#share-hint').text('');
-            const { isFree, sharedUsers, recentUsers, contacts } = await getInitalData(projectID);
-            if (isFree) {
-                hintBox.versionBox('此功能仅在专业版中提供,免费版可选择单位工程进行分享。');
+            let sharedUsers = [];
+            let recentUsers = [];
+            let contacts = [];
+            let data;
+            if (mode === Mode.PROJECT) {
+                curProjectID = projectID;
+                data = await getInitialData(projectID);
+                if (data.isFree) {
+                    return hintBox.versionBox('此功能仅在专业版中提供,免费版可选择单位工程进行分享。');
+                }
             } else {
-                curSharedUsers = sharedUsers;
-                initSharedView(sharedUsers);
-                initRecentView(recentUsers);
-                initContactsView(contacts);
-                setTimeout(() => $('#share-phone').focus(), 200);
-                $('#share').modal('show');
+                data = await getInitialLibData(ModeToLibType[curMode]);
             }
+            sharedUsers = data.sharedUsers;
+            recentUsers = data.recentUsers;
+            contacts = data.contacts;
+            curSharedUsers = sharedUsers;
+            initSharedView(sharedUsers);
+            initRecentView(recentUsers);
+            initContactsView(contacts);
+            setTimeout(() => $('#share-phone').focus(), 200);
+            $('#share').modal('show');
         } catch (err) {
             console.log(err);
             alert(err);
@@ -595,6 +679,7 @@ const SHARE_TO = (() => {
     }
 
     return {
+        Mode,
         initModal,
         handleEventListener,
         permissionChangeListener,

+ 2 - 2
web/common/html/header.html

@@ -66,8 +66,8 @@
             <li class="nav-item dropdown">
                 <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-wrench" data-placement="bottom"></i> 工具</a>
                 <div class="dropdown-menu dropdown-menu-right">
-                    <a id="compleRationLib" class="dropdown-item compleRationLib" href="/complementaryRation/ration" target="_blank">定额库编辑器</a>
-                    <a id="compleGljLib" class="dropdown-item compleGljLib" href="/complementaryGlj" target="_">人材机库编辑器</a>
+                    <a id="compleRationLib" class="dropdown-item compleRationLib" href=<%- "/complementaryRation/ration/" + userID %> target="_blank">定额库编辑器</a>
+                    <a id="compleGljLib" class="dropdown-item compleGljLib" href=<%- "/complementaryGlj" %> target="_blank">人材机库编辑器</a>
                 </div>
             </li>
             <% } %>