瀏覽代碼

1.广东建筑,清单基数的文字修改,将“施工机具费”改为“机具费”
2.广东建筑,计算程序把施工机具费改成了机具费后,导入导出接口相关代码更改
3.单位工程文件名称后面的“分享”按钮,改成蓝色底、白色字
4.分享按钮,滑过时,显示分享人数及简略信息
5.打开分享的项目,头部分享提示更改
6.广东的清单基数,缺少“甲供主材费”、“甲供设备费”
7.广东建筑,{暂估材料费(从子目汇总)}没有算上措施项目费下的材料暂估。
8.导入招标文件,报错问题

vian 5 年之前
父節點
當前提交
b5534d69ed

+ 1 - 1
modules/main/controllers/project_controller.js

@@ -48,7 +48,7 @@ module.exports = {
             } else {
                 callback(req, res, err, message, null);
             }
-        });
+        }, req.session.sessionUser.id);
     },
     getDataForInterface: async function (req, res) {
         const data = JSON.parse(req.body.data);

+ 2 - 2
modules/main/models/project.js

@@ -102,7 +102,7 @@ Project.prototype.save = function(datas, callback){
     me.datas = [];
 };
 
-Project.prototype.getData = function(projectID, callback){
+Project.prototype.getData = function(projectID, callback, userID){
     var functions = [];
     var itemName;
     let firstTime = +new Date();
@@ -114,7 +114,7 @@ Project.prototype.getData = function(projectID, callback){
                     let endTime = +new Date();
                     console.log(moduleName+'---------------'+(endTime - startTime));
                     cb(err, {moduleName: moduleName, data: data})
-                })
+                }, userID)
             }
         })(itemName))
     }

+ 9 - 1
modules/pm/controllers/pm_controller.js

@@ -211,7 +211,7 @@ module.exports = {
         });
     },
     //project getData接口
