Browse Source

Merge branch '1.0.0_online' of http://smartcost.f3322.net:3000/SmartCost/ConstructionOperation into 1.0.0_online

TonyKang 6 years ago
parent
commit
911bcb4417
40 changed files with 651 additions and 269 deletions
  1. 1 1
      config/config.js
  2. 2 2
      config/db/db_manager.js
  3. 2 1
      modules/all_models/engineering_lib.js
  4. 17 0
      modules/all_models/online_logs.js
  5. 2 0
      modules/all_models/project_feature_lib.js
  6. 1 1
      modules/all_models/stdRation_lib.js
  7. 2 0
      modules/basic_info_lib/controllers/basic_info_controller.js
  8. 3 1
      modules/bills_lib/controllers/bills_lib_controllers.js
  9. 2 0
      modules/bills_template_lib/controllers/bills_template_controller.js
  10. 2 0
      modules/calc_program_lib/controllers/calc_program_controller.js
  11. 7 2
      modules/common/const/bills_fixed.js
  12. 2 0
      modules/fee_rate_lib/controllers/fee_rate_controller.js
  13. 2 0
      modules/main_col_lib/controllers/main_col_controller.js
  14. 2 0
      modules/material_replace_lib/controllers/material_replace_controller.js
  15. 44 1
      modules/project_feature_lib/controllers/project_feature_controller.js
  16. 17 8
      modules/project_feature_lib/facade/project_feature_facade.js
  17. 7 1
      modules/ration_repository/controllers/ration_repository_controller.js
  18. 2 1
      modules/ration_repository/controllers/repository_views_controller.js
  19. 128 207
      modules/ration_repository/models/ration_item.js
  20. 4 0
      modules/std_billsGuidance_lib/controllers/libController.js
  21. 13 2
      modules/std_glj_lib/controllers/gljController.js
  22. 2 0
      modules/std_glj_lib/controllers/gljMapController.js
  23. 3 2
      modules/users/controllers/compilation_controller.js
  24. 19 0
      modules/users/controllers/user_controller.js
  25. 60 0
      modules/users/facade/online_facade.js
  26. 1 0
      modules/users/routes/user_route.js
  27. 20 8
      web/common/js/slideResize.js
  28. 26 2
      web/maintain/project_feature_lib/html/main.html
  29. 3 0
      web/maintain/ration_repository/dinge.html
  30. 15 7
      web/maintain/ration_repository/js/installation.js
  31. 2 2
      web/maintain/ration_repository/js/main.js
  32. 6 5
      web/maintain/ration_repository/main.html
  33. 2 1
      web/maintain/report/js/rpt_tpl_pre_handle.js
  34. 13 8
      web/maintain/std_glj_lib/js/glj.js
  35. 2 2
      web/over_write/js/chongqing_2018.js
  36. 154 0
      web/over_write/js/neimenggu_2017.js
  37. 10 4
      web/users/js/compilation.js
  38. 14 0
      web/users/js/user.js
  39. 11 0
      web/users/views/compilation/add.html
  40. 26 0
      web/users/views/user/index.html

+ 1 - 1
config/config.js

@@ -11,7 +11,7 @@ module.exports = {
             auth: {
                 "authdb": "admin"
             },
-            connectTimeoutMS: 20000,
+            connectTimeoutMS: 100000,
             useMongoClient: true
         }
     },

+ 2 - 2
config/db/db_manager.js

