소스 검색

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuCost

TonyKang 5 년 전
부모
커밋
ae72be55ff

+ 5 - 1
modules/all_models/user.js

@@ -29,7 +29,11 @@ let upgrade = mongoose.Schema({
     compilationID:String,//编办ID
     upgrade_time:Number,
     isUpgrade:Boolean,
-    remark:String//描述:广东办刘飞 2018-06-17 启用/关闭
+    remark:String, //描述:广东办刘飞 2018-06-17 启用/关闭
+    deadline: {
+        type:String,
+        default: '',
+    },
 }, { _id: false })
 
 const userdList = mongoose.Schema({

+ 4 - 0
modules/import/controllers/import_controller.js

@@ -11,6 +11,10 @@ let controller = {
         let data = req.body;
         return await pm_facade.downLoadProjectFile(data);
     },
+    copyConstructionProject:async function(req){
+      let data = req.body;
+      return await pm_facade.copyConstructionProject(data);
+    },
     prepareInitialData: async function(req) {
         const data = req.body;
         return await pm_facade.prepareInitialData(data.userID, data.compilationID, data.example);

+ 1 - 0
modules/import/routes/import_route.js

@@ -9,6 +9,7 @@ module.exports = function (app) {
     importRouter.post('/importProject',importController.action);
     importRouter.post('/exportProject',importController.action);
     importRouter.post('/copyProject',importController.action);
+    importRouter.post('/copyConstructionProject',importController.action);
     importRouter.post('/prepareInitialData',importController.action);
     importRouter.get('/test',function (req,res) {
         res.json("hello word");

+ 1 - 1
modules/main/facade/ration_facade.js

@@ -533,7 +533,7 @@ async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
         if(isMaterial == true){//材料计算添加时要先检查
             for(let sub of std.rationGljList){
                 let t_g = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
-                if(t_g && connect_key == gljUtil.getIndex(t_g)) throw `本定额中包含工料机${t_g.code},与当前工料机编号相同,添加定额失败`;
+                if(t_g && connect_key == gljUtil.getIndex(t_g,['code','name','specs','unit','gljType'])) throw `本定额中包含工料机[${t_g.code}]${t_g.name},与当前工料机编号相同,添加定额失败`;
             }
         }
         for(let sub of std.rationGljList){

+ 4 - 1
modules/main/routes/main_route.js

@@ -6,6 +6,7 @@
 import BaseController from "../../common/base/base_controller";
 const projectModel = require("../../pm/models/project_model");
 const pmFacade = require('../../pm/facade/pm_facade');
+const systemSettingModel = require('../../system_setting/model/index');
 import OptionsDao from '../../options/models/optionsModel';
 import optionSetting from '../../options/models/optionTypes';
 let config = require("../../../config/config.js");
@@ -31,6 +32,7 @@ module.exports =function (app) {
                     options = await optionsDao.saveOptions(req.session.sessionUser.id, req.session.sessionCompilation._id, optionSetting);
                 }
                 const markReadProjectIDs = isOpenShareProject ? await pmFacade.markShareItemsRead(projectID, req.session.sessionUser.id) : [];
+                const version = await systemSettingModel.getVersion();
                 res.render('building_saas/main/html/main.html',
                     {
                         userAccount: req.session.userAccount,
@@ -43,7 +45,8 @@ module.exports =function (app) {
                         LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
                         options:JSON.stringify(options),
                         overWriteUrl:req.session.sessionCompilation.overWriteUrl,
-                        markReadProjectIDs: JSON.stringify(markReadProjectIDs)
+                        markReadProjectIDs: JSON.stringify(markReadProjectIDs),
+                        version
                     });
             } else {
                 res.redirect('/pm');

+ 15 - 0
modules/pm/controllers/pm_controller.js

@@ -870,6 +870,21 @@ module.exports = {
         }
         res.json(result);
     },
+    copyConstructionProject: async function (req, res) {
+      let data = JSON.parse(req.body.data);
+      let result = {
+          error: 0
+      };
+      try {
+          data.session = req.session;
+          result.data = await redirectToImportServer(data, "copyConstructionProject", req);
+      } catch (err) {
+          console.log(err);
+          result.error = 1;
+          result.message = err.message;
+      }
+      res.json(result);
+    },
     importProcessChecking:async function (req,res) {
         let result={
             error:0

+ 36 - 1
modules/pm/facade/pm_facade.js

@@ -48,6 +48,7 @@ module.exports={
     uploadToken:uploadToken,
     downLoadProjectFile:downLoadProjectFile,
     importProcessChecking:importProcessChecking,
+    copyConstructionProject,
     isTenderOverrun,
     getWelcomeInfo:getWelcomeInfo
 };
@@ -417,7 +418,7 @@ async function getShareInfoAfterChangePermission(permissionType, receiver, proje
 
 //拷贝例题项目
 //@param {String}userID {Array}projIDs拷贝的例题项目ID(建设项目、文件夹)@return {Boolean}
-async function copyExample(userID, compilation, projIDs){
+async function copyExample(userID, compilation, projIDs,nameMap){
     let allProjs = [],
         IDMapping = {},
         projMapping = {};
@@ -437,6 +438,7 @@ async function copyExample(userID, compilation, projIDs){
         if (i === parentExample.length - 1) {
             data.NextSiblingID = -1;
         }
+        if(nameMap && nameMap[data.ID]) data.name = nameMap[data.ID];
     }
     //获取所有的子项目
     let posterityProjs = await getPosterityProjects(projIDs);
@@ -1682,6 +1684,39 @@ async function importProcessChecking(data){
 
 }
 
+async function copyConstructionProject(data){
+  let log_data = {
+    key:data.key,
+    content: '正在复制建设项目,请稍候……',
+    userID:data.user_id,
+    compilationID: data.session.sessionCompilation._id,
+    status:"start",
+    create_time:+new Date()
+  };
+
+  await importLogsModel.create(log_data);
+  doCopy(data.user_id,data.session.sessionCompilation._id,data.projectID,data.newName,data.key);
+
+  return "start copy";
+  async function doCopy(user_id,compilationId,projectID,newName,key) {
+      let doc = {status:"finish"};
+      try {
+          let nameMap={};
+          nameMap[projectID] = newName
+          let r = await copyExample(user_id,compilationId,[projectID],nameMap);
+          if(r == false){
+              doc.errorMsg = "复制失败,请检查项目是否存在!";
+              doc.status = "error";
+          }
+      }catch (error){
+          console.log(error);
+          doc.errorMsg = "复制失败,请检查项目是否存在!";
+          doc.status = "error";
+      }finally {
+          await importLogsModel.update({key:key},doc);
+      }
+  }
+}
 
 async function importProject(data,req,updateData) {
     let result = {error:0};

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

@@ -65,6 +65,7 @@ module.exports = function (app) {
     pmRouter.post('/changeFile', pmController.changeFile);
     pmRouter.post('/exportProject', pmController.exportProject);
     pmRouter.post('/importProject', pmController.importProject);
+    pmRouter.post('/copyConstructionProject',systemMiddleware.tenderNumberChecking,pmController.copyConstructionProject);
     pmRouter.post('/importProcessChecking', pmController.importProcessChecking);
 
 

+ 11 - 0
modules/system_setting/model/index.js

@@ -0,0 +1,11 @@
+module.exports = {
+    getVersion,
+};
+
+const mongoose = require('mongoose');
+const sysModel = mongoose.model('system_setting');
+
+async function getVersion() {
+    const data = await sysModel.findOne({}, '-_id version').lean();
+    return data && data.version || '';
+}

+ 15 - 4
modules/users/controllers/cld_controller.js

@@ -11,7 +11,8 @@
 import CLDModel from "../models/cld_model";
 import UserModel from "../models/user_model"
 import CompilationModel from "../models/compilation_model";
-let online_facade = require('../facade/online_facade')
+let online_facade = require('../facade/online_facade');
+const SMS = require('../models/sms');
 
 class CLDController {
 
@@ -106,6 +107,9 @@ class CLDController {
     async setUsersUpgrade(request, response) {
         let ssoID = request.body.ssoId;
         let compilationID = request.body.cid;
+        let deadline = request.body.deadline || '';
+        let status = parseInt(request.body.status);
+        let smssend = parseInt(request.body.smssend);
         try {
 
             let userModel = new UserModel();
@@ -114,7 +118,7 @@ class CLDController {
 
             let compilationModel = new CompilationModel();
 
-            let compilationData = compilationModel.getCompilationById(compilationID);
+            let compilationData = await compilationModel.getCompilationById(compilationID);
 
             if (compilationData === null || compilationData === undefined) {
                 throw '不存在该编办或者编办未发布';
@@ -129,8 +133,9 @@ class CLDController {
             let upgradeInfo = {
                 compilationID:compilationID,//编办ID
                 upgrade_time:new Date().getTime(),
-                isUpgrade:true,
-                remark: ''
+                isUpgrade: status !== 2,
+                remark: '',
+                deadline: deadline,
             };
 
             if (upgradeIndex === -1) {
@@ -143,6 +148,12 @@ class CLDController {
             let result = await userModel.updateUser(condition, {upgrade_list: upgrade_list});
 
             if (result) {
+                // 短信发送
+                if (smssend) {
+                    // 发送短信
+                    const Sms = new SMS();
+                    await Sms.sendProductMsg(userData.mobile, status, userData.real_name, compilationData.name, deadline);
+                }
                 response.json({error: 0, msg: 'success'});
             } else {
                 throw '更新失败';

+ 45 - 0
modules/users/models/sms.js

@@ -111,6 +111,51 @@ class SMS {
         }
     }
 
+    async sendProductMsg(mobile, status, name, product, deadline) {
+        try {
+            let templateId = 0;
+            switch (status) {
+                case 1: templateId = 746380;break;// 产品升级通知
+                case 2: templateId = 746381;break;// 产品降级通知
+                case 3: templateId = 746379;break;// 产品延期通知
+            }
+            const formData = {
+                smsUser: this.smsUser,
+                templateId: templateId,
+                msgType: 0,
+                phone: mobile,
+            };
+            formData.vars = '{"%name%": "' + name + '", "%product%": "' + product + '"' + (status !== 2 ? ', "%deadline%": "' + deadline + '"' : '') +'}';
+            const signature = await this.getSignature(this.sortDict(formData), this.smskey);
+            formData.signature = signature;
+
+            let postData = {
+                url: this.url,
+                form: formData,
+                encoding: 'utf8'
+            };
+
+            return new Promise(function (resolve, reject) {
+                try {
+                    // 请求接口
+                    Request.post(postData, function (err, postResponse, body) {
+                        if (err) {
+                            throw '请求错误';
+                        }
+                        if (postResponse.statusCode !== 200) {
+                            throw '短信发送失败!';
+                        }
+                        resolve(body);
+                    });
+                } catch (error) {
+                    reject([]);
+                }
+            });
+        } catch (error) {
+            console.log(error);
+        }
+    }
+
     md5(data) {
         var str = data;
         return crypto.createHash("md5").update(str).digest("hex");

+ 1 - 1
modules/users/models/user_model.js

@@ -384,7 +384,7 @@ class UserModel extends BaseModel {
     /**
      * 从session中判断用户是否是免费版
      * @param {String} sessionVersion
-     * @return {Boolean} 
+     * @return {Boolean}
      */
     isFreeFromSession(sessionVersion) {
         if (!sessionVersion) {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2897 - 2828
package-lock.json


+ 31 - 5
public/common_util.js

@@ -51,12 +51,38 @@
     // 通过F11打开全屏后,没有办法通过代码退出全屏,只能通过F11退出:
     // https://stackoverflow.com/questions/51114885/combining-requestfullscreen-and-f11; https://stackoverflow.com/questions/43392583/fullscreen-api-not-working-if-triggered-with-f11/44368592#44368592;
     function handleFullscreen() {
-        const isFullscreen = window.innerHeight === window.screen.height;
-        if (isFullscreen) {
-            const p = document.exitFullscreen();
-            p.catch(() => alert('按F11即可退出全屏模式'));
+        if (isFullscreen()) {
+            const p = exitFullscreen();
+            if (Object.prototype.toString.call(p) === '[object Promise]') {
+                p.catch(() => alert('按F11即可退出全屏模式'));
+            }
         } else {
-            document.documentElement.requestFullscreen();
+            fullscreen(document.documentElement);
+        }
+    }
+    function isFullscreen() {
+        return window.innerHeight === window.screen.height;
+    }
+    function fullscreen(ele) {
+        if (ele.requestFullscreen) {
+            ele.requestFullscreen();
+        } else if (ele.mozRequestFullscreen) {
+            ele.mozRequestFullScreen();
+        } else if (ele.webkitRequestFullscreen) {
+            ele.webkitRequestFullscreen();
+        } else if (ele.msRequestFullscreen) {
+            ele.msRequestFullscreen();
+        }
+    }
+    function exitFullscreen() {
+        if(document.exitFullscreen) {
+            return document.exitFullscreen();
+        } else if(document.mozCancelFullscreen) {
+            return document.mozCancelFullscreen();
+        } else if(document.webkitExitFullscreen) {
+            return document.webkitExitFullscreen();
+        } else if(document.msExitFullscreen) {
+            return document.msExitFullscreen();
         }
     }
 

+ 5 - 2
public/web/syntax-detection.js

@@ -151,8 +151,11 @@ function checkSyntax() {
         }
 
         // DOM
-        if (typeof document.documentElement.requestFullscreen !== 'function') {
-            throw new TypeError('document.documentElement.requestFullscreen is not a function');
+        if (typeof document.documentElement.requestFullscreen !== 'function' && 
+            typeof document.documentElement.mozRequestFullscreen !== 'function' &&
+            typeof document.documentElement.webkitRequestFullscreen !== 'function' &&
+            typeof document.documentElement.msRequestFullscreen !== 'function') {
+            throw new TypeError('fullscreen is not a function');
         }
 
     } catch (err) {

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

@@ -45,6 +45,7 @@
         // const G_SHOW_BLOCK_LIB = true;
         const G_SHOW_BLOCK_LIB = false;
         const markReadProjectIDs = JSON.parse('<%- markReadProjectIDs %>');
+        const VERSION = '<%- version %>';
     </script>
 </head>
 

+ 1 - 0
web/building_saas/main/js/views/material_calc_view.js

@@ -1034,6 +1034,7 @@ materialCalcObj = {
 $(function () {
     $("#calc-nav").on('shown.bs.tab', function () {
         materialCalcObj.initTabWidth();
+        materialCalcObj.showDatas();
         projectGljObject.refreshSubViews();
     });
     $("#calTab ul li a").on('shown.bs.tab', function () {

+ 43 - 2
web/building_saas/pm/js/pm_share.js

@@ -445,7 +445,7 @@ const pmShare = (function () {
             let node = tree.items[options.row];
             // Draw Text
             GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
-            if (node && node.data.projType === projectType.tender) {
+            if (node && node.data.projType === projectType.tender||node.data.projType === projectType.project) {
                 let text = options.sheet.getText(options.row, options.col);
                 let acStyle = options.sheet.getActualStyle(options.row, options.col),
                     zoom = options.sheet.zoom();
@@ -732,6 +732,7 @@ const pmShare = (function () {
         //data.allowCopy与shareInfo里allowCopy的区别:
         //data.allowCopy为该单位实际的权限(跟着最新的分享信息走,可能随着父项)
         for (let data of datas) {
+            if(data.projType == projectType.project) data.allowCopy = isAllowCopy(userID, data); //20200715 专业版要求能复制建设项目
             if (data.projType === projectType.tender) {
                 data.allowCopy = isAllowCopy(userID, data);
                 data.allowCooperate = isAllowCoop(userID, data);
@@ -782,12 +783,27 @@ const pmShare = (function () {
                     icon: 'fa-copy',
                     disabled: function () {
                         let selected = tree.selected;
-                        return !(selected && selected.data.allowCopy);
+                        return !(selected && selected.data.allowCopy && selected.data.projType === projectType.tender);
                     },
                     callback: function (key, opt) {
                         $('#copyShare').modal('show');
                     }
                 },
+                "copyProject": {
+                  name: "拷贝建设项目",
+                  icon: 'fa-copy',
+                  disabled: function () {
+                      let selected = tree.selected;
+                      return !(selected && selected.data.allowCopy && selected.data.projType === projectType.project);
+                  },
+                  callback: function (key, opt) {
+                      if($(".p-title").text().includes('免费')){
+                        hintBox.versionBox('此功能仅在专业版中提供,免费公用版可选择单个分段进行拷贝');
+                        return;
+                      }
+                      copyContructionProject(tree.selected);
+                  }
+                },
                 "cancel": {
                     name: "清除",
                     icon: 'fa-remove',
@@ -928,6 +944,31 @@ const pmShare = (function () {
             alert(err);
         }
     }
+    //拷贝分享的建设项目
+    //@param {Object}selected 
+    async function copyContructionProject(selected){
+      try {
+        let newName = getCopyName(selected);
+        //获取单项工程的单位工程
+        let projectQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], userID: userID,projType: "Project"};
+        const rstData = await ajaxPost('/pm/api/getProjectsByQuery', {user_id: userID, query: projectQuery, options: '-_id -property'}, false, 10000);
+        for(let project of rstData){
+            if(project.name === newName){
+                alert("已存在此建设项目");
+                return;
+            }
+        }
+        let tenderCount = 0;
+        if(selected.children) tenderCount = selected.children.length;
+        let key = uuid.v1();
+        $.bootstrapLoading.progressStart('拷贝建设项目', true);
+        $("#progress_modal_body").text('正在拷贝建设项目,请稍候……');
+        await ajaxPost('/pm/api/copyConstructionProject', {user_id: userID, tenderCount: tenderCount,key:key,projectID:selected.data.actualTreeInfo.ID,newName:newName});
+        importProcessChecking(key, null, projTreeObj.emitTreeChange);
+      } catch (error) {
+        console.log(error);
+      }
+    }
     //获取拷贝后的名称
     //@param {Object}node @return {String}
     function getCopyName(node) {

+ 18 - 3
web/over_write/js/hunan_2020.js

@@ -68,7 +68,7 @@ function overwriteRationCalcBases (taxType){
         {type: 'measure1', name: '措施费I'},
         {type: 'measure2', name: '措施费II'},
         {type: 'manage', name: '企业管理费'},
-        {type: 'forceFee', name: '规费'},
+        {type: 'force', name: '规费'},
         {type: 'profit', name: '利润'},
         {type: 'tax', name: '税金'},
         {type: 'common', name: '建安费'},
@@ -237,9 +237,24 @@ if (typeof baseFigureTemplate !== 'undefined') {
         YHGCFBHSC(tender) {
             return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.SAFE_COST], tender, 'common');
         },
-        // 养护工程费(不含设备费) 算法:取清单固定类别是“建筑安装工程费”的金额,扣除设备的金额。
+        // 养护工程费(不含设备费) 算法:取清单固定类别是“建筑安装工程费”的金额,扣除设备的金额(所有设备类型的人材机型定额)
         YHGCFBHSB(tender) {
-            return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.EQUIPMENT_ACQUISITION_FEE], tender, 'common');
+            let baseFee = this['YHGCF'](tender);
+            const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+            const allSubNodes = [];
+            projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
+            const equipmentNodes = allSubNodes.filter(node => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            for (const node of equipmentNodes) {
+                const data = node.data;
+                if (cbTools.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
+                    cbTools.isUnDef(data.feesIndex[feeField]) || cbTools.isUnDef(data.feesIndex[feeField][subFeeField])) {
+                    continue;
+                }
+                baseFee -= data.feesIndex[feeField][subFeeField];
+            }
+            return baseFee.toDecimal(decimalObj.bills.totalPrice);
         },
         // 定额养护工程费 取清单固定类别是“建筑安装工程费”的定额建安费。
         DEYHGCF(tender) {