-    getData: function (projectID, callback) {
+    getData: function (projectID, callback, userID) {
         projectModel.findOne({ $or: [{ deleteInfo: null }, { 'deleteInfo.deleted': false }], ID: projectID }, '-_id').then(async function (project) {
             if (!project) {
                 callback('', consts.projectConst.PROJECT_INFO, {});
@@ -251,6 +251,14 @@ module.exports = {
             //获取单位工程完整目录结构
             let fullPath = await pm_facade.getFullPath(projectID);
             projInfo.fullPath = fullPath;
+            // 获取分享的tip
+            projInfo.shareTip = await pm_facade.getShareTip(projectID, 2);
+            // 获取分享状态
+            if (typeof userID === 'string') {
+                projInfo.shareState = await pm_facade.getShareState(projectID, userID);
+            }
+            // 获取项目所属用户
+            projInfo.owner = await userModel.findOne({_id: mongoose.Types.ObjectId(project.userID)}, 'real_name');
             callback('', consts.projectConst.PROJECT_INFO, project);
         }, function (err) {
             callback(err, consts.projectConst.PROJECT_INFO, {});

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

@@ -17,6 +17,8 @@ module.exports={
     getShareInfoMap,
     getRecentShareList,
     getProjectShareList,
+    getShareTip,
+    getShareState,
     moveProject:moveProject,
     accessToCopyProject,
     copyProject:copyProject,
@@ -268,26 +270,65 @@ async function getRecentShareList(userID, count) {
 }
 
 // 获取某项目的分享记录
-async function getProjectShareList(projectID) {
-    const sharedList = await shareListModel.find({ projectID }).lean();
+async function getProjectShareList(projectID, limit = null) {
+    const sharedList = limit 
+        ? await shareListModel.find({ projectID }).lean().sort({ shareDate: -1 }).limit(limit)
+        : await shareListModel.find({ projectID }).lean().sort({ shareDate: -1 });
     const userIDs = [];
     const userMap = {};
-    sharedList.forEach(item => {
+    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;
             user.allowCopy = matched.allowCopy;
             user.allowCooperate = matched.allowCooperate;
         }
     });
+    users.sort((a, b) => a.index - b.index);
     return users;
 }
 
+// 获取分享的提示(造价书分享按钮tooltip使用)
+async function getShareTip(projectID, limit) {
+    const task = [
+        getProjectShareList(projectID, limit),
+        shareListModel.count({ projectID })
+    ];
+    const [users, count] = await Promise.all(task);
+    return users.reduce((acc, user, index) => {
+        if (index === 0) {
+            acc += '已分享给';
+            acc += user.real_name;
+        } else {
+            acc += ` ${user.real_name}`;
+        }
+        if (index === users.length - 1 && count > limit) {
+            acc += `等${count}人`;
+        }
+        return acc;
+    }, '');
+}
+
+// 获取项目的分享状态
+// 分享项目的拷贝和编辑性,需要参考父项
+// 以项目链上最新更新的分享数据为准
+async function getShareState(projectID, receiver) {
+    const projectIDs = await getUpChainIDs(projectID);
+    const shareList = await shareListModel.find({ projectID: { $in: projectIDs }, receiver }).lean();
+    shareList.sort((a, b) => Date.parse(b.updateDate) - Date.parse(a.updateDate));
+    return {
+        allowCopy: shareList[0] && shareList[0].allowCopy || false,
+        allowCooperate: shareList[0] && shareList[0].allowCooperate || false
+    };
+}
+
 //拷贝例题项目
 //@param {String}userID {Array}projIDs拷贝的例题项目ID(建设项目、文件夹)@return {Boolean}
 async function copyExample(userID, compilation, projIDs){

+ 4 - 0
web/building_saas/css/main.css

@@ -56,6 +56,10 @@ font-size: .875rem;
 height: calc(1.5em + .5rem + 2px);
 font-size: .875rem;
 }
+.btn-xs{
+  padding:0rem .5rem;
+  font-size:.875rem;
+}
 /*自定义css*/
 .login-body,.login-html{
 height:100%;

+ 1 - 0
web/building_saas/main/js/models/calc_base.js

@@ -771,6 +771,7 @@ let baseFigureTemplate = {
         return rst;
     },
     'JGZCF': function (tender) {//甲供主材费
+        debugger;
         let rst = 0;
         let projGljs = calcBase.project.projectGLJ.datas.gljList;
         for(let glj of projGljs){

+ 21 - 3
web/building_saas/main/js/views/project_info.js

@@ -3,6 +3,21 @@
  */
 
 var projectInfoObj = {
+    getSubShareInfo: function (proj) {
+        const { allowCopy, allowCooperate } = proj.shareState;
+        let str = '(';
+        if (allowCopy) {
+            str += '可拷贝 ';
+        }
+        if (allowCooperate) {
+            if (allowCopy) {
+                str += ' ';
+            }
+            str += '可编辑';
+        }
+        str += ')';
+        return str === '()' ? '' : str;
+    },
     getFullPathHtml: function (proj) {
         let fullPath = [], i, pm = '<span class="text-truncate"><a href="/pm">项目管理</a></span>', angleRight = '<span class="text-truncate"><i class="fa fa-angle-right fa-fw"></i></span>';
         if (proj) {
@@ -10,6 +25,8 @@ var projectInfoObj = {
             let engName = pathArr[pathArr.length - 2] || '',
                 projectName = pathArr[pathArr.length - 3] || '',
                 folderName = pathArr[pathArr.length - 4] || '';
+            const subShareInfo = projectInfoObj.getSubShareInfo(proj);
+            const receiveTip = `<span class="alert alert-success py-0 px-2 m-0" id="share-info"><i class="fa fa-share-alt"></i>来自 ${proj.owner && proj.owner.real_name || ''} 的分享${subShareInfo}</span>`;
             let newHtml = `   <span data-toggle="tooltip" data-placement="bottom" data-original-title="${folderName}"><i class="fa fa-folder-open-o"></i>...</span>
                 <span class="text-muted px-1">\</span>
                 <span data-toggle="tooltip" data-placement="bottom" data-original-title="${projectName}"><i class="fa fa-cubes"></i>...</span>
@@ -18,15 +35,16 @@ var projectInfoObj = {
                 <span class="text-muted px-1">\</span>
                  <span><i class="fa fa-sticky-note-o"></i></span>
                 <span class="text-truncate"  data-toggle="tooltip" data-placement="bottom" data-original-title="${proj.name}">&nbsp;${proj.name}</span>
-                ${projectReadOnly ?
+                ${projectReadOnly || projectCooperate ? receiveTip : `<span id="share-tip" class="ml-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="${proj.shareTip}"><a id="init-share" href="javascript:;" class="btn btn-xs btn-primary"><i class="fa fa-share-alt"></i> 分享</a></span>`}
+                `;
+            /* ${projectReadOnly ?
                     '<span data-toggle="tooltip" data-placement="bottom" data-original-title="当前的工程状态为“只读”,如果要进行编辑,请在项目管理-分享界面,使用“拷贝工程”功能。">(只读)</span>'
                     : ''}
                 ${projectCooperate ?
                     '<span data-toggle="tooltip" data-placement="bottom" data-original-title="当前的工程状态为“协作”,可直接编辑分享人的原始数据。">(协作)</span>'
                     : ''}
                 
-                ${projectReadOnly || projectCooperate ? '' : '<span><a id="init-share" class="pl-2" href="javascript:;"><i class="fa fa-share-alt" aria-hidden="true"></i> 分享</a></span>'}
-                `;
+                ${projectReadOnly || projectCooperate ? '' : `<span id="share-tip" class="ml-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="${proj.shareTip}"><a id="init-share" href="javascript:;" class="btn btn-xs btn-primary"><i class="fa fa-share-alt"></i> 分享</a></span>`} */
             fullPath.push(newHtml);
             fullPath.push(`<input id="rootProjectName" value="${projectName}" type="hidden">`);
 

+ 25 - 0
web/common/components/share/index.js

@@ -261,6 +261,7 @@ const SHARE_TO = (() => {
                     initContactsView(rst.contacts)
                 }
                 initSharedView(curSharedUsers);
+                refreshShareTip(curSharedUsers);
                 refreshTreeView();
             }
         } catch (err) {
@@ -285,6 +286,30 @@ const SHARE_TO = (() => {
         }
     }
 
+    // 刷新造价书的分享按钮tooltip提示
+    function refreshShareTip(sharedUsers) {
+        const $shareTip = $('#share-tip');
+        if (!$shareTip) {
+            return;
+        }
+        const limit = 2;
+        const count = sharedUsers.length;
+        const users = sharedUsers.slice(0, 2);
+        const tip = users.reduce((acc, user, index) => {
+            if (index === 0) {
+                acc += '已分享给';
+                acc += user.real_name;
+            } else {
+                acc += ` ${user.real_name}`;
+            }
+            if (index === users.length - 1 && count > limit) {
+                acc += `等${count}人`;
+            }
+            return acc;
+        }, '');
+        $shareTip.attr('data-original-title', tip);
+    }
+
     // 初始化分享给的页面
     async function initModal(projectID) {
         try {

+ 23 - 8
web/over_write/js/guangdong_2018.js

@@ -45,7 +45,7 @@ function overwriteRationCalcBases (){
     rationCalcBases['甲供材料费'] = function (node, isTender) {
         return calcTools.partASupplyFee(node, '甲供材料费', isTender, false);
     };
-    rationCalcBases['甲供施工机具费'] = function (node, isTender) {
+    rationCalcBases['甲供机具费'] = function (node, isTender) {
         return calcTools.partASupplyFee(node, '甲供机械费', isTender, false);
     };
     rationCalcBases['甲供主材费'] = function (node, isTender) {
@@ -60,7 +60,7 @@ function overwriteRationCalcBases (){
     rationCalcBases['甲定材料费'] = function (node, isTender) {
         return calcTools.partASupplyFee(node, '甲定材料费', isTender, false);
     };
-    rationCalcBases['甲定施工机具费'] = function (node, isTender) {
+    rationCalcBases['甲定机具费'] = function (node, isTender) {
         return calcTools.partASupplyFee(node, '甲定机械费', isTender, false);
     };
     rationCalcBases['甲定主材费'] = function (node, isTender) {
@@ -106,7 +106,7 @@ if (typeof module !== 'undefined') {
             '分部分项工程费': {base: 'FBFXGCF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
             '分部分项人工费': {base: 'FBFXDEJJRGF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
             '分部分项材料费': {base: 'FBFXDEJJCLF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
-            '分部分项施工机具费': {base: 'FBFXDEJJJXF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
+            '分部分项机具费': {base: 'FBFXDEJJJXF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
             '分部分项主材费': {base: 'FBFXZCF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
             '分部分项设备费': {base: 'FBFXSBF', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
             '分部分项人工工日': {base: 'FBFXRGGR', fixedFlag: fixedFlag.SUB_ENGINERRING, class: 'FBFX'},
@@ -115,16 +115,29 @@ if (typeof module !== 'undefined') {
             '其他项目费': {base: 'QTXMF',  fixedFlag: fixedFlag.OTHER, class: 'QTXM'},
             '甲供人工费': {base: 'JGDEJJRGF', class: 'RCJ'},
             '甲供材料费': {base: 'JGDEJJCLF', class: 'RCJ'},
-            '甲供施工机具费': {base: 'JGDEJJJXF', class: 'RCJ'},
+            '甲供机具费': {base: 'JGDEJJJXF', class: 'RCJ'},
+            '甲供主材费': {base: 'JGZCF', class: 'RCJ'},
+            '甲供设备费': {base: 'JGSBF', class: 'RCJ'},
             '甲定人工费': {base: 'JDDEJJRGF', class: 'RCJ'},
             '甲定材料费': {base: 'JDDEJJCLF', class: 'RCJ'},
-            '甲定施工机具费': {base: 'JDDEJJJXF', class: 'RCJ'},
+            '甲定机具费': {base: 'JDDEJJJXF', class: 'RCJ'},
             '甲定主材费': {base: 'JDZCF', class: 'RCJ'},
             '甲定设备费': {base: 'JDSBF', class: 'RCJ'},
             '暂估材料费(从子目汇总)': {base: 'ZGCLFFZM', class: 'RCJ'},
             '税金': {base: 'SJ', fixedFlag: fixedFlag.TAX, class: 'SJ'}
         };
     }
+    if(typeof baseFigureTemplate !== 'undefined'){
+        baseFigureTemplate['ZGCLFFZM'] = function (tender) { //暂估材料费(从子目汇总)
+            const feeField = 'estimate';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            // 分部分项暂估合价
+            const subEngineeringFee = cbTools.getBillsFee(fixedFlag.SUB_ENGINERRING, feeField, subFeeField);
+            // 措施项目暂估合价
+            let measureFee = cbTools.getBillsFee(fixedFlag.MEASURE, feeField, subFeeField);
+            return (subEngineeringFee + measureFee).toDecimal(decimalObj.bills.totalPrice);
+        };
+    }
 }
 
 if(typeof gljCol !== 'undefined'){
@@ -196,7 +209,7 @@ if (typeof commonConstants !== 'undefined') {
         '{分部分项工程费}': 'QDF',
         '{分部分项人工费}': 'QRG',
         '{分部分项材料费}': 'QCL',
-        '{分部分项施工机具费}': 'QJX',
+        '{分部分项机具费}': 'QJX',
         '{分部分项主材费}': 'QZCF',
         '{分部分项设备费}': 'QSBF',
         '{分部分项人工工日}': 'FBFXRGGR', // 标准没有,自增
@@ -205,10 +218,12 @@ if (typeof commonConstants !== 'undefined') {
         '{其他项目费}': 'QTF',
         '{甲供人工费}': 'JGRGF', // 自增
         '{甲供材料费}': 'JGC',
-        '{甲供施工机具费}': 'JGSGJJF', // 自增
+        '{甲供机具费}': 'JGJJF', // 自增
+        '{甲供主材费}': 'JGZCF', // 自增
+        '{甲供设备费}': 'JGSBF', // 自增
         '{甲定人工费}': 'JDRGF', // 自增
         '{甲定材料费}': 'JDCLF', // 自增
-        '{甲定施工机具费}': 'JDSGJJF', // 自增
+        '{甲定机具费}': 'JDJJF', // 自增
         '{甲定主材费}': 'JDZCF', // 自增
         '{甲定设备费}': 'JDSBF', // 自增
         '{暂估材料费(从子目汇总)}': 'ZGCLFCZMHZ', // 自增

+ 2 - 2
web/over_write/js/guangdong_2018_export.js

@@ -108,7 +108,7 @@ const XMLStandard = (function () {
         '直接费': 'RGF+CLF+JXF+ZCF+SBF+GLF',
         '人工费': 'RGF',
         '材料费': 'CLF',
-        '施工机具费': 'JXF',
+        '机具费': 'JXF',
         '主材费': 'ZCF',
         '设备费': 'SBF',
         '管理费': 'GLF',
@@ -120,7 +120,7 @@ const XMLStandard = (function () {
         '直接费': 'ZJF',
         '人工费': 'RGF',
         '材料费': 'CLF',
-        '施工机具费': 'JXF',
+        '机具费': 'JXF',
         '主材费': 'ZCF',
         '设备费': 'SBF',
         '管理费': 'GLF',

+ 1 - 1
web/over_write/js/guangdong_2018_import.js

@@ -45,7 +45,7 @@ const importXML = (() => {
         '4': '四类地区',
     }
     // 一些数据是需要从后端获取自增数字后赋值的,这里是记录,用完会在extractProject清空
-    const countData = {
+    let countData = {
         projectCount: 0,    //项目数量
         projectGLJCount: 0,  //项目人材机数量
         ratioCount: 0,      //组成物数量