@@ -50,11 +50,11 @@ module.exports = {
         var config = require("../config.js");
         var dbURL = 'mongodb://' + config[env].server + ":" + config[env].port + '/scConstruct';
         if(config[env].dbURL){
-            mg.connect(config[env].dbURL,{connectTimeoutMS: 20000,useMongoClient: true});
+            mg.connect(config[env].dbURL,{connectTimeoutMS: 100000,useMongoClient: true});
         } else if(config[env].options){
             mg.connect(dbURL,config[env].options);
         }else {
-            mg.connect(dbURL,{connectTimeoutMS: 20000,useMongoClient: true});//useMongoClient': true*! //报 DeprecationWarning: `open()` is deprecated in mongoose这个错
+            mg.connect(dbURL,{connectTimeoutMS:100000,useMongoClient: true});//useMongoClient': true*! //报 DeprecationWarning: `open()` is deprecated in mongoose这个错
         }
         var db = mg.connection;
         db.on("error",function (err) {

+ 2 - 1
modules/all_models/engineering_lib.js

@@ -79,7 +79,8 @@ let modelSchema = {
     //单位工程取费专业
     projectEngineering:Number,
     //是否计算安装增加费
-    isInstall:{type: Boolean, default: false}
+    isInstall:{type: Boolean, default: false},
+    seq:Number//序列号
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 

+ 17 - 0
modules/all_models/online_logs.js

@@ -0,0 +1,17 @@
+/**
+ * Created by zhang on 2019/4/12.
+ */
+//用户在线时长统计
+
+let mongoose = require("mongoose");
+let Schema = mongoose.Schema;
+
+// 表结构
+let schema = {
+    userID: String,
+    compilationID: String,
+    dateString: String,
+    dateTime:Number,//dateString转换回毫秒数对应的数值,方便查询
+    online_times: Number
+};
+mongoose.model("online_logs", new Schema(schema, {versionKey: false}),"online_logs");

+ 2 - 0
modules/all_models/project_feature_lib.js

@@ -12,6 +12,8 @@ const project_feature_lib = new Schema({
         createDate: Number,
         recentOpr: [oprSchema],
         name: String,
+        compilationId: String,
+        compilationName: String,
         feature:{
             type: [Schema.Types.Mixed],
             default: []

+ 1 - 1
modules/all_models/stdRation_lib.js

@@ -8,7 +8,7 @@ const oprSchema = require('../all_schemas/opr_schema');
 const RepositoryMapSchema = new Schema({
     "ID": Number,
     "dispName" : String,
-    "libCode": String, //定额编号
+    "libCode": String, //定额库编码
     "appType" : String, //如:"建筑" / "公路"
     "localeType": String, //如 各个省份 / 部颁
     "descr" : String,

+ 2 - 0
modules/basic_info_lib/controllers/basic_info_controller.js

@@ -4,6 +4,7 @@
 import BaseController from "../../common/base/base_controller";
 import basicInfoFacade from "../facade/basic_info_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class BasicInfoController extends BaseController{
     async main(request, response) {
@@ -59,6 +60,7 @@ class BasicInfoController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete basicInfoLib ${request.ip}`);
         let result={
             error:0
         };

+ 3 - 1
modules/bills_lib/controllers/bills_lib_controllers.js

@@ -5,7 +5,8 @@
 let billsLibDao = require("./../models/bills_lib_interfaces");
 let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
-}
+};
+let logger = require('../../../logs/log_helper').logger;
 
 module.exports = {
     getMaxNumber: function(req, res){
@@ -33,6 +34,7 @@ module.exports = {
     },
     deleteStdBillsLib: function(req, res){
         let data = JSON.parse(req.body.data);
+        logger.info(`deleteBillsLib ${req.ip}`);
         billsLibDao.deleteStdBillsLib(data, function(err, message){
             callback(req, res, err, message, null);
         });

+ 2 - 0
modules/bills_template_lib/controllers/bills_template_controller.js

@@ -11,6 +11,7 @@ import {default as BillsFixedFlagConst, List as BillsFixedFlagList} from "../../
 import {default as BillsTypeFlagConst, List as BillsTypeFlagList} from "../../common/const/bills_type.js";
 import CompilationModel from '../../users/models/compilation_model';
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class BillsTemplateController extends BaseController {
 
@@ -93,6 +94,7 @@ class BillsTemplateController extends BaseController {
     }
 
     async deleteLibByID(request,response){
+        logger.info(`delete billsTemplateLib ${request.ip}`);
         let result={
             error:0
         };

+ 2 - 0
modules/calc_program_lib/controllers/calc_program_controller.js

@@ -3,6 +3,7 @@
  */
 import BaseController from "../../common/base/base_controller";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 import calcProgramFacade from "../facade/calc_program_facade";
 import CompilationModel from '../../users/models/compilation_model';
 
@@ -71,6 +72,7 @@ class CalcProgramController extends BaseController {
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete calcProgramLib ${request.ip}`);
         let result={
             error:0
         };

+ 7 - 2
modules/common/const/bills_fixed.js

@@ -60,8 +60,11 @@ const fixedFlag = {
     //附加税
     ADDITIONAL_TAX: 28,
     //环境保护税
-    ENVIRONMENTAL_PROTECTION_TAX: 29
-
+    ENVIRONMENTAL_PROTECTION_TAX: 29,
+    //建设工程竣工档案编制费
+    PROJECT_COMPLETE_ARCH_FEE:30,
+    //住宅工程质量分户验收费
+    HOUSE_QUALITY_ACCEPT_FEE:31
 };
 const fixedFlagList = [
     {name: "分部分项工程", value: fixedFlag.SUB_ENGINERRING},
@@ -93,6 +96,8 @@ const fixedFlagList = [
     {name: "环境保护税", value: fixedFlag.ENVIRONMENTAL_PROTECTION_TAX},
     {name: '专项技术措施暂估价', value: fixedFlag.SPECIAL_TECH_PROVISIONAL},
     {name: '专业发包工程管理费', value: fixedFlag.LET_CONTRACT_MANAGEMENT},
+    {name: '建设工程竣工档案编制费', value: fixedFlag.PROJECT_COMPLETE_ARCH_FEE},
+    {name: '住宅工程质量分户验收费', value: fixedFlag.HOUSE_QUALITY_ACCEPT_FEE}
 ];
 
 export {fixedFlag as default, fixedFlagList as List};

+ 2 - 0
modules/fee_rate_lib/controllers/fee_rate_controller.js

@@ -3,6 +3,7 @@
  */
 import BaseController from "../../common/base/base_controller";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 import feeRateFacade from "../facade/fee_rate_facade";
 import CompilationModel from '../../users/models/compilation_model';
 
@@ -71,6 +72,7 @@ class FeeRateController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
         let result={
             error:0
         };

+ 2 - 0
modules/main_col_lib/controllers/main_col_controller.js

@@ -9,6 +9,7 @@
 import BaseController from "../../common/base/base_controller";
 import mainColFacade from "../facade/main_col_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class MainColController extends BaseController {
 
@@ -36,6 +37,7 @@ class MainColController extends BaseController {
     }
 
     async deleteLibByID(request,response){
+        logger.info(`delete colSettingLib ${request.ip}`);
         let result={
             error:0
         };

+ 2 - 0
modules/material_replace_lib/controllers/material_replace_controller.js

@@ -4,6 +4,7 @@
 import BaseController from "../../common/base/base_controller";
 import materialFacade from "../facade/material_replace_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class ReplaceController extends BaseController{
     /**
@@ -100,6 +101,7 @@ class ReplaceController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete materialLib ${request.ip}`);
         let result={
             error:0
         };

+ 44 - 1
modules/project_feature_lib/controllers/project_feature_controller.js

@@ -4,15 +4,57 @@
 import BaseController from "../../common/base/base_controller";
 import featureFacade from "../facade/project_feature_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import CompilationModel from '../../users/models/compilation_model';
+let mongoose = require('mongoose');
+let featureLibModel = mongoose.model('std_project_feature_lib');
 
 class FeatureController extends BaseController{
     async main(request, response) {
-        let featureLibs = await featureFacade.findByCondition({},{feature:0},false);
+        //
+        let allLibs = await featureLibModel.find({});
+        for (let lib of allLibs) {
+            if (lib.name.indexOf('重庆2018') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b52b027fd3bb0000b257cf8', compilationName: '重庆定额(2018)'}}, {multi: true});
+            } else if (lib.name.indexOf('甘肃2013') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b75146cfa63aa000df7ff3c', compilationName: '甘肃定额(2013)'}}, {multi: true});
+            } else if (lib.name.indexOf('江西2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b754aacfa63aa000df80481', compilationName: '江西定额(2017)'}}, {multi: true});
+            }else if (lib.name.indexOf('浙江2010') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b85218494c4a2000d3d8f5c', compilationName: '浙江定额(2010)'}}, {multi: true});
+            }else if (lib.name.indexOf('内蒙古2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c1760b489ad9a000dd1e78a', compilationName: '内蒙古定额(2017)'}}, {multi: true});
+            }else if (lib.name.indexOf('浙江2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c246ed917f3a0000dbf7111', compilationName: '浙江定额(2018)'}}, {multi: true});
+            }else if (lib.name.indexOf('广东') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c66649650da2d000d8d37ba', compilationName: '广东定额(2018)'}}, {multi: true});
+            }
+        }
+        //
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
+        let filter = request.query.filter ? {compilationId: request.query.filter} : {};
+        let featureLibs = await featureFacade.findByCondition(filter,{feature:0},false);
         let randerData = {
             title:'工程特征库',
             userAccount: request.session.managerData.username,
             userID: request.session.managerData.userID,
             featureLibs:featureLibs,
+            compilationList: compilationList,
             layout: 'maintain/common/html/layout'
         };
         response.render("maintain/project_feature_lib/html/main", randerData);
@@ -59,6 +101,7 @@ class FeatureController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete projectFeatureLib ${request.ip}`);
         let result={
             error:0
         };

+ 17 - 8
modules/project_feature_lib/facade/project_feature_facade.js

@@ -5,6 +5,7 @@ import mongoose from "mongoose";
 const uuidV1 = require('uuid/v1');
 let moment = require("moment");
 let projectFeatureModel = mongoose.model('std_project_feature_lib');
+let compilationModel = mongoose.model('compilation');
 
 
 let projectFeatureLib = {
@@ -18,14 +19,22 @@ let projectFeatureLib = {
     addLib : async function (data){
         let now = new Date().getTime();
         let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
-        let newLib = {
-            creator: data.userAccount,
-            createDate: now,
-            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
-            name: data.name,
-        };
-        newLib.ID = uuidV1();
-        return await projectFeatureModel.create(newLib);
+        //取编办信息
+        let compilation = await compilationModel.findOne({_id:data.compilationId});
+        if(compilation){
+            let newLib = {
+                creator: data.userAccount,
+                createDate: now,
+                recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+                name: data.name,
+                compilationId: data.compilationId,
+                compilationName: compilation.name,
+            };
+            newLib.ID = uuidV1();
+            return await projectFeatureModel.create(newLib);
+        }else {
+            throw  new Error("没有找到该编办!");
+        }
     },
     saveLib:async function(param) {
         return await projectFeatureModel.findOneAndUpdate(param.query,param.data,{new:true});

+ 7 - 1
modules/ration_repository/controllers/ration_repository_controller.js

@@ -6,6 +6,7 @@ var rationRepository = require("../models/repository_map");
 import baseController from "../../common/base/base_controller";
 import CompilationModel from "../../users/models/compilation_model";
 const gljMapModel = mongoose.model('std_glj_lib_map');
+const compilationModel = mongoose.model('compilation');
 import async from "async";
 var callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
@@ -19,6 +20,7 @@ const rationItem = require("../models/ration_item");
 const rationLibModel = mongoose.model('std_ration_lib_map');
 const rationItemModel = mongoose.model('std_ration_lib_ration_items');
 import STDGLJListModel from '../../std_glj_lib/models/gljModel';
+let logger = require('../../../logs/log_helper').logger;
 
 class RationRepositoryController extends baseController {
     async getRationLibsByCompilation(req, res){
@@ -134,6 +136,7 @@ class RationRepositoryController extends baseController {
     }
 
     deleteRationLib(req, res) {
+        logger.info(`deleteRationLib ${req.ip}`);
         let oprtor = req.body.oprtor,
             libId = req.body.libId;
         rationRepository.deleteRationLib(oprtor, libId, function (err, message) {
@@ -274,8 +277,11 @@ class RationRepositoryController extends baseController {
             }
             //获取所有的定额
             let allRations = await rationItemModel.find({rationRepId: rationRepId, $or: [{isDeleted: false}, {isDeleted: null}]});
+            let compilation = await compilationModel.findOne({_id: mongoose.Types.ObjectId(rationLib.compilationId)});
+            let tempUrl = compilation.overWriteUrl ? req.app.locals.rootDir + compilation.overWriteUrl : req.app.locals.rootDir;
+            let absoluteUrl = fs.existsSync(tempUrl) && fs.statSync(tempUrl).isFile()? tempUrl : null;
             for(let ration of allRations){
-                rationItem.calcForRation(stdGLJListByID, ration);
+                rationItem.calcForRation(stdGLJListByID, ration, absoluteUrl);
                 task.push({
                     updateOne: {
                         filter: {ID: ration.ID},

+ 2 - 1
modules/ration_repository/controllers/repository_views_controller.js

@@ -54,7 +54,8 @@ class ViewsController extends BaseController{
                 redirectCoe: redirectCoe,
                 redirectInstallation: redirectInstallation,
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
-                priceProperties: JSON.stringify(priceProperties)
+                priceProperties: JSON.stringify(priceProperties),
+                overWriteUrl: overWriteUrl
             });
     }
     async redirectGlj(req, res){

+ 128 - 207
modules/ration_repository/models/ration_item.js

@@ -301,8 +301,90 @@ function round(v,e){
     return Math.round(v*t)/t;
 }
 
+function calcRation(gljArr) {
+    let labourPrc = [],
+        materialPrc = [],
+        machinePrc = [],
+        managePrc = [],
+        profitPrc = [],
+        riskPrc = [],
+        singlePrc,
+        updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0};
+    gljArr.forEach(function (gljItem) {
+        if(gljItem.gljParentType !== -1){
+            singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
+            if(gljItem.gljParentType === 1){
+                labourPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType ===2){
+                materialPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 3){
+                machinePrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 6){
+                managePrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 7){
+                profitPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 8){
+                riskPrc.push(singlePrc);
+            }
+        }
+    });
+    if(labourPrc.length > 0){
+        let sumLaP = 0;
+        for(let i=0; i<labourPrc.length; i++){
+            sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], -6);
+        }
+        updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.labourPrice, -2);
+    }
+    if(materialPrc.length > 0){
+        let sumMtP = 0;
+        for(let i= 0; i<materialPrc.length; i++){
+            sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], -6);
+        }
+        updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.materialPrice, -2);
+    }
+    if(machinePrc.length > 0){
+        let sumMaP = 0;
+        for(let i =0; i< machinePrc.length; i++){
+            sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], -6);
+        }
+        updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.machinePrice, -2);
+    }
+    if(managePrc.length > 0){
+        let sumMgP = 0;
+        for(let i =0; i< managePrc.length; i++){
+            sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], -6);
+        }
+        updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.managePrice, -2);
+    }
+    if(profitPrc.length > 0){
+        let sumPfP = 0;
+        for(let i =0; i< profitPrc.length; i++){
+            sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], -6);
+        }
+        updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.profitPrice, -2);
+    }
+    if(riskPrc.length > 0){
+        let sumRkP = 0;
+        for(let i =0; i< riskPrc.length; i++){
+            sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], -6);
+        }
+        updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.riskPrice, -2);
+    }
+    return updatePrc;
+}
 
-rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
+rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, overWriteUrl, callback) {
     async.each(basePrcArr, function (basePrcObj, finalCb) {
         let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
         async.waterfall([
@@ -379,7 +461,6 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                     }
                 }
                 gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
-                    const processDecimal = -6;
                     if(err){
                         cb(err);
                     }
@@ -400,35 +481,25 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                                     }
                                     if(theGlj.gljType <= 3){
                                         gljParentType = theGlj.gljType;
-                                    }
-                                    if(theGlj.gljType > 200 && theGlj.gljType < 300){
+                                    } else if(theGlj.gljType > 200 && theGlj.gljType < 300){
                                         gljParentType = 2;
-                                    }
-                                    if(theGlj.gljType > 300 && theGlj.gljType < 400){
+                                    } else if(theGlj.gljType > 300 && theGlj.gljType < 400){
                                         gljParentType = 3;
-                                    }
-                                    //管理费
-                                    if(theGlj.gljType === 6){
+                                    } else if(theGlj.gljType === 6){   //管理费
                                         gljParentType = 6;
-                                    }
-                                    //利润
-                                    if(theGlj.gljType === 7){
+                                    } else if(theGlj.gljType === 7){    //利润
                                         gljParentType = 7;
-                                    }
-                                    //风险费
-                                    if(theGlj.gljType === 8){
+                                    } else if(theGlj.gljType === 8){    //风险费
                                         gljParentType = 8;
                                     }
                                     if(theGlj)
                                     if(theGlj.ID === adjGljId){
                                         gljArr.push({gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType});
-                                    }
-                                    else {
+                                    } else {
                                         if(theGlj.priceProperty && Object.keys(theGlj.priceProperty).length > 0){
                                             let priceKeys = Object.keys(theGlj.priceProperty);
                                             gljArr.push({gljId: theGlj.ID, basePrice: parseFloat(theGlj.priceProperty[priceKeys[0]]), gljParentType: gljParentType});
-                                        }
-                                        else {
+                                        } else {
                                             gljArr.push({gljId: theGlj.ID, basePrice: parseFloat(theGlj.basePrice), gljParentType: gljParentType});
                                         }
                                     }
@@ -441,82 +512,18 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                                     }
                                 })
                             });
-                            //recalculate the price of ration
-                            let labourPrc = [],
-                                materialPrc = [],
-                                machinePrc = [],
-                                managePrc = [],
-                                profitPrc = [],
-                                riskPrc = [],
-                                singlePrc,
-                                updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0};
-                            gljArr.forEach(function (gljItem) {
-                                if(gljItem.gljParentType !== -1){
-                                    singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
-                                    if(gljItem.gljParentType === 1){
-                                        labourPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType ===2){
-                                        materialPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 3){
-                                        machinePrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 6){
-                                        managePrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 7){
-                                        profitPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 8){
-                                        riskPrc.push(singlePrc);
-                                    }
-                                }
-                            });
-                            if(labourPrc.length > 0){
-                                let sumLaP = 0;
-                                for(let i=0; i<labourPrc.length; i++){
-                                    sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], processDecimal);
+                            let updatePrc = null;
+                            let overWriteCalc = false;  //需要重写算法
+                            if (overWriteUrl) {
+                                let overWriteExports = require(overWriteUrl);
+                                if (typeof overWriteExports.calcRation !== 'undefined') {
+                                    overWriteCalc = true;
+                                    updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
                                 }
-                                updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
                             }
-                            if(materialPrc.length > 0){
-                                let sumMtP = 0;
-                                for(let i= 0; i<materialPrc.length; i++){
-                                    sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
-                                }
-                                updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
-                            }
-                            if(machinePrc.length > 0){
-                                let sumMaP = 0;
-                                for(let i =0; i< machinePrc.length; i++){
-                                    sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
-                                }
-                                updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
-                            }
-                            if(managePrc.length > 0){
-                                let sumMgP = 0;
-                                for(let i =0; i< managePrc.length; i++){
-                                    sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], processDecimal);
-                                }
-                                updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
-                            }
-                            if(profitPrc.length > 0){
-                                let sumPfP = 0;
-                                for(let i =0; i< profitPrc.length; i++){
-                                    sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], processDecimal);
-                                }
-                                updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
-                            }
-                            if(riskPrc.length > 0){
-                                let sumRkP = 0;
-                                for(let i =0; i< riskPrc.length; i++){
-                                    sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], processDecimal);
-                                }
-                                updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
+                            if (!overWriteCalc) {
+                                updatePrc = calcRation(gljArr);
                             }
-                            updatePrc.basePrice = scMathUtil.roundTo(
-                                updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice + updatePrc.managePrice + updatePrc.profitPrice + updatePrc.riskPrice, -2);
                             let task = {
                                 updateOne: {
                                     filter: {
@@ -710,126 +717,40 @@ rationItemDAO.prototype.updateRationTemplate = async function (rationRepId, rati
 };
 
 //计算导入数据的价格
-rationItemDAO.prototype.calcForRation = function (stdGljList, ration) {
-    const processDecimal = -6;
-    //根据工料机类型划分价格
-    const labour = [1],
-        material = [201, 202, 203, 204, 205, 206, 207],
-        machine = [301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312],
-        manage = [6],
-        profit = [7],
-        risk = [8];
-    let labourPrc = [], materialPrc = [], machinePrc = [], managePrc = [], profitPrc = [], riskPrc = [],
-        singlePrc, updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, basePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0};
-    let rationGljList = ration.rationGljList;
-    for(let rationGlj of rationGljList){
+rationItemDAO.prototype.calcForRation = function (stdGljList, ration, overWriteUrl) {
+    let rationGljList = ration.rationGljList,
+        gljArr = [];
+    for(let rationGlj of rationGljList) {
         let glj = stdGljList[rationGlj.gljId];
-        let prcType = isDef(glj) ? getParentType(glj.gljType) : null;
-        if(isDef(prcType)){
-            singlePrc = scMathUtil.roundTo(parseFloat(glj.basePrice) * parseFloat(rationGlj.consumeAmt), -3);
-            if(prcType === 'labour'){
-                labourPrc.push(singlePrc);
-            }
-            else if(prcType === 'material'){
-                materialPrc.push(singlePrc);
-            }
-            else if(prcType === 'machine'){
-                machinePrc.push(singlePrc);
-            }
-            else if(prcType === 'manage'){
-                managePrc.push(singlePrc);
-            }
-            else if(prcType === 'profit'){
-                profitPrc.push(singlePrc);
-            }
-            else if(prcType === 'risk'){
-                riskPrc.push(singlePrc);
-            }
-        }
-    }
-    //计算人工费
-    if(labourPrc.length > 0){
-        let sumLaP = 0;
-        for(let i = 0, len  = labourPrc.length; i < len; i++){
-            sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], processDecimal);
-        }
-        updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
-    }
-    //材料费
-    if(materialPrc.length > 0){
-        let sumMtP = 0;
-        for(let i = 0, len  = materialPrc.length; i < len; i++){
-            sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
-        }
-        updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
-    }
-    //机械费
-    if(machinePrc.length > 0){
-        let sumMaP = 0;
-        for(let i = 0, len  = machinePrc.length; i < len; i++){
-            sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
-        }
-        updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
-    }
-    //管理费
-    if(managePrc.length > 0){
-        let sumMgP = 0;
-        for(let i = 0, len  = managePrc.length; i < len; i++){
-            sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], processDecimal);
-        }
-        updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
-    }
-    //利润
-    if(profitPrc.length > 0){
-        let sumPfP = 0;
-        for(let i = 0, len  = profitPrc.length; i < len; i++){
-            sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], processDecimal);
-        }
-        updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
-    }
-    //风险费
-    if(riskPrc.length > 0){
-        let sumRkP = 0;
-        for(let i = 0, len  = riskPrc.length; i < len; i++){
-            sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], processDecimal);
-        }
-        updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
-    }
-    //基价
-    updatePrc.basePrice = scMathUtil.roundTo(
-        updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice + updatePrc.managePrice + updatePrc.profitPrice + updatePrc.riskPrice, -2);
-    //更新定额数据
-    ration.labourPrice = updatePrc.labourPrice.toString();
-    ration.materialPrice = updatePrc.materialPrice.toString();
-    ration.machinePrice = updatePrc.machinePrice.toString();
-    ration.basePrice = updatePrc.basePrice.toString();
-
-    function isDef(v){
-        return v !== undefined && v !== null;
-    }
-    //是否属于人工、材料、机械类型
-    function getParentType(type){
-        if(labour.includes(type)){
-            return 'labour';
-        }
-        if(material.includes(type)){
-            return 'material';
-        }
-        if(machine.includes(type)){
-            return 'machine';
-        }
-        if(manage.includes(type)){
-            return 'manage';
+        let gljPType = parseInt(glj.gljType.toString().match(/\d+?/)[0]);
+        if (glj.priceProperty && Object.keys(glj.priceProperty).length > 0) {
+            let priceKeys = Object.keys(glj.priceProperty);
+            gljArr.push({
+                gljId: glj.ID,
+                basePrice: parseFloat(glj.priceProperty[priceKeys[0]]),
+                consumeAmt: rationGlj.consumeAmt,
+                gljParentType: gljPType
+            });
+        } else {
+            gljArr.push({gljId: glj.ID, basePrice: parseFloat(glj.basePrice), consumeAmt: rationGlj.consumeAmt, gljParentType: gljPType});
         }
-        if(profit.includes(type)){
-            return 'profit';
+        let updatePrc = null;
+        let overWriteCalc = false;  //需要重写算法
+        if (overWriteUrl) {
+            let overWriteExports = require(overWriteUrl);
+            if (typeof overWriteExports.calcRation !== 'undefined') {
+                overWriteCalc = true;
+                updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
+            }
         }
-        if(risk.includes(type)){
-            return 'risk'
+        if (!overWriteCalc) {
+            updatePrc = calcRation(gljArr);
         }
-        return null;
+        ration.labourPrice = updatePrc.labourPrice.toString();
+        ration.materialPrice = updatePrc.materialPrice.toString();
+        ration.machinePrice = updatePrc.machinePrice.toString();
+        ration.basePrice = updatePrc.basePrice.toString();
     }
-
 };
 
 /**

+ 4 - 0
modules/std_billsGuidance_lib/controllers/libController.js

@@ -10,6 +10,7 @@
 import BaseController from '../../common/base/base_controller';
 import moment from 'moment';
 const billsGuidanceFacade = require('../facade/facades');
+let logger = require('../../../logs/log_helper').logger;
 let callback = function (req, res, err, msg, data) {
     res.json({error: err, message: msg, data: data});
 };
@@ -45,6 +46,9 @@ class BillsGuideLibController extends BaseController{
                 await billsGuidanceFacade.initBillsGuideLib(data.updateData);
             }
             else{
+                if (data.updateType === 'delete') {
+                    logger.info(`delete billsGuidanceLib ${req.ip}`);
+                }
                 await billsGuidanceFacade.updateBillsGuideLib(data);
             }
             callback(req, res, 0, '', data.updateData);

+ 13 - 2
modules/std_glj_lib/controllers/gljController.js

@@ -13,6 +13,9 @@ const gljModel = mongoose.model('std_glj_lib_gljList');
 const stdRationModel = mongoose.model('std_ration_lib_ration_items');
 const cplRationModel = mongoose.model('complementary_ration_items');
 const fs = require('fs');
+const compilationModel = mongoose.model('compilation');
+const gljLibModel = mongoose.model('std_glj_lib_map');
+
 let gljDao = new GljDao();
 let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
@@ -34,9 +37,17 @@ class GljController extends BaseController{
             callback(req,res,err, 'Get Tree', data)
         });
     }
-    updateRationBasePrc(req, res){
+    async updateRationBasePrc(req, res){
         let basePrcArr = JSON.parse(req.body.basePrcArr);
-        rationItemDao.updateRationBasePrc(basePrcArr, function (err, message) {
+        let repId = req.body.repId;
+        let absoluteUrl = null;
+        let stdGljLib = await gljLibModel.findOne({ID: repId});
+        if(stdGljLib){
+            let compilation = await compilationModel.findOne({_id: mongoose.Types.ObjectId(stdGljLib.compilationId)});
+            let tempUrl = compilation.overWriteUrl ? req.app.locals.rootDir + compilation.overWriteUrl : req.app.locals.rootDir;
+            absoluteUrl = fs.existsSync(tempUrl) && fs.statSync(tempUrl).isFile()? tempUrl : null;
+        }
+        rationItemDao.updateRationBasePrc(basePrcArr, absoluteUrl, function (err, message) {
             if(err){
                 callback(req, res, err, message, null);
             }

+ 2 - 0
modules/std_glj_lib/controllers/gljMapController.js

@@ -6,6 +6,7 @@ import BaseController from "../../common/base/base_controller";
 import {GljMapDao} from "../models/gljMapModel";
 import CompilationModel from "../../users/models/compilation_model";
 let gljMapDao = new GljMapDao();
+let logger = require('../../../logs/log_helper').logger;
 
 let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
@@ -74,6 +75,7 @@ class GljMapController extends BaseController{
         })
     }
     removeGljLib(req, res){
+        logger.info(`deleteGljLib ${req.ip}`);
         let oprtor = req.body.oprtor,
             libId = req.body.libId;
         gljMapDao.removeGljLib(oprtor, libId, function (err, message) {

+ 3 - 2
modules/users/controllers/compilation_controller.js

@@ -26,6 +26,7 @@ import basicInfoFacade from "../../basic_info_lib/facade/basic_info_facade";
 import {default as category, List as categoryList} from "../../common/const/category_const.js";
 let config = require("../../../config/config.js");
 const fs = require('fs');
+let _ = require('lodash');
 
 class CompilationController extends BaseController {
 
@@ -149,7 +150,7 @@ class CompilationController extends BaseController {
             // 获取计价规则中对应的标准库数据
             let engineeringLibModel = new EngineeringLibModel();
             engineeringList = await engineeringLibModel.getLibsByValuationID(valuationId);
-
+            engineeringList = _.sortBy(engineeringList,['seq'])
         } catch (error) {
             console.log(error);
         }
@@ -236,7 +237,7 @@ class CompilationController extends BaseController {
             billsGuidanceList = await billsGuidanceFc.getBillsGuideLibs({compilationId: selectedCompilation._id, $or: [{deleted: null}, {deleted: false}]});
 
             //获取工程特征库
-            featureList = await projectFeatureFacade.findByCondition({},null,false);
+            featureList = await projectFeatureFacade.findByCondition({compilationId: selectedCompilation._id},null,false);
 
             //获取基本信息库
             infoList = await basicInfoFacade.findByCondition({},null,false);

+ 19 - 0
modules/users/controllers/user_controller.js

@@ -11,6 +11,7 @@ import Config from "../../../config/config";
 import CompilationModel from "../models/compilation_model";
 let config = require("../../../config/config.js");
 let _ = require("lodash");
+let online_facade = require('../facade/online_facade')
 
 class UserController extends BaseController {
 
@@ -66,6 +67,7 @@ class UserController extends BaseController {
             // console.log(condition);
             // 获取用户列表
             userList = await userModel.getList(condition, page, Config.pageSize);
+            await online_facade.setOnlineTimes(userList,condition);
             // console.log(userList)
         } catch (error) {
             console.log(error);
@@ -225,6 +227,23 @@ class UserController extends BaseController {
         response.json(responseData);
     }
 
+    async getOnlineInfo(request, response){
+        let filter = JSON.parse(request.body.data);
+        let responseData = {
+            error: 0,
+            msg: '',
+            data: null
+        };
+        try{
+            let info = await online_facade.getOnlineInfo(filter);
+            responseData.data = info;
+        } catch (error) {
+            console.log(error);
+            responseData.error = error.code;
+            responseData.msg = error.err;
+        }
+        response.json(responseData);
+    }
 
     async updateUser(request, response) {
         let data = JSON.parse(request.body.data);

+ 60 - 0
modules/users/facade/online_facade.js

@@ -0,0 +1,60 @@
+/**
+ * Created by zhang on 2019/4/16.
+ */
+
+module.exports = {
+    setOnlineTimes:setOnlineTimes,
+    getOnlineInfo:getOnlineInfo
+};
+
+let mongoose = require("mongoose");
+let logs_model = mongoose.model("online_logs");
+
+async function getOnlineInfo(filter) {
+    let datas = [];
+    let logs = await logs_model.find(filter);
+    let less = 0;
+    for(let l of logs){
+        let d = getTimeString(l.online_times);
+        let online_times = d.s;
+        less += d.less;
+        if(online_times!=""){
+            datas.push({dateString:l.dateString,dateTime:l.online_times,online_times:online_times})
+        }
+    }
+    if(datas.length>1){//大于2个才把不够1分钟的累积到最后一条记录
+        let last =  datas[datas.length - 1];
+        last.online_times = getTimeString(last.dateTime + less).s;
+    }
+
+    return datas;
+}
+
+
+async function setOnlineTimes(userList,condition){
+    for(let u of userList){
+        let filter = {'userID':u._id.toString()};
+        if(u.latest_used) filter["compilationID"] = u.latest_used;
+        if(condition.latest_login && condition.latest_login == ""){
+            let startTime = condition.latest_login['$gte']; //- 24*60*60*1000 //往前推一天  {'$gte': startTime, '$lt': endTime}latest_login
+            filter['dateTime'] = {'$gte': startTime, '$lt':  condition.latest_login['$lt']}
+        }
+        let result =  await logs_model.aggregate([
+            {$match: filter},
+            {$group: {_id: "$userID", total: {$sum: "$online_times"}}}
+        ]);
+        u._doc.filter = JSON.stringify(filter);
+        if(result.length > 0)  u._doc.online_times = getTimeString(result[0].total).s;
+    }
+}
+
+
+function getTimeString(times) {
+    let s = "",perHour = 1000 * 60 * 60,perMin = 1000 * 60;
+    let hour = parseInt(times/perHour);
+    let min = parseInt((times % perHour)/perMin);
+    let less =  (times % perHour)%perMin;//不够一分钟的时间
+    if(hour > 0) s = s+`${hour}小时`;
+    if(min > 0)  s= s+`${min}分钟`;
+    return {s:s,less:less}
+}

+ 1 - 0
modules/users/routes/user_route.js

@@ -17,6 +17,7 @@ module.exports =function (app) {
     router.get('/testUser', userController.auth, userController.init, userController.testUsers);
     router.get('/search', userController.auth, userController.init, userController.search);
     router.post('/findByID', userController.auth, userController.init, userController.findByID);
+    router.post('/getOnlineInfo', userController.auth, userController.init, userController.getOnlineInfo);
     router.post('/getUserList', userController.auth, userController.init, userController.getUserList);
     router.post('/updateUser', userController.auth, userController.init, userController.updateUser);
     router.post('/deleteUser', userController.auth, userController.init, userController.deleteUser);

+ 20 - 8
web/common/js/slideResize.js

@@ -15,6 +15,14 @@
  * */
 
 const SlideResize = (function() {
+    //函数防抖
+    let timer = null;
+    function deBounce(fn, wait) {
+        if (timer) {
+            clearTimeout(timer);
+        }
+        timer = setTimeout(fn, wait);
+    }
     //设置水平拖动条的宽度
     //@param {Object dom}resize滚动条
     function setResizeWidth (resize) {
@@ -74,10 +82,12 @@ const SlideResize = (function() {
                 eleObj.right.css('width', rightPercentWidth);
                 setResizeWidth(eleObj.resize);
                 mouseMoveCount += Math.abs(moveSize);
-                if (mouseMoveCount > triggerCBSize && callback) {
-                    callback();
-                    mouseMoveCount = 0;
-                }
+                deBounce(function () {
+                    if (callback) {
+                        callback();
+                        mouseMoveCount = 0;
+                    }
+                }, 20)
             }
         });
         $('body').mouseup(function (e) {
@@ -152,10 +162,12 @@ const SlideResize = (function() {
                 //设置下部分div内spread高度
                 eleObj.bottomSpread.height(bottomChange - limit.notBottomSpread);
                 mouseMoveCount += Math.abs(moveSize);
-                if (mouseMoveCount > triggerCBSize && callback) {
-                    callback();
-                    mouseMoveCount = 0;
-                }
+                deBounce(function () {
+                    if (callback) {
+                        callback();
+                        mouseMoveCount = 0;
+                    }
+                }, 20)
             }
         });
         $('body').mouseup(function (e) {

+ 26 - 2
web/maintain/project_feature_lib/html/main.html

@@ -2,14 +2,29 @@
     <div class="content">
         <div class="container-fluid">
             <div class="row">
-                <div class="col-md-5">
+                <div class="col-md-2">
+                    <div class="list-group mt-3">
+                        <% for (let compilation of compilationList) { %>
+                        <% if (compilation._id === 'all') { %>
+                        <a href="/projectFeature/main" class="list-group-item list-group-item-action <%= compilation.active %>">
+                            所有
+                        </a>
+                        <% } else { %>
+                        <a id="<%= compilation._id %>" href="/projectFeature/main?filter=<%= compilation._id %>" class="list-group-item list-group-item-action <%= compilation.active %>">
+                            <%= compilation.name %>
+                        </a>
+                        <% }} %>
+                    </div>
+                </div>
+                <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                         <table class="table table-hover table-bordered">
-                            <thead><tr><th >库名称</th><th width="160">添加时间</th><th width="120">操作</th></tr></thead>
+                            <thead><tr><th >库名称</th><th>费用定额</th><th width="160">添加时间</th><th width="120">操作</th></tr></thead>
                             <tbody id="showArea">
                             <% for(let lib of featureLibs){ %>
                             <tr class="libTr">
                                 <td id="<%= lib.ID%>"><a href="/projectFeature/edit/<%= lib.ID%>"><%= lib.name%></a></td>
+                                <td><%= lib.compilationName%></td>
                                 <td><%= moment(lib.createDate).format('YYYY-MM-DD')%></td>
                                 <td>
                                     <a style="color: #0275d8" onclick='getFeatureLib("<%= lib.ID%>")' title="编辑"><i class="fa fa-pencil-square-o"></i></a>
@@ -43,6 +58,15 @@
                         <input id="name" name="name" class="form-control" placeholder="请输入特征库名称" type="text">
                         <small class="form-text text-danger" id="nameError" style="display: none">请输入特征库名称。</small>
                     </div>
+                    <div class="form-group">
+                        <label>编办名称</label>
+                        <select class="form-control" name="compilationId">
+                            <% for (let compilation of compilationList) { %>
+                                <% if (compilation.name !== '所有') { %>
+                            <option value="<%= compilation._id %>"><%= compilation.name %></option>
+                            <% }} %>
+                        </select>
+                    </div>
                     <input type="hidden" name = "userAccount" value="<%= userAccount%>">
                 </form>
             </div>

+ 3 - 0
web/maintain/ration_repository/dinge.html

@@ -675,6 +675,9 @@
         <script type="text/javascript" src="/public/web/QueryParam.js"></script>
         <script type="text/javascript" src="/public/web/storageUtil.js"></script>
         <script type="text/javascript" src="/web/maintain/ration_repository/js/coe.js"></script>
+        <% if(overWriteUrl){ %>
+        <script type="text/javascript" src="<%= overWriteUrl %>"></script>
+        <% } %>
         <script src="/lib/codemirror/codemirror.js"></script>
         <script src="/lib/codemirror/xml.js"></script>
         <script src="/web/common/js/uploadImg.js"></script>

+ 15 - 7
web/maintain/ration_repository/js/installation.js

@@ -188,6 +188,7 @@ let feeItemObj = {
         if(!me.isDef(feeItem)){
             me.workBook.focus(true);
             me.currentFeeItem = null;
+            se.cache= [];
             return;
         }
         fr.addObj = null;
@@ -202,7 +203,7 @@ let feeItemObj = {
     },
     onSelectionChanged: function (sender, info) {
         let me = feeItemObj;
-        if(info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
+        if(!info.oldSelections || info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
             let row = info.newSelections[0].row;
             let node = me.cache[row];
             me.initSelection(node);
@@ -262,7 +263,7 @@ let feeItemObj = {
         me.updateFeeItem([updateObj]);
     },
     onClipboardPasting: function (sender, info) {
-        let me = this;
+        let me = feeItemObj;
         if(info.cellRange.col + info.cellRange.colCount > me.setting.header.length){
             info.cancel = true;
         }
@@ -657,7 +658,7 @@ let feeRuleObj = {
             this.buildHeader();
             this.sheet.setRowCount();
 
-
+            this.sheet.options.allowCellOverflow = false;
             sheetCommonObj.bindEscKey(this.workBook, [{sheet: this.sheet, editStarting: this.onEditStarting, editEnded: this.onEditEnded}])
             this.setOptions(this.workBook, this.setting.options);
             this.sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
@@ -713,35 +714,44 @@ let feeRuleObj = {
     validPasteData: function (data) {
         //插入须有编码
         if(!this.isDef(data.code)){
+            alert('粘贴时,编码不能为空,或者粘贴的数据中需包含编码');
             return false;
         }
         //编码须唯一
         if(this.isDef(data.code) && this.hasCode(data)){
+            alert('编码须唯一!');
             return false;
         }
         //基数要合法
         if(this.isDef(data.base) && this.setting.comboItems.base.indexOf(data.base) < 0){
+            alert('基数不正确!');
             return false;
         }
         //费率、人工、材料、机械,须数字
         if(this.isDef(data.feeRate) && isNaN(data.feeRate)){
+            alert('费率须为数字!');
             return false;
         }
         if(this.isDef(data.labour) && isNaN(data.labour)){
+            alert('人工须为数字!');
             return false;
         }
         if(this.isDef(data.material) && isNaN(data.material)){
+            alert('材料须为数字!');
             return false;
         }
         if(this.isDef(data.machine) && isNaN(data.machine)){
+            alert('机械须为数字!');
             return false;
         }
         //基数为分别按人材机时,费率须为空
         if(this.isDef(data.base) && data.base === this.base.RCJ && this.isDef(data.feeRate) && data.feeRate !== ''){
+            alert("基数为分别按人材机时,费率须为空!");
             return false;
         }
         //基数为 人工、材料、机械时 三者之和须为100
         if(this.isDef(data.base) && data.base !== this.base.RCJ && this.validRCJ(data)){
+            alert("基数为 人工、材料、机械时 三者之和须为100");
             return false;
         }
         return true;
@@ -991,12 +1001,10 @@ let feeRuleObj = {
                 if(me.validPasteData(tempObj)){
                     me.decimalPasteData(tempObj);
                     //front
-                    feeRule = tempObj;
+                    me.cache[row] = tempObj;
                     me.toUpdate = true;
                 }
-            }
-            //insert
-            else{
+            } else{//  //insert
                 if(me.validPasteData(items[i])){
                     me.decimalPasteData(items[i]);
                     items[i].ID = uuid.v1();

+ 2 - 2
web/maintain/ration_repository/js/main.js

@@ -22,7 +22,7 @@ $(function () {
             alert('名称不可为空!');
             $('#libNameTxt').val('')
         } else if (!libCode) {
-            alert('定额编号不可为空');
+            alert('定额库编码不可为空');
             $('#libCode').val('');
         } else if(allNames.indexOf(libName) !== -1){
             alert('此定额库已存在!');
@@ -64,7 +64,7 @@ $(function () {
             alert("名称不可为空!");
             $("#renameText").val('');
         } else if (!newLibCode) {
-            alert('定额编号不可为空!');
+            alert('定额库编码不可为空!');
             $('#renameCode').val('');
         } else if(filterName.length > 0 && newName !== orgName){
             alert("该定额库已存在!");

+ 6 - 5
web/maintain/ration_repository/main.html

@@ -49,7 +49,7 @@
                   <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                       <table class="table table-hover table-bordered">
-                        <thead><tr><th>定额库名称</th><th>定额编号</th><th width="160">费用定额</th><th width="160">添加时间</th><th width="90">操作</th><th width="90">原始数据</th><th width="150">内部数据</th><th width="90">补充模板</th></tr></thead>
+                        <thead><tr><th>定额库名称</th><th>定额库编码</th><th width="160">费用定额</th><th width="160">添加时间</th><th width="90">操作</th><th width="90">原始数据</th><th width="150">内部数据</th><th width="90">补充模板</th></tr></thead>
                         <tbody id="showArea">
                         <% for(let lib of rationLibs){ %>
                         <tr id="<%= lib.ID %>">
@@ -60,6 +60,7 @@
                             <td>
                                 <a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a>
                                 <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a>
+                                <a href="javascript:void(0);" data-toggle="modal" data-target="#reCalcAll" title="全部计算"><i class="fa fa-calculator"></i></a>
                             </td>
                             <td>
                                 <a class="btn btn-secondary btn-sm import-source" href="javacript:void(0);" data-id="<%= lib.ID %>" title="导入原始数据"><i class="fa fa-sign-in fa-rotate-90"></i>导入</a>
@@ -122,8 +123,8 @@
                             <input id="libNameTxt" class="form-control" placeholder="输入定额库名称" type="text">
                         </div>
                         <div class="form-group">
-                            <label>定额编号</label>
-                            <input id="libCode" class="form-control" placeholder="输入定额编号" type="text">
+                            <label>定额库编码</label>
+                            <input id="libCode" class="form-control" placeholder="输入定额库编码" type="text">
                         </div>
                         <div class="form-group">
                             <label>费用定额名称</label>
@@ -159,8 +160,8 @@
                       <input class="form-control" id="renameText" placeholder="输入定额库名称" type="text" value="">
                     </div>
                       <div class="form-group">
-                          <label>定额编号</label>
-                          <input class="form-control" id="renameCode" placeholder="输入定额编号" type="text" value="">
+                          <label>定额库编码</label>
+                          <input class="form-control" id="renameCode" placeholder="输入定额库编码" type="text" value="">
                       </div>
                   </form>
                 </div>

+ 2 - 1
web/maintain/report/js/rpt_tpl_pre_handle.js

@@ -19,7 +19,8 @@ const fixed_material_types = [
     {Name: "钢筋(2)", Title: "", Value: 2},
     {Name: "木材(3)", Title: "", Value: 3},
     {Name: "水泥(4)", Title: "", Value: 4},
-    {Name: "标准砖(5)", Title: "", Value: 5}
+    {Name: "商品砼(5)", Title: "", Value: 5},
+    {Name: "商品砂浆(6)", Title: "", Value: 6}
 ];
 const fixed_glj_types = [
     {Name: "人工(1)", Title: "", Value: 1},

+ 13 - 8
web/maintain/std_glj_lib/js/glj.js

@@ -36,6 +36,10 @@ $(document).ready(function () {
     rightElesObj.left = $('#midContent');
     rightElesObj.right = $('#rightContent');
     SlideResize.horizontalSlide(rightElesObj, {min: 200, max: `$('#dataRow').width() - $('#leftContent').width() - 200`}, function () {
+        let resizeRate = 500 / $('#midContent').width(),
+            sheetRate = 100 - resizeRate;
+        $('#leftResize').css('width', `${resizeRate}%`);
+        $('#GLJListSheet').css('width', `${sheetRate}%`);
        refreshALlWorkBook();
     });
 });
@@ -85,10 +89,9 @@ let repositoryGljObj = {
     currentCache: null,
     parentNodeIds: {},
     gljList: [],
-    //materialType: ['钢材', '木材', '水泥', '钢筋', '标准砖'],//三材类型:钢材1、钢筋101、木材2、水泥3、标准砖4
-    materialType: {textArr: ['钢材', '钢筋', '木材', '水泥', '标准砖'], comboItems: [{text: '钢材', value: 1}, {text: '钢筋', value: 2},{text: '木材', value: 3},//三材类型:钢材1、钢筋101、木材2、水泥3、标准砖4
-         {text: '水泥', value: 4}, {text: '标准砖', value: 5}]},
-    materialTypeIdx: {'1': '钢材', '2': '钢筋', '3': '木材', '4': '水泥', '5': '标准砖'},
+    materialType: {textArr: ['钢材', '钢筋', '木材', '水泥', '商品砼','商品砂浆'], comboItems: [{text: '钢材', value: 1}, {text: '钢筋', value: 2},{text: '木材', value: 3},//三材类型:钢材1、钢筋2、木材3、水泥4、商品砼5、商品砂浆6
+         {text: '水泥', value: 4}, {text: '商品砼', value: 5},{text: '商品砂浆', value: 6}]},
+    materialTypeIdx: {'1': '钢材', '2': '钢筋', '3': '木材', '4': '水泥', '5': '商品砼', '6': '商品砂浆'},
     machineModel: {textArr: ['特', '大', '中', '小'], comboItems: [{text: '特', value: 1}, {text: '大', value: 2},{text: '中', value: 3}, {text: '小', value: 4}]},
     machineModelIdx: {'1': '特', '2': '大', '3': '中', '4': '小'},
     distTypeTree: null,//add
@@ -246,7 +249,7 @@ let repositoryGljObj = {
     //工料机价格是否相同
     priceIsEqual: function (gljA, gljB) {
         if(!priceProperties || priceProperties.length === 0){
-            return gljA.basePrice === gljB.basePrice;
+            return gljA.basePrice == gljB.basePrice;
         }
         return _.isEqual(gljA.priceProperty, gljB.priceProperty);
     },
@@ -745,6 +748,7 @@ let repositoryGljObj = {
         return objA[me.colMapping.colToField[col]] !== objB[[me.colMapping.colToField[col]]];
     },
     onCellEditEnd: function(sender, args) {
+        debugger;
         let me = repositoryGljObj, that = gljComponentOprObj,
             updateArr = [], addArr = [], updateBasePrcArr = [];
         let deESCFields = ['code', 'name', 'specs'];//消除转义字符
@@ -859,7 +863,6 @@ let repositoryGljObj = {
                 }
             }
             if(!me.priceIsEqual(rObj, me.currentEditingGlj)){
-                console.log('df');
                 //update basePrice of ration when editting basePrice of glj
                 let gljType = -1;
                 let gljTypeParent = me.distTypeTree.distTypes[me.distTypeTree.prefix + me.currentEditingGlj.gljType].parent;
@@ -1503,15 +1506,17 @@ let repositoryGljObj = {
     updateRationBasePrcRq: function (basePrcArr, workBook, callback) {
         let me = this;
         me.prevent = true;
+        me.calcRation = true;
         if (!$.bootstrapLoading.isLoading()) {
             $.bootstrapLoading.start();
         }
         $.ajax({
             type: 'post',
             url: 'api/updateRationBasePrc',
-            data:{basePrcArr: JSON.stringify(basePrcArr)},
+            data:{basePrcArr: JSON.stringify(basePrcArr), repId: pageOprObj.gljLibId},
             dataType: 'json',
             success: function (result) {
+                me.calcRation = false;
                 if(result.error){
                     alert("计算定额基价失败");
                 }
@@ -1566,7 +1571,7 @@ let repositoryGljObj = {
                     sheetCommonObj.cleanData(gljComponentOprObj.workBook.getSheet(0), gljComponentOprObj.setting, -1);
                     sheetsOprObj.showData(gljComponentOprObj, gljComponentOprObj.workBook.getSheet(0), gljComponentOprObj.setting, me.currentComponent);
                 }
-                if ($.bootstrapLoading.isLoading()) {
+                if (!me.calcRation && $.bootstrapLoading.isLoading()) {
                     $.bootstrapLoading.end();
                 }
             },

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

@@ -2,9 +2,9 @@
  * Created by Zhong on 2018/8/14.
  */
 //允许使用的工料机类型:人工、普通材料、混凝土、砂浆、配合比、商品混凝土、商品砂浆、其他材料费、机械台班、机上人工、机械组成物、仪器仪表、燃料动力费、折旧费、
-// 检修费、维护费、安拆费及场外运费、校验费、其他费用、其他施工机具使用费、主材、企业管理费、利润、一般风险费
+// 检修费、维护费、安拆费及场外运费、校验费、其他费用、其他施工机具使用费、主材、设备、企业管理费、利润、一般风险费
 if(typeof allowGljType !== 'undefined'){
-    allowGljType = [1, 201, 202, 203, 204, 205, 206, 207, 301, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 4, 6, 7, 8];
+    allowGljType = [1, 201, 202, 203, 204, 205, 206, 207, 301, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 4,5, 6, 7, 8];
 }
 if(typeof allowComponent !== 'undefined'){
     //允许含有组成物的工料机类型:混凝土、砂浆、配合比、机械台班、仪器仪表、主材

+ 154 - 0
web/over_write/js/neimenggu_2017.js

@@ -0,0 +1,154 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/4/17
+ * @version
+ */
+
+//允许使用的工料机类型:人工、普通材料、混凝土、砂浆、配合比、商品混凝土、商品砂浆、机械台班、机械组成物、机上人工、主材、设备、企业管理费、利润
+if(typeof allowGljType !== 'undefined'){
+    allowGljType = [1, 201, 202, 203, 204, 205, 206, 301, 302, 303, 4, 5, 6, 7];
+}
+if(typeof allowComponent !== 'undefined'){
+    //允许含有组成物的工料机类型:混凝土、砂浆、配合比、机械台班、主材
+    allowComponent = [202, 203, 204, 301, 4];
+}
+if(typeof componentType !== 'undefined'){
+    //可以作为组成物的工料机类型:普通材料、机械组成物、机上人工、主材
+    componentType = [201, 302, 303, 4];
+}
+if(typeof machineAllowComponent !== 'undefined'){
+    //允许含有组成物的机械工料机类型:机械台班
+    machineAllowComponent = [301];
+}
+if(typeof machineComponent !== 'undefined'){
+    //可以作为机械工料机组成物的工料机类型:机械组成物、机上人工
+    machineComponent = [302, 303];
+}
+if(typeof materialAllowComponent !== 'undefined'){
+    //允许含有组成物的材料工料机类型:混凝土、砂浆、配合比
+    materialAllowComponent = [202, 203, 204];
+}
+if(typeof materialComponent !== 'undefined'){
+    //可以作为材料工料机组成物的工料机类型:普通材料
+    materialComponent = [201];
+}
+//覆盖前端基价计算
+//基价=人工费+材料费+机械费+管理费利润
+//管理费利润=Round(人工费*(管理费消耗量+利润消耗量)%,2) 注:书中管理费、利润的单位都是“%”
+if (typeof rationGLJOprObj !== 'undefined' && typeof rationGLJOprObj.rationCal !== 'undefined') {
+    rationGLJOprObj.rationCal = function () {
+        let me = rationGLJOprObj;
+        let price = {gljType1: [], gljType2: [], gljType3: []},
+            rst = {labourPrice: 0, materialPrice: 0, machinePrice: 0},
+            rationBasePrc = 0;
+        let manageProfitConsume = 0;   //管理费、利润消耗量
+        if(me.currentRationItem && me.cache['_GLJ_' + me.currentRationItem.ID]){
+            let cacheArr = me.cache['_GLJ_' + me.currentRationItem.ID];
+            cacheArr.forEach(function (gljData) {
+                if(gljData.gljType && gljData.basePrice && gljData.consumeAmt){
+                    let parent = me.distTypeTree.distTypes[me.distTypeTree.prefix + gljData.gljType].parent;
+                    if(parent && parent.data.ID <= 3){
+                        price['gljType' + parent.data.ID].push(scMathUtil.roundTo(gljData.basePrice * gljData.consumeAmt, -3));//取三位
+                    }
+                    if(!parent && gljData.gljType <= 3){
+                        price['gljType' + gljData.gljType].push(scMathUtil.roundTo(gljData.basePrice * gljData.consumeAmt, -3));//取三位
+                    }
+                    if([6, 7].includes(gljData.gljType)){
+                        manageProfitConsume = scMathUtil.roundTo(manageProfitConsume + gljData.consumeAmt, -6);
+                    }
+                }
+            });
+            if(price.gljType1.length > 0){
+                let labourPrice = 0;
+                price.gljType1.forEach(function (singlePrc) {
+                    labourPrice = scMathUtil.roundTo(labourPrice + singlePrc, me.processDecimal);
+                });
+                let roundPrice = scMathUtil.roundTo(labourPrice, -2);
+                rst.labourPrice = roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
+                //管理费利润
+                let manageProfitPrc = scMathUtil.roundTo(roundPrice * manageProfitConsume * 0.01, -2);
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + manageProfitPrc, -2);
+            }
+            if(price.gljType2.length > 0){
+                let materialPrice = 0;
+                price.gljType2.forEach(function (singlePrc) {
+                    materialPrice = scMathUtil.roundTo(materialPrice + singlePrc, me.processDecimal);
+                });
+                let roundPrice = scMathUtil.roundTo(materialPrice, -2);
+                rst.materialPrice = roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
+            }
+            if(price.gljType3.length > 0){
+                let machinePrice = 0;
+                price.gljType3.forEach(function (singlePrc) {
+                    machinePrice = scMathUtil.roundTo(machinePrice + singlePrc, me.processDecimal);
+                });
+                let roundPrice = scMathUtil.roundTo(machinePrice, -2);
+                rst.machinePrice = roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
+            }
+            rst.rationBasePrc = rationBasePrc;
+        }
+        return rst;
+    }
+}
+
+if (typeof module !== 'undefined') {
+    module.exports = {
+        calcRation: function (gljArr, scMathUtil) {
+            let labourPrc = [],
+                materialPrc = [],
+                machinePrc = [],
+                manageProfitConsume = 0,
+                singlePrc,
+                updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, manageProfitPrice: 0, basePrice: 0};
+            gljArr.forEach(function (gljItem) {
+                if(gljItem.gljParentType !== -1){
+                    singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
+                    if(gljItem.gljParentType === 1){
+                        labourPrc.push(singlePrc);
+                    } else if(gljItem.gljParentType ===2){
+                        materialPrc.push(singlePrc);
+                    } else if(gljItem.gljParentType === 3){
+                        machinePrc.push(singlePrc);
+                    } else if(gljItem.gljParentType === 6){
+                        manageProfitConsume = scMathUtil.roundTo(manageProfitConsume + gljItem.consumeAmt, -6);
+                    } else if(gljItem.gljParentType === 7){
+                        manageProfitConsume = scMathUtil.roundTo(manageProfitConsume + gljItem.consumeAmt, -6);
+                    }
+                }
+            });
+            if(labourPrc.length > 0){
+                let sumLaP = 0;
+                for(let i=0; i<labourPrc.length; i++){
+                    sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], -6);
+                }
+                updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
+                updatePrc.manageProfitPrice = scMathUtil.roundTo(updatePrc.labourPrice * manageProfitConsume * 0.01, -2);
+                updatePrc.basePrice = scMathUtil.roundTo(updatePrc.labourPrice + updatePrc.manageProfitPrice, -2);
+            }
+            if(materialPrc.length > 0){
+                let sumMtP = 0;
+                for(let i= 0; i<materialPrc.length; i++){
+                    sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], -6);
+                }
+                updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
+                updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.materialPrice, -2);
+            }
+            if(machinePrc.length > 0){
+                let sumMaP = 0;
+                for(let i =0; i< machinePrc.length; i++){
+                    sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], -6);
+                }
+                updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
+                updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.machinePrice, -2);
+            }
+            return updatePrc;
+        }
+    };
+}

+ 10 - 4
web/users/js/compilation.js

@@ -747,10 +747,12 @@ function switchChange(element) {
     return !currentStatus;
 }
 
-function editEngineer(selector) {
-    let engineerName =  $(selector).prev("span").text();
+function editEngineer(selector,key) {
+    let editText =  $(selector).prev("span").text();
     let parentDiv = $(selector).parent("div");
-    parentDiv.next("div").find("input").val(engineerName);
+    let width =  key == 'seq'?70:200;
+    parentDiv.next("div").css('width',width);
+    parentDiv.next("div").find("input").val(editText);
     parentDiv.hide();
     parentDiv.next("div").show();
 }
@@ -769,7 +771,11 @@ function confirmUpdate(selector,engineerID) {
      let updateData = {};
      updateData[key] = newValue;
      updateEngineer(engineerID,updateData,function () {
-        inputDiv.prev("div").find("span").text(newValue);
+         if(key == 'seq'){
+             window.location.reload();
+         } else {
+             inputDiv.prev("div").find("span").text(newValue);
+         }
      });
      inputDiv.prev("div").show();
      inputDiv.hide();

+ 14 - 0
web/users/js/user.js

@@ -43,6 +43,20 @@ $(document).ready(function() {
 });
 let cacheUser = null;
 
+async function getOnlineInfo(filter) {
+    try {
+        let htmlString = `<tbody><tr><th>日期/时间</th><th>在线时长</th></tr>`;
+        let info = await ajaxPost("/user/getOnlineInfo",JSON.parse(filter));
+        for(let i of info){
+            htmlString += `<tr><td>${i.dateString}</td><td>${i.online_times}</td></tr>`
+        }
+        htmlString +="<tbody>";
+        $("#time-detail-table").html(htmlString);
+    }catch (e){
+        console.log(e)
+    }
+}
+
 async function getUserInfo(ID) {
     let user = await ajaxPost("/user/findByID",{ID:ID});
     let infoString = `<tr><th>注册时间</th><td>${user.create_time}</td><th>最近登录</th><td>${user.last_login}</td></tr>

+ 11 - 0
web/users/views/compilation/add.html

@@ -34,6 +34,7 @@
                         <table class="table engineer_table">
                             <thead>
                             <tr>
+                                <th>序号</th>
                                 <th>工程专业</th>
                                 <th>费用标准</th>
                                 <th>定额取费专业</th>
@@ -49,6 +50,16 @@
                                 <% engineeringList.forEach(function(engineering) {%>
                                 <tr >
                                     <td>
+                                        <div><span><%= engineering.seq %></span> <a onclick='editEngineer(this,"seq")'><i class="glyphicon glyphicon-pencil"></i></a></div>
+                                        <div class="input-group input-group-sm input_group_div" style="width:200px;display: none">
+                                            <input class="form-control" name="seq">
+                                            <div class="input-group-btn">
+                                                <button type="button" class="btn btn-success" onclick='confirmUpdate(this,"<%= engineering._id.toString()%>")'>
+                                                    <span class="glyphicon glyphicon-ok"></span></button>
+                                            </div>
+                                        </div>
+                                    </td>
+                                    <td>
                                         <div><span><%= engineering.name %></span> <a onclick='editEngineer(this)'><i class="glyphicon glyphicon-pencil"></i></a></div>
                                         <div class="input-group input-group-sm input_group_div" style="width:200px;display: none">
                                             <input class="form-control" name="name">

+ 26 - 0
web/users/views/user/index.html

@@ -98,6 +98,7 @@
                     <th>企业名称</th>
                     <th>企业地区</th>
                     <th>最近使用版本 </th>
+                    <th>在线时长(<%= filter.loginMsg === undefined ? '所有' : filter.loginMsg %>)</th>
                     <th width="180">注册时间 / 最近登录</th>
                     <% if (manager.superAdmin == 1) { %>
                     <th>操作</th>
@@ -113,6 +114,7 @@
                     <td><%= user.company %></td>
                     <td><%= model.province[user.province] %></td>
                     <td><%= compilationMap[user.latest_used]?compilationMap[user.latest_used].name:""%></td>
+                    <td><a onclick="getOnlineInfo('<%= user._doc.filter%>')" href="#time-detail" data-toggle="modal" data-target="#time-detail"><%= user._doc.online_times %></a></td>
                     <td><%= moment(user.create_time).format('YYYY-MM-DD HH:mm:ss') %><br><%= user.latest_login?moment(user.latest_login).format('YYYY-MM-DD HH:mm:ss'):"" %></td>
                     <% if (manager.superAdmin == 1) { %>
                     <td><a onclick='deleteUser("<%= user._id.toString()%>")' data-toggle="modal" data-target="#delUser" class="btn btn-link btn-sm" style="padding: 0px">删除</a></td>
@@ -196,6 +198,30 @@
     </div>
 </div>
 
+<!-- 弹窗在线时长-->
+<div class="modal fade" id="time-detail" tabindex="-1" role="dialog">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                <h4 class="modal-title" >在线时长详情</h4>
+            </div>
+            <div class="modal-body">
+                <table class="table table-bordered" id = 'time-detail-table'>
+                    <tr><th>日期/时间</th><th>在线时长</th></tr>
+                    <!--<tr><th>日期/时间</th><th>在线时长</th></tr>
+                    <tr><td>04-10</td><td>2小时10分钟</td></tr>
+                    <tr><td>04-09</td><td>1小时7分钟</td></tr>
+                    <tr><td>04-08</td><td>2小时35分钟</td></tr>-->
+                </table>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+
 <script type="text/javascript">
     let compilationList = JSON.parse('<%- compilationString %>');
     let adminName = '<%- adminName %>';