Explorar o código

feat: 分享定额库

vian %!s(int64=5) %!d(string=hai) anos
pai
achega
f6425f21d1
Modificáronse 49 ficheiros con 595 adicións e 191 borrados
  1. 3 0
      config/gulpConfig.js
  2. 1 0
      modules/all_models/ration.js
  3. 18 0
      modules/all_models/share_lib.js
  4. 4 2
      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 2
      modules/complementary_ration_lib/models/compleRationModel.js
  8. 29 18
      modules/complementary_ration_lib/models/searchModel.js
  9. 4 4
      modules/complementary_ration_lib/routes/routes.js
  10. 12 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. 64 9
      modules/pm/facade/pm_facade.js
  14. 3 0
      modules/pm/routes/pm_route.js
  15. 8 0
      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. 9 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. 11 5
      web/building_saas/complementary_ration_lib/js/ration.js
  22. 3 1
      web/building_saas/complementary_ration_lib/js/ration_assist.js
  23. 2 2
      web/building_saas/complementary_ration_lib/js/ration_coe.js
  24. 2 2
      web/building_saas/complementary_ration_lib/js/ration_glj.js
  25. 9 9
      web/building_saas/complementary_ration_lib/js/repository_glj.js
  26. 5 2
      web/building_saas/complementary_ration_lib/js/section_tree.js
  27. 2 2
      web/building_saas/main/js/views/calc_program_manage.js
  28. 2 2
      web/building_saas/main/js/views/config_material_view.js
  29. 3 3
      web/building_saas/main/js/views/divide_view.js
  30. 1 1
      web/building_saas/main/js/views/electrovalence_view.js
  31. 1 1
      web/building_saas/main/js/views/fee_rate_view.js
  32. 1 1
      web/building_saas/main/js/views/main_tree_col.js
  33. 5 5
      web/building_saas/main/js/views/material_calc_view.js
  34. 1 1
      web/building_saas/main/js/views/mbzm_view.js
  35. 2 2
      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 8
      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. 1 1
      web/building_saas/main/js/views/sub_view.js
  45. 4 4
      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. 117 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');

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

@@ -99,7 +99,8 @@ class CompleRationController extends BaseController{
                 if(overWrite.sortRationGLJ) util = overWrite;
             }
             if (data.type === libType.complementary) {
-                rations = await compleRationDao.getCompleRationBySection(req.session.sessionUser.id, data.sectionId,util);
+                const userID = data.owner || req.session.sessionUser.id;
+                rations = await compleRationDao.getCompleRationBySection(userID, data.sectionId,util);
             }  else {
                 rations = await compleRationDao.getRationGljItemsBySection(data.sectionId,util);
             }
@@ -111,7 +112,8 @@ class CompleRationController extends BaseController{
 
     async getCoeList(req, res){
         try{
-            let coeList = await coeFacade.getComplementaryCoes(req.session.sessionUser.id, req.session.sessionCompilation._id);
+            const { userID } = JSON.parse(req.body.data);
+            let coeList = await coeFacade.getComplementaryCoes(userID, req.session.sessionCompilation._id);
             callback(req, res, 0, 'success', coeList);
         } catch (err) {
             callback(req, res, 1, err, null);

+ 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,12 +40,24 @@ 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 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,
@@ -57,10 +71,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});
@@ -68,10 +83,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,
@@ -105,9 +121,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 - 2
modules/complementary_ration_lib/models/compleRationModel.js

@@ -19,7 +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){
         try{
@@ -463,7 +464,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);
@@ -471,6 +474,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,

+ 29 - 18
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] = String(rationRepIds[0]).split('*');//优先取第一个
             for (let l of rationRepIds){
-                if(l != firstLib && l != compleRationLib){
-                    otherLibs.push(l);
+                const [libID, owner] = String(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,16 +43,16 @@ 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') {
-                    let stdChapter = await stdSectionTreeModel.findOne({rationRepId: ration.rationRepId, ID: ration.sectionId, $or: [{isDeleted: null}, {isDeleted: false}]});
+                    let stdChapter = await stdSectionTreeModel.findOne({ID: ration.sectionId});
                     if(isDef(stdChapter)){
                         ration.chapter = stdChapter._doc;
                     }
                 } else {
-                    let compleChapter = await compleRationSectionTreeModel.findOne({ID: ration.sectionId, $or: [{isDeleted: null}, {isDeleted: false}]});
+                    let compleChapter = await compleRationSectionTreeModel.findOne({ID: ration.sectionId});
                     if(isDef(compleChapter)){
                         ration.chapter = compleChapter._doc;
                     }
@@ -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;
         }
@@ -110,14 +114,21 @@ class SearchDao{
         let resultCount = 0,
             rst = {data: [], count: null};
         try{
+            let compleLibUsers = new Set();
+            const stdRationLibs = [];
+            rationRepId.forEach(libItem => {
+                const [libID, owner] = String(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'}}]
                 }, {
@@ -125,7 +136,7 @@ class SearchDao{
                 }]
             };
             let compleFilter = {
-                userId: userId,
+                userId: { $in: compleLibUsers },
                 compilationId: compilationId,
                 '$and': [{
                     '$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
@@ -135,14 +146,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);

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

@@ -9,6 +9,9 @@ let bill_facade = require('../facade/bill_facade');
 let project_facade = require("../facade/project_facade");
 let logger = require("../../../logs/log_helper").logger;
 const GLJController = require("../../glj/controllers/glj_controller");
+const pmFacade = require('../../pm/facade/pm_facade');
+const { ShareLibType } = require('../../../public/common_constants');
+const compleRationLib = 'compleRationLib';
 let controller = {
     insertGLJAsRation:async function (req){
         let data = req.body.data;
@@ -19,6 +22,14 @@ let controller = {
         let data = req.body.data;
         data = JSON.parse(data);
         let userID = req.session.sessionUser.id;
+        const compilationID = req.session.sessionCompilation._id;
+        if (data.libIDs && !data.libIDs.includes(compleRationLib)) {
+            const rationLibUsers = await pmFacade.getReceiveLibList(userID, compilationID, ShareLibType.RATION_LIB);
+            data.libIDs.push(compleRationLib);
+            rationLibUsers.forEach(user => {
+                data.libIDs.push(`${compleRationLib}*${user._id}`);
+            });
+        }
         return await ration_facade.replaceRations(userID,data,req.session.sessionCompilation);
     },
     addNewRation:async function(req) {
@@ -28,6 +39,7 @@ let controller = {
         }
         data = JSON.parse(data);
         let start = +new Date();
+        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

@@ -73,6 +73,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();
@@ -308,6 +311,10 @@ function getProgramID(programArray,feeType) {
 async function insertNewRation(newData,defaultLibID,std,calQuantity,programArray) {//插入新的定额
     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;
@@ -355,6 +362,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,data.programArray);
         if(newRecode){
             recodes.push(newRecode);
@@ -1083,6 +1093,10 @@ async function updateCoeAdjust(data,compilation) {
 async function  updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false,programArray) {
     // 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

@@ -639,6 +639,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);
@@ -701,15 +776,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 });
             }

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

@@ -21,6 +21,8 @@ module.exports={
     getShareInfoMap,
     getRecentShareList,
     getProjectShareList,
+    getReceiveLibList,
+    getLibShareList,
     getUnreadShareListByCompilation,
     getShareTip,
     getShareState,
@@ -107,6 +109,7 @@ let compleGljSectionTModel = mongoose.model('complementary_glj_section_templates
 let progressiveModel = mongoose.model('std_progressive_lib');
 let importLogsModel = mongoose.model("import_logs");
 const shareListModel = mongoose.model('share_list');
+const shareLibModel = mongoose.model('share_libs');
 let welcomeModel = mongoose.model("welcome_setting");
 let divideModel = mongoose.model("divide_setting");
 let evaluateListModel = mongoose.model("evaluate_list");
@@ -238,19 +241,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: {
@@ -260,7 +267,7 @@ async function updateShareList(updateData) {
         }
     ));
     if (bulks.length) {
-        await shareListModel.bulkWrite(bulks);
+        await model.bulkWrite(bulks);
     }
 }
 
@@ -286,7 +293,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) {
@@ -328,6 +338,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

@@ -56,9 +56,12 @@ module.exports = function (app) {
     pmRouter.post('/getGCDatas', pmController.getGC);
     pmRouter.post('/recGC', pmController.recGC);
     pmRouter.post('/delGC', pmController.delGC);
+    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);

+ 8 - 0
public/common_constants.js

@@ -174,6 +174,13 @@
         BX: 5 // 补项
     };
 
+    // 分享库类型
+    const ShareLibType = {
+        RATION_LIB: 1,
+        GLJ_LIB: 2,
+        BLOCK_LIB: 3,
+    };
+
     return {
         fixedFlag,
         GRANULARITY,
@@ -189,5 +196,6 @@
         EXPORT_KIND,
         RationType,
         BillType,
+        ShareLibType,
     };
 })

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

@@ -1263,6 +1263,34 @@ var sheetCommonObj = {
         }
         return null;
     },
+    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 %>';
     </script>
@@ -603,6 +604,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>
@@ -612,6 +614,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>

+ 9 - 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();
 
@@ -452,9 +456,12 @@ let coeOprObj = {
     },
     getCoeList: function () {
         let me = coeOprObj;
+        const params = location.href.split('/');
+        const curUserID = params[params.length - 1];
         $.ajax({
             type: 'post',
-            url: 'api/getCoeList',
+            url: '/complementaryRation/api/getCoeList',
+            data: {data: JSON.stringify({userID: curUserID})},
             dataType: 'json',
             timeout:20000,
             success: function (result) {
@@ -475,7 +482,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');
         });
     }

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

@@ -619,7 +619,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){
@@ -675,12 +675,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--
@@ -689,12 +691,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,

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

@@ -412,7 +412,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) {
                 sheetCommonObj.cleanData(me.sheet, me.setting, -1);
                 let rstArr = [], dummyR = { gljId: 0, consumeAmt: 0 }, newAddArr = [];
@@ -557,7 +557,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);
                 var cacheArr = [];
                 for (let i = 0; i < rstData.length; i++) {

+ 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);
     },
 };
 
@@ -242,6 +242,9 @@ let sectionTreeObj = {
     },
     
     refreshBtn: function (selected) {
+        if (isReadOnly) {
+            return;
+        }
         let me = this;
         me.insertBtn.removeClass('disabled');
         me.removeBtn.removeClass('disabled');
@@ -529,7 +532,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

@@ -99,8 +99,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

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

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

@@ -79,9 +79,9 @@ let divideObj = {
     if(!projectReadOnly){
       this.initDivideRightClick();
     }else {
-      disableSpread(this.divideSpread);
-      disableSpread(this.billsSpread);
-      disableSpread(this.divideSubSpread);
+      sheetCommonObj.disableSpread(this.divideSpread);
+      sheetCommonObj.disableSpread(this.billsSpread);
+      sheetCommonObj.disableSpread(this.divideSubSpread);
     }
   },
   initExecSpread:function(){

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

@@ -145,7 +145,7 @@ let electrovalenceObj = {
     this.sheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onElectrovalenceEditStarting);
     this.sheet.name('electrovalence_sheet');
     if (projectReadOnly) {
-      disableSpread(this.spread);
+      sheetCommonObj.disableSpread(this.spread);
     }
   },
   showDatas: function (datas) {

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

@@ -447,7 +447,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/main_tree_col.js

@@ -660,7 +660,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')) {

+ 5 - 5
web/building_saas/main/js/views/material_calc_view.js

@@ -108,7 +108,7 @@ materialCalcObj = {
         this.materialSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMaterialRangeChange);
         this.materialSheet.name('material_calc');
         if(projectReadOnly){
-            disableSpread(this.materialSpread);
+            sheetCommonObj.disableSpread(this.materialSpread);
         }else {
             this.initRightClick("materialCalcSheet",this.materialSpread)
         }
@@ -124,7 +124,7 @@ materialCalcObj = {
         this.freightSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onFreightPriceRangeChange);
         this.freightSheet.name('freight_calc');
         if(projectReadOnly){
-            disableSpread(this.freightSpread);
+            sheetCommonObj.disableSpread(this.freightSpread);
         }else {
             this.initRightClick("freightSheet",this.freightSpread)
         }
@@ -140,7 +140,7 @@ materialCalcObj = {
         this.freightRationSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onFreightRationEditStarting);
         this.freightRationSheet.name('freight_ration');
         if(projectReadOnly){
-            disableSpread(this.freightRationSpread);
+            sheetCommonObj.disableSpread(this.freightRationSpread);
         }else {
             this.initRightClick("freight_ration_sheet",this.freightRationSpread);
         }
@@ -156,7 +156,7 @@ materialCalcObj = {
 
         this.priceRationSheet.name('price_ration');
         if(projectReadOnly){
-            disableSpread(this.priceRationSpread);
+            sheetCommonObj.disableSpread(this.priceRationSpread);
         }else {
             this.initRightClick("price_ration_sheet",this.priceRationSpread);
         }
@@ -172,7 +172,7 @@ materialCalcObj = {
         this.priceSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onPriceEditStarting);
         this.priceSheet.name('price_calc');
         if(projectReadOnly){
-            disableSpread(this.priceSpread);
+            sheetCommonObj.disableSpread(this.priceSpread);
         }else {
             this.initRightClick("priceSheet",this.priceSpread)
         }

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

@@ -58,7 +58,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 () {

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

@@ -83,7 +83,7 @@ projectGljObject={
             if(this.projectGljSetting.view.lockColumns){
                 this.projectGljSetting.view.lockColumns = null;
             }
-            disableSpread(this.projectGljSpread);  //disableRightMenu("project_glj_sheet",this.projectGljSpread,this.rightClickCallback);
+            sheetCommonObj.disableSpread(this.projectGljSpread);  //disableRightMenu("project_glj_sheet",this.projectGljSpread,this.rightClickCallback);
         }else {
             this.initProjectGljRightClick();
         }
@@ -121,7 +121,7 @@ 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

@@ -99,7 +99,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

@@ -459,7 +459,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

@@ -617,7 +617,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);
@@ -988,7 +988,7 @@ var projectObj = {
                 let mainTabFocus = sessionStorage.getItem('mainTab') ? sessionStorage.getItem('mainTab') : '#tab_zaojiashu';
                 $(mainTabFocus).click();
                 if(projectReadOnly){
-                    disableSpread(that.mainSpread);
+                    sheetCommonObj.disableSpread(that.mainSpread);
                 }
                 if (projectObj.project.projectInfo.lastFileVer != VERSION)
                     projectObj.project.calcProgram.doTenderCalc();  // 打开标段后,进行一次全部计算,包括调价计算。
@@ -3368,35 +3368,6 @@ function disableTools(){
     $('#cancel_divide_btn').prop('disabled', 'disabled');
     $('#cancel_all_divide_btn').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 - 8
web/building_saas/main/js/views/std_ration_lib.js

@@ -50,7 +50,7 @@ var rationLibObj = {
             this.resultSpread.refresh();
         }
     },
-    loadStdRationLibs: function () {
+    loadStdRationLibs: async function () {
         let from = $('#divide_de').is(':visible')?"divide_":"";
         let select = $(`#${from}stdRationLibSelect`);
         select.empty();
@@ -62,7 +62,9 @@ var rationLibObj = {
             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(`${from}stdRationLib`);
         ration_lib.forEach(function (data) {
             let option = $('<option>').val(data.id).text(data.name);
@@ -113,9 +115,10 @@ var rationLibObj = {
         }
         return false;
     },
-    loadStdRation: function (rationLibID){
+    loadStdRation: function (rationLibIDVal){
         let from = $('#divide_de').is(':visible')?"divide_":"";
         $.bootstrapLoading.start();
+        const [rationLibID, owner] = rationLibIDVal.split('*');
         rationLibObj.curLibType = rationLibID === rationLibObj.compleRationLibId ? rationLibObj.libType.complementary : rationLibObj.libType.std;
         var that = this;
         let rationChapterSpread = this[from+'rationChapterSpread'];
@@ -152,7 +155,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();
@@ -247,7 +250,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) {
                 let chapterSheet = me[from+'rationChapterSpread'].getActiveSheet();
                 let sectionName = chapterSheet.getText(chapterSheet.getActiveRowIndex(), chapterSheet.getActiveColumnIndex());
                 simplifyName(sectionName, datas);
@@ -267,7 +271,8 @@ var rationLibObj = {
         let pre = $('#divide_de').is(':visible')?"divide_":"";
         var select = $(`#${pre}stdRationLibSelect`), rationCode = args.sheet.getText(args.row, 0);
         if (rationCode !== '') {
-            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;
@@ -571,11 +576,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

@@ -58,7 +58,7 @@ var subRateObject={
             if(this.subRateSetting.view.lockColumns){
                 this.subRateSetting.view.lockColumns = null;
             }
-            disableSpread(this.subRateSpread);
+            sheetCommonObj.disableSpread(this.subRateSpread);
             disableRightMenu("subRate",this.subRateSpread);
         }else {
             this.initRightClick("subRate",this.subRateSpread)

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

@@ -50,7 +50,7 @@ let subObj = {
         sheetCommonObj.bindEscKey(subSpread, subEscSheets);
 
         if(projectReadOnly){
-            disableSpread(subSpread);
+            sheetCommonObj.disableSpread(subSpread);
         }
     },
     initNavItem:function (node) {

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

@@ -186,7 +186,7 @@ let zmhs_obj = {
         }
         this[pre+'coeSheetData'] = coeList;
         if(projectReadOnly){
-            disableSpread(zmhs_obj.coeSpread);
+            sheetCommonObj.disableSpread(zmhs_obj.coeSpread);
         }
         if(preSelections){//定位光标到之前的位置
             coeSheet.setSelection(preSelections[0].row,preSelections[0].col,preSelections[0].rowCount,preSelections[0].colCount);
@@ -213,7 +213,7 @@ let zmhs_obj = {
         sheetCommonObj.showData(this[pre+'cusSheet'], this.cusSetting,cusList);
         this[pre+'cusSheet'].getRange(cusList.length,-1,this[pre+'cusSheet'].getRowCount()-cusList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
         if(projectReadOnly){
-            disableSpread(zmhs_obj[pre+'cusSpread']);
+            sheetCommonObj.disableSpread(zmhs_obj[pre+'cusSpread']);
         }
     },
     showStableData: function (node) {
@@ -226,7 +226,7 @@ let zmhs_obj = {
         this[pre+"stableSheet"].getRange(0, proportionCol, stableList.length, 1, GC.Spread.Sheets.SheetArea.viewport).locked(false);
         this[pre+"stableSheet"].getRange(stableList.length, -1, this[pre+"stableSheet"].getRowCount() - stableList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
         if(projectReadOnly){
-            disableSpread(zmhs_obj[pre+'stableSpread']);
+            sheetCommonObj.disableSpread(zmhs_obj[pre+'stableSpread']);
         }
     },
     getComboBoxForCodes:function (coe,i) {
@@ -253,7 +253,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

@@ -329,7 +329,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>

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

@@ -7,7 +7,19 @@ 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 +37,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 +138,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 +169,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 +197,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 +224,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 +243,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 +540,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(`此功能仅在专业版中提供,${commonUtil.getVersionText()}可选择单个分段进行分享。`);
+            let sharedUsers = [];
+            let recentUsers = [];
+            let contacts = [];
+            let data;
+            if (mode === Mode.PROJECT) {
+                curProjectID = projectID;
+                data = await getInitialData(projectID);
+                if (data.isFree) {
+                    return hintBox.versionBox(`此功能仅在专业版中提供,${commonUtil.getVersionText()}可选择单个分段进行分享。`);
+                }
             } 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 +677,7 @@ const SHARE_TO = (() => {
     }
 
     return {
+        Mode,
         initModal,
         handleEventListener,
         permissionChangeListener,

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

@@ -57,8 +57,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>
             <% } %>