zhangweicheng 6 лет назад
Родитель
Сommit
05d8345e57

+ 1 - 0
config/gulpConfig.js

@@ -149,6 +149,7 @@ module.exports = {
         'web/building_saas/main/js/views/zlfb_view.js',
         'web/building_saas/main/js/views/installation_fee_view.js',
         'web/building_saas/main/js/views/material_adjust_view.js',
+        'web/building_saas/main/js/views/config_material_view.js',
         'web/building_saas/main/js/views/index_view.js',
         'web/building_saas/main/js/views/project_glj_view.js',
         'web/building_saas/main/js/views/importBills.js',

+ 5 - 1
modules/all_models/evaluate_list.js

@@ -8,15 +8,19 @@ import mongoose from "mongoose";
 
 let Schema = mongoose.Schema;
 let evaluateSchema = {
-    ID:String,
+    ID:{type:String,  index: true},
     projectID: {type:Number,index: true},
+    is_related:{type: Number, default: 0},//关联,1关,0不关
     projectGLJID:Number,//关联工料机ID
     seq:String,//序号
     code:String,
     name:String,
     specs:String,
     unit:String,
+    type:Number,
     market_price:String,
+    quantity:String,
+    base_price:String,
     locked:{type: Number, default: 0},//锁定,1锁,0不锁
     remark:String,
     originPlace:String,//产地

+ 1 - 1
modules/all_models/unit_price.js

@@ -11,7 +11,7 @@ let Schema = mongoose.Schema;
 let collectionName = 'unit_price';
 let modelSchema = {
     // 自增ID
-    id: {type:Number,unique: true},
+    id: {type:Number,unique: true, index: true},
     // 基价单价
     base_price: String,
     // 市场单价

+ 13 - 0
modules/glj/controllers/glj_controller.js

@@ -699,6 +699,19 @@ class GLJController extends BaseController {
         res.json(result);
     }
 
+    async updateEvaluateMaterial(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.updateEvaluateMaterial(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
     async modifyKeyValue(req,res){//修改工料机关键的属性:名称、类型、规格、型号等
         let result={
             error:0

+ 33 - 2
modules/glj/facade/glj_facade.js

@@ -2,12 +2,17 @@
  * Created by zhang on 2019/1/2.
  */
 module.exports={ //先导出后require可以解决循环引用问题
-    changeUnitFile:changeUnitFile
+    changeUnitFile:changeUnitFile,
+    updateEvaluateMaterial:updateEvaluateMaterial
 };
 
+const mongoose = require('mongoose');
 const ProjectModel = require('../../pm/models/project_model').project;
 import UnitPriceFileModel from "../models/unit_price_file_model";
 import UnitPriceModel from "../models/unit_price_model";
+let evaluateListModel = mongoose.model("evaluate_list");
+let projectGLJModel = mongoose.model("glj_list");
+let unitFileMode = mongoose.model("unit_price");
 
 async function changeUnitFile(projectData,unitFile,type,userID) {
     let projectId = projectData.projectID;
@@ -77,4 +82,30 @@ async function changeUnitFile(projectData,unitFile,type,userID) {
             throw '切换单价文件失败!';
         }
         return changeUnitPriceFileInfo;
-}
+}
+
+
+async function updateEvaluateMaterial(data) {
+    let modelMap = {
+        "glj_list":projectGLJModel,
+        "evaluate_list":evaluateListModel,
+        "unit_price":unitFileMode
+    };
+    for(let t of data.tasks){
+        let model = modelMap[t.type];
+        switch (t.action) {
+            case "update":
+                let query = {};
+                if(t.hasOwnProperty('ID')) query['ID'] = t.ID;
+                if(t.hasOwnProperty('id')) query['id'] = t.id;
+                await model.update(query,t.doc);
+                break;
+            case "add":
+                await model.create(t.doc);
+                break;
+            case "delete":
+                await model.deleteOne({ID:t.ID});
+                break;
+        }
+    }
+}

+ 2 - 2
modules/glj/models/unit_price_file_model.js

@@ -33,8 +33,8 @@ class UnitPriceFileModel extends BaseModel {
         switch (scene) {
             // 新增数据的验证规则
             case 'add':
-                this.model.schema.path('name').required(true);
-                this.model.schema.path('project_id').required(true);
+               /* this.model.schema.path('name').required(true);
+                this.model.schema.path('project_id').required(true);*/
                 break;
         }
     }

+ 4 - 0
modules/glj/routes/glj_router.js

@@ -28,6 +28,10 @@ router.post('/batchUpdatePrices', gljController.init, gljController.batchUpdateP
 router.post('/batchUpdateGLJProperty', gljController.init, gljController.batchUpdateGLJProperty);
 router.post('/batchUpdateConsumption', gljController.init, gljController.batchUpdateConsumption);
 router.post('/modifyKeyValue',gljController.init, gljController.modifyKeyValue);
+router.post('/updateEvaluateMaterial', gljController.updateEvaluateMaterial);
+
+
+
 
 router.get('/test', gljController.init, gljController.test);
 router.get('/testModify', gljController.init, gljController.testModify);

+ 24 - 0
modules/main/facade/evaluate_facade.js

@@ -0,0 +1,24 @@
+/**
+ * Created by zhang on 2019/9/11.
+ */
+
+
+module.exports={
+    getData:getData
+};
+
+const mongoose = require('mongoose');
+let evaluateListModel = mongoose.model("evaluate_list");
+let consts = require('../../main/models/project_consts');
+
+
+
+function getData(projectID, callback) {
+    evaluateListModel.find({'projectID': projectID}).lean().exec((err, datas) => {
+        if (err) {
+            callback(1, '', null);
+        } else {
+            callback(0, consts.projectConst.EVALUATE_LIST, datas);
+        }
+    })
+}

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

@@ -17,6 +17,7 @@ var labour_coe_facade = require('../facade/labour_coe_facade');
 var calc_program_facade = require('../facade/calc_program_facade');
 import GLJController from "../../glj/controllers/glj_controller";
 let installation_facade = require('../facade/installation_facade');
+let evaluate_facade = require('../facade/evaluate_facade');
 let pmController = require('../../pm/controllers/pm_controller');
 
 
@@ -45,6 +46,7 @@ moduleMap[projectConsts.PROJECTGLJ] = new GLJController();
 moduleMap[projectConsts.INSTALLATION_FEE] = installation_facade;
 moduleMap[projectConsts.RATION_TEMPLATE] = ration_template;
 moduleMap[projectConsts.PROJECT_INFO] = pmController;
+moduleMap[projectConsts.EVALUATE_LIST] = evaluate_facade;
 
 var Project = function (){};
 

+ 2 - 1
modules/main/models/project_consts.js

@@ -21,7 +21,8 @@ let projectConst = {
     LABOUR_COE:'labour_coe',
     CALC_PROGRAM:'calc_program',
     INSTALLATION_FEE:'installation_fee',
-    PROJECT_INFO: 'project_info'
+    PROJECT_INFO: 'project_info',
+    EVALUATE_LIST:'evaluate_list'
 };
 
 let projectConstList = [

+ 34 - 4
modules/pm/facade/pm_facade.js

@@ -72,7 +72,7 @@ let productModel = mongoose.model('product');
 let stdRationItemModel = mongoose.model('std_ration_lib_ration_items');
 let stdGljItemModel = mongoose.model('std_glj_lib_gljList');
 import BillsTemplateModel from "../models/templates/bills_template_model";
-
+let evaluateListModel = mongoose.model("evaluate_list");
 let featureLibModel =  mongoose.model("std_project_feature_lib");
 let scMathUtil = require('../../../public/scMathUtil').getUtil();
 let counter = require('../../../public/counter/counter');
@@ -243,7 +243,8 @@ async function copyProject(userID, compilationID,data,newProjectID = null) {
         copyRationSubList(originalID,newProjectID,billMap.uuidMaping,rationMap.uuidMaping,projectGLJMap.IDMap,rationCoeModel),
         copyRationSubList(originalID,newProjectID,billMap.uuidMaping,rationMap.uuidMaping,projectGLJMap.IDMap,quantityDetailModel),
         copyRationSubList(originalID,newProjectID,billMap.uuidMaping,rationMap.uuidMaping,projectGLJMap.IDMap,rationInstallationModel),
-        copyRationSubList(originalID,newProjectID,billMap.uuidMaping,rationMap.uuidMaping,projectGLJMap.IDMap,rationTemplateModel)
+        copyRationSubList(originalID,newProjectID,billMap.uuidMaping,rationMap.uuidMaping,projectGLJMap.IDMap,rationTemplateModel),
+        copyMaterialList(originalID,newProjectID,projectGLJMap.IDMap,evaluateListModel)
     ];
     if(originalProperty.calcProgramFile){
         copyTasks.push(commonCopy(newProjectID,originalProperty.calcProgramFile.ID,calcProgramFileID,calcProgramsModel));
@@ -466,6 +467,25 @@ async function copyRationSubList(originalPID,newProjectID,billIDMap,rationIDMap,
     await insertMany(newList,model);
 }
 
+
+async function copyMaterialList(originalPID,newProjectID,projectGLJIDMap,model) {//暂估材料等信息
+    let materialList = await model.find({projectID:originalPID}, '-_id').lean();
+    let newList = [];
+    for(let m of materialList){
+        newList.push(getNewMaterial(m,newProjectID,projectGLJIDMap))
+    }
+    await insertMany(newList,model);
+
+}
+
+function getNewMaterial(m,newProjectID,projectGLJIDMap) {
+    m.ID = uuidV1();
+    m.projectID = newProjectID;
+    if(projectGLJIDMap[m.projectGLJID]) m.projectGLJID = projectGLJIDMap[m.projectGLJID];
+    return m;
+}
+
+
 function getCopyRationSubData(doc,newProjectID,billIDMap,rationIDMap,projectGLJIDMap){
     doc.ID = uuidV1();
     doc.projectID = newProjectID;
@@ -1654,6 +1674,7 @@ async function exportTenderData(data){
     result.rationTemplates = await rationTemplateModel.find({projectID:data.projectID});
     result.calcProgramsFile = await calcProgramsModel.findOne({projectID:data.projectID});
     result.labourCoes = await labourCoesModel.findOne({projectID:data.projectID});
+    result.evaluateList = await evaluateListModel.find({projectID:data.projectID}, '-_id').lean();
 
     return cipher.aesEncrypt(JSON.stringify(result));
 }
@@ -1685,7 +1706,7 @@ async function importProjects(data,req,fields) {
 
 
 async function handleEachProject(data,projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap){
-    let bills = [],rations = [],projectGLJs = [],rationGLJs=[],rationCoes=[],quantityDetails=[],rationInstallations=[],rationTemplates=[];
+    let bills = [],rations = [],projectGLJs = [],rationGLJs=[],rationCoes=[],quantityDetails=[],rationInstallations=[],rationTemplates=[],evaluateList=[];
     let newProjectSetting =null,newCalcProgramsFile = null,newLabourCoe = null;
     let billsIDMap = {},projectGLJIDMap={},rationIDMap = {};
     let newProjectID = projectIDMap[data.projSetting.projectID];
@@ -1733,6 +1754,7 @@ async function handleEachProject(data,projectIDMap,labourCoeFileIDMap,calcProgra
     if(data.quantityDetails && data.quantityDetails.length > 0) quantityDetails = setRationSubList(data.quantityDetails,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
     if(data.rationInstallations && data.rationInstallations.length > 0) rationInstallations = setRationSubList(data.rationInstallations,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
     if(data.rationTemplates && data.rationTemplates.length > 0) rationTemplates = setRationSubList(data.rationTemplates,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+    if(data.evaluateList && data.evaluateList.length > 0) evaluateList = setMaterialList(data.evaluateList,newProjectID,projectGLJIDMap);
 
     //生成projectSetting 文件
     if(data.projSetting){
@@ -1765,12 +1787,19 @@ async function handleEachProject(data,projectIDMap,labourCoeFileIDMap,calcProgra
     if(quantityDetails.length > 0) await insertMany(quantityDetails,quantityDetailModel);
     if(rationInstallations.length > 0) await insertMany(rationInstallations,rationInstallationModel);
     if(rationTemplates.length > 0) await insertMany(rationTemplates,rationTemplateModel);
+    if(evaluateList.length > 0) await insertMany(evaluateList,evaluateListModel);
     if(newCalcProgramsFile) await calcProgramsModel.create(newCalcProgramsFile);
     if(newLabourCoe) await labourCoesModel.create(newLabourCoe);
 
 
 }
-
+function setMaterialList(datas,newProjectID,projectGLJIDMap){
+    let arrs = [];
+    for(let d of datas){
+       arrs.push(getNewMaterial(d,newProjectID,projectGLJIDMap))
+    }
+    return arrs
+}
 
 function setRationSubList(datas,newProjectID,billIDMap,rationIDMap,projectGLJIDMap) {
     let arrs = [];
@@ -1786,6 +1815,7 @@ async function handleMainProjectDatas(mainData,updateData,userID) {
     let mainProjectID = -1;
     let projectIDMap = {},feeRateFileIDMap={},unitPriceFileIDMap={},labourCoeFileIDMap={},calcProgramFileIDMap={};
     let tasks = [];
+    projectIDMap[-1] = -1;//最后一个项目的nextID为-1的情况
     //生成新的projectID
     for(let p of mainData.projects){
         let newProjectID = await getCounterID("projects");

+ 1 - 0
public/web/gljUtil.js

@@ -289,6 +289,7 @@ let gljUtil = {
     getIndex(obj, pops){
         let t_index = '';
         let k_arr = [];
+        if(!pops) pops = this.gljKeyArray;
         for (let p of pops) {
             let tmpK = (obj[p] == undefined || obj[p] == null || obj[p] == '') ? 'null' : obj[p];
             k_arr.push(tmpK);

+ 4 - 2
public/web/slideResize.js

@@ -167,7 +167,8 @@ const SlideResize = (function() {
                 //设置下部分div高度
                 eleObj.bottom.height(bottomChange);
                 //设置下部分div内spread高度
-                eleObj.bottomSpread.height(bottomChange - limit.notBottomSpread);
+                let notBottomHeight = limit.bottomNav?eval(limit.bottomNav):limit.notBottomSpread;
+                eleObj.bottomSpread.height(bottomChange - notBottomHeight);
                 mouseMoveCount += Math.abs(moveSize);
                 deBounce(function () {
                     if (callback) {
@@ -221,7 +222,8 @@ const SlideResize = (function() {
         eleObj.top.height(curTopHeight);
         eleObj.topSpread.height(curTopHeight - limit.notTopSpread);
         eleObj.bottom.height(curBottomHeight);
-        eleObj.bottomSpread.height(curBottomHeight - limit.notBottomSpread);
+        let notBottomHeight = limit.bottomNav?eval(limit.bottomNav):limit.notBottomSpread;
+        eleObj.bottomSpread.height(curBottomHeight - notBottomHeight);
         if (callback) {
             callback();
         }

+ 1 - 1
web/building_saas/css/custom.css

@@ -54,7 +54,7 @@ legend.legend{
     width: 110px;
 }
 .a_color{
-    color: #007bff;
+    color: #007bff
 }
 
 .filterType a{

+ 48 - 17
web/building_saas/css/main.css

@@ -176,6 +176,16 @@ a{
     background-color: #6c757d;
     color:#fff
 }
+.gl-side.gl-side-lg{
+    width:200px;
+}
+.nav-side .nav-link{
+    padding:.5rem;
+}
+.nav-side .nav-link.active{
+    background:#ddd;
+    color:#333;
+}
 .pm-side{
     position: fixed;
     left:0;
@@ -373,16 +383,6 @@ a{
         transform: translateX(10px);
     }
 }
-.gl-side.gl-side-lg{
-    width:200px;
-}
-.nav-side .nav-link{
-    padding:.5rem;
-}
-.nav-side .nav-link.active{
-    background:#ddd;
-    color:#333;
-}
 .gl-side{
     border-right:1px solid #ccc;
     width:120px
@@ -621,25 +621,56 @@ a{
 }
 /*书签颜色*/
 .annotate-color-1{
-    background: #E2F2C5
+    background: #E2F2C5;
+    color: #E2F2C5
+}
+.annotate-color-1::before{
+    color: #E2F2C5!important;
 }
 .annotate-color-2{
-    background: #F9E2CF
+    background: #F9E2CF;
+    color:#F9E2CF
+}
+.annotate-color-2::before{
+    color: #F9E2CF
 }
 .annotate-color-3{
-    background: #F2EFD9
+    background: #F2EFD9;
+    color:#F2EFD9
+}
+.annotate-color-3::before{
+    color:#F2EFD9
 }
 .annotate-color-4{
-    background: #F5D1DA
+    background: #F5D1DA;
+    color:#F5D1DA
+}
+.annotate-color-4::before{
+    color:#F5D1DA
 }
 .annotate-color-5{
-    background: #E3E3E3
+    background: #E3E3E3;
+    color:#E3E3E3
+}
+.annotate-color-5::before{
+    color:#E3E3E3
 }
 .annotate-color-6{
-    background: #B6F3F2
+    background: #B6F3F2;
+    color:#B6F3F2
+}
+.annotate-color-6::before{
+    color:#B6F3F2
 }
 .annotate-color-7{
-    background: #ECE0F5
+    background: #ECE0F5;
+    color:#ECE0F5
+}
+.annotate-color-7::before{
+    color:#ECE0F5
+}
+.input-group-text.active{
+    color:#666;
 }
 /*宽屏菜单*/
 @media screen and (min-width: 900px) {

+ 88 - 0
web/building_saas/glj/html/project_glj.html

@@ -38,6 +38,37 @@
             <div class="" id="material_adjust_sheet" style="overflow: hidden;width: 100%">
             </div>
         </div>
+        <div class="main-content col p-0" id="config_material" style="overflow: hidden; display: none"><!--暂估材料,主要材料等-->
+            <div class="top-content" id="configMaterialTop" style="overflow: hidden">
+                <div class="main-data-top" style="width: 100%; overflow: hidden" id="config_material_sheet">
+                </div>
+            </div>
+            <div class="resize-y" id="configMaterialResize"></div>
+            <div class="bottom-content" id="configMaterialBottom">
+                <ul class="nav nav-tabs" role="tablist">
+                      <li class="nav-item">
+                          <a class=" nav-link  active " data-toggle="tab" data-name="related_sheet" id="related_link" href="#related_div" role="tab">关联暂估材料</a>
+                      </li>
+                     <li class="nav-item">
+                         <a class=" nav-link " data-toggle="tab" data-name="detail_sheet" id="detail_link" href="#related_div" role="tab">关联暂估材料明细</a>
+                     </li>
+                </ul>
+                <!-- Tab panes -->
+                <div class="tab-content">
+                    <div class="tab-pane active" id="related_div" role="tabpanel">
+                        <div class="form-inline py-1 toolsbar_feeRate" id="filterToolDiv">
+                            <label class="mx-2" for="filterGljName">材料名称包括:</label>
+                            <input type="text" class="form-control form-control-sm" id="filterGljName">
+                            <button type="button" class="btn btn-outline-primary btn-sm" id = "filterAgain">重新过滤</button>
+                           <!-- <button type="button" class="btn btn-outline-primary btn-sm" id = "autoRelated">自动关联招标材料</button>-->
+                        </div>
+                        <div class="main-data-bottom" id="related_sheet" style="overflow:hidden">
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
         <div class="main-content col p-0" id="project-glj-main" style="overflow: hidden; ">
             <div class="top-content" id="projectGljTop" style="overflow: hidden">
                 <div class="main-data-top" style="width: 100%; overflow: hidden" id="project_glj_sheet">
@@ -172,6 +203,7 @@
         </div>
     </div>
 </div>
+
 <!--弹出 从人材机汇总中选择-->
 <div class="modal fade" id="selectFromGLJ" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">
@@ -234,4 +266,60 @@
             </div>
         </div>
     </div>
+</div>
+
+<!--暂估材料弹出 从人材机汇总中选择-->
+<div class="modal fade" id="selectPGLJ" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">从人材机汇总中选择</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body" style="padding: 0px">
+                <div class="btn-toolbar" style="margin: 10px">
+                    <div class="btn-group btn-group-sm mr-2">
+                        <button type="button" class="btn btn-outline-primary pglj_sel_check_btn">全选</button>
+                        <button type="button" class="btn btn-outline-primary pglj_sel_check_btn">全选主材</button>
+                        <button type="button" class="btn btn-outline-primary pglj_sel_check_btn">全选设备</button>
+                    </div>
+                    <!--前面3个按钮 有选中状态,出现 取消 按钮-->
+                    <button type="button" class="btn btn-outline-danger btn-sm mr-2 pglj_sel_check_btn">取消</button>
+                    <div class="input-group input-group-sm mr-2" style="width:200px">
+                        <input type="text" class="form-control form-control-sm"  placeholder="查找" id="pglj_sel_input" value="">
+                        <div class="input-group-append">
+                            <button class="btn btn-outline-primary btn-sm" id="pglj_sel_btn_find" type="button"><i class="fa fa-search" aria-hidden="true"></i></button>
+                        </div>
+                    </div>
+                    <div class="input-group input-group-sm">
+                        <div class="form-check form-check-inline">
+                            <input class="form-check-input pglj_sel_input" type="checkbox" id="pglj_sel_all" value="0">
+                            <label class="form-check-label" for="pglj_sel_all">所有</label>
+                        </div>
+                        <div class="form-check form-check-inline">
+                            <input class="form-check-input pglj_sel_input pglj_sel_input_other" type="checkbox" id="pglj_sel_material" checked value="2">
+                            <label class="form-check-label" for="pglj_sel_material">材</label>
+                        </div>
+                        <div class="form-check form-check-inline">
+                            <input class="form-check-input pglj_sel_input pglj_sel_input_other" type="checkbox" id="pglj_sel_main" checked value="4">
+                            <label class="form-check-label" for="pglj_sel_main">主材</label>
+                        </div>
+                        <div class="form-check form-check-inline">
+                            <input class="form-check-input pglj_sel_input pglj_sel_input_other" type="checkbox" id="pglj_sel_eqp" checked value="5">
+                            <label class="form-check-label" for="pglj_sel_eqp">设备</label>
+                        </div>
+                    </div>
+                </div>
+                <div class="modal-auto-height" style="margin-top:10px; border: 1px solid #ccc">
+                    <div  id="pglj_from_sheet" style="overflow: hidden;height: 100%"></div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" id="pglj_sel_confirm" data-dismiss="modal">确定</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
 </div>

+ 1 - 0
web/building_saas/js/global.js

@@ -35,6 +35,7 @@ function autoFlashHeight(){
     $('#comments').find('textarea').height($('#comments').height() - 25);
     typeof(adaptiveTzjnrWidth)== 'function' ?adaptiveTzjnrWidth():'';
     $('#project-glj-main').width($(window).width()-($('.main-nav').width()+ 2)-($('.filterType').width()+12)-5); //2、12是padding宽度,width 是不算padding宽度的
+    $('#config_material').width($(window).width()-($('.main-nav').width()+ 2)-($('.filterType').width()+12)-5); //2、12是padding宽度,width 是不算padding宽度的
     $('#material_adjust').width($(window).width()-($('.main-nav').width()+ 2)-($('.filterType').width()+12)-5);//材料调差
     $('#index_content').width($(window).width()-($('.main-nav').width()+ 2)-($('#index_nav').width()+12)-5);//材料调差
     //typeof zmhs_obj === 'object' ? zmhs_obj.loadSideResize() : '';

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

@@ -2306,6 +2306,7 @@
     <script type="text/javascript" src='/web/building_saas/main/js/views/zlfb_view.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/installation_fee_view.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/material_adjust_view.js'></script>
+    <script type="text/javascript" src='/web/building_saas/main/js/views/config_material_view.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/index_view.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/project_glj_view.js'></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/importBills.js"></script>

+ 2 - 1
web/building_saas/main/js/models/main_consts.js

@@ -17,7 +17,8 @@ const ModuleNames = {
     labour_coe: 'labour_coe',
     calc_program: 'calc_program',
     installation_fee:'installation_fee',
-    projectInfo: 'project_info'
+    projectInfo: 'project_info',
+    evaluate_list:'evaluate_list'
 };
 
 let gljType = gljUtil.gljType;

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

@@ -102,6 +102,7 @@ var PROJECT = {
             this.composition.loadData();
             this.labourCoe = new LabourCoe(this);
             this.calcProgram = new CalcProgram(this);
+            this.evaluate_list = new EvaluateList(this);
             this.calcBase = calcBase;
 
             // this.masterField = {ration: 'billsItemID', volumePrice: 'billsItemID'};

+ 14 - 1
web/building_saas/main/js/models/project_glj.js

@@ -12,6 +12,8 @@ function ProjectGLJ() {
     this.getRatioId = null;
 }
 
+
+
 /**
  * 加载数据
  *
@@ -898,4 +900,15 @@ ProjectGLJ.prototype.calcTenderQuantity  = function (){
     let rationDatas = projectObj.project.Ration.datas;
     let billsDatas = projectObj.project.Bills.datas;
     gljUtil.calcProjectGLJQuantity(this.datas,rationGLJDatas,rationDatas,billsDatas,getDecimal("glj.quantity"),_,scMathUtil,true);
-};
+};
+
+class EvaluateList {
+    constructor (project) {
+        this.project = project;
+        this.datas = [];
+        project.registerModule(ModuleNames.evaluate_list, this);
+    };
+    loadData (datas) {
+        this.datas = datas;
+    };
+}

+ 688 - 0
web/building_saas/main/js/views/config_material_view.js

@@ -0,0 +1,688 @@
+/**
+ * Created by zhang on 2019/9/10.
+ */
+let configMaterialObj = {
+    GLJIDMap:{},
+    relateFilterAgain:false,
+    configSpread:null,
+    relatedSpread:null,
+    evaluateMaterialDatas:[],
+    evaluateMaterialSetting:{
+        header: [
+            {headerName: "关联", headerWidth: 80, dataCode: "is_related", dataType: "String",cellType:'checkBox'},
+            {headerName: "编号", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "序号", headerWidth: 80, dataCode: "seq", dataType: "String"},
+            {headerName: "材料名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell'},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "数量", headerWidth: 90, dataCode: "quantity", hAlign: "right", dataType: "Number",validator:"number"},//decimalField:'glj.quantity'
+            {headerName: "暂定价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "合价", headerWidth: 90, dataCode: "totalPrice", hAlign: "right", dataType: "Number",validator:"number",decimalField:'bills.totalPrice'},
+            {headerName: "锁定", headerWidth: 80, dataCode: "locked", hAlign: "left", dataType: "String",cellType:'checkBox'},
+            {headerName: "产地", headerWidth: 80, dataCode: "originPlace", hAlign: "left", dataType: "String",visible:false},
+            {headerName: "厂家", headerWidth: 80, dataCode: "vender", hAlign: "left", dataType: "String",visible:false},
+            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
+        ],
+        view:{ lockColumns: ["is_related","unit","totalPrice","originPlace","vender"]}
+    },
+    evaluateRelateSetting:{
+        header: [
+            {headerName: "关联", headerWidth: 80, dataCode: "is_related", dataType: "String",cellType:'checkBox'},
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "类别", headerWidth: 45, dataCode: "short_name" ,hAlign: "center",dataType: "String"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell'},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "数量", headerWidth: 90, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
+            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "合价", headerWidth: 90, dataCode: "totalPrice", hAlign: "right", dataType: "Number",validator:"number",decimalField:'bills.totalPrice'},
+            {headerName: "供货方式", headerWidth: 70, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
+            {headerName: "产地", headerWidth: 80, dataCode: "originPlace", hAlign: "left", dataType: "String"},
+            {headerName: "厂家", headerWidth: 80, dataCode: "vender", hAlign: "left", dataType: "String"},
+            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
+        ],
+        view:{ lockColumns: ["code","type","name","specs","unit","quantity","marketPrice","basePrice","supply","originPlace","vender","remark"]}
+    },
+    initSpread:function(){
+        if(!this.configSpread){
+            this.configSpread = SheetDataHelper.createNewSpread($("#config_material_sheet")[0],2);
+            sheetCommonObj.spreadDefaultStyle(this.configSpread);
+            this.relatedSpread = SheetDataHelper.createNewSpread($("#related_sheet")[0],2);
+            sheetCommonObj.spreadDefaultStyle(this.relatedSpread);
+        }
+        this.initEvaluateMaterialSheet();
+        this.initEvaluateRelateSheet();
+        //打开别人分享的项目,只读
+        if(projectReadOnly){
+            disableSpread(this.configSpread);
+            disableSpread(this.relatedSpread);
+        }else {
+            this.initRightClick();
+        }
+    },
+    initEvaluateMaterialSheet:function(){
+        this.evaluateMaterialSheet = this.configSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.evaluateMaterialSheet,this.evaluateMaterialSetting,30);
+        this.evaluateMaterialSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onEvaluateMaterialValueChange);
+        this.evaluateMaterialSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onEvaluateMaterialSelectionChange);
+        this.evaluateMaterialSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onEvaluateMaterialEditStarting);
+        //this.evaluateMaterialSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onSheetRangeChange);
+        this.evaluateMaterialSheet.name('evaluateMaterialSheet');
+        this.evaluateMaterialSheet.setRowHeight(0, 36, 1);
+    },
+    initEvaluateRelateSheet:function () {
+        this.evaluateRelateSheet = this.relatedSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.evaluateRelateSheet,this.evaluateRelateSetting,30);
+        this.evaluateRelateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onEvaluateRelateValueChange);
+        this.evaluateRelateSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onEvaluateRelateEditStarting);
+        //this.evaluateRelateSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onSheetRangeChange);
+        this.evaluateRelateSheet.name('evaluateRelateSheet');
+        this.evaluateRelateSheet.setRowHeight(0, 36, 1);
+    },
+
+    showEvaluateMaterialDatas:function () {
+        this.configSpread.setActiveSheetIndex(0);
+        this.evaluateMaterialDatas = this.getEvaluateMaterialDatas();
+        sheetCommonObj.showData(this.evaluateMaterialSheet, this.evaluateMaterialSetting,this.evaluateMaterialDatas);
+        this.evaluateMaterialSheet.setRowCount(this.evaluateMaterialDatas.length);
+    },
+    showEvaluateRelateDatas:function () {
+        this.relatedSpread.setActiveSheetIndex(0);
+        this.evaluateRelateDatas = this.getEvaluateRelateDatas();
+        sheetCommonObj.showData(this.evaluateRelateSheet, this.evaluateRelateSetting,this.evaluateRelateDatas);
+        this.evaluateRelateSheet.setRowCount(this.evaluateRelateDatas.length);
+    },
+
+    refreshSheetDatas:function () {
+        this.showEvaluateMaterialDatas();
+        this.showEvaluateRelateDatas();
+    },
+    getEvaluateRelateDatas:function () {
+        //$('filterGljName')
+        let name = '';
+        let datas = [];
+        let sel = this.evaluateMaterialSheet.getSelections()[0];
+        let srow = sel.row == -1||sel.row == ""?0:sel.row;
+        if(this.evaluateMaterialDatas.length>srow){
+             name = this.relateFilterAgain== true? $('#filterGljName').val(): this.evaluateMaterialDatas[srow].name;
+            datas = this.filterEvaluateRelate(name,this.evaluateMaterialDatas[srow].projectGLJID);
+        }
+        if(this.relateFilterAgain== false) $('#filterGljName').val(name);
+        return datas;
+    },
+    filterEvaluateRelate:function (name,projectGLJID) {
+        let datas = [];
+        let projectGLJ =  projectObj.project.projectGLJ;
+        let materialIdList = projectGLJ.datas.constData.materialIdList;
+        for(let d of projectGLJ.datas.gljList){
+            if (materialIdList.indexOf(d.type) >= 0){//材料类型
+                if(name != ''){//name为''时不做过滤
+                    if(d.name.indexOf(name)==-1){
+                        if(!(d.is_evaluate == 1 && d.id == projectGLJID)) continue;//虽然不匹配,但是是关联的暂估材料,这时应该显示
+                    }
+                    if(d.is_evaluate == 1 && d.id != projectGLJID) continue;
+                }
+                let t = {
+                    id:d.id,
+                    code : d.code,
+                    type : d.type,
+                    short_name :projectGLJ.getShortNameByID(d.type),
+                    name : d.name,
+                    specs : d.specs,
+                    unit : d.unit,
+                    quantity : d.quantity,
+                    supply:d.supply,
+                    originPlace:d.originPlace,
+                    vender:d.vender,
+                    remark:d.remark,
+                    from:d
+                };
+                t.is_related = d.is_evaluate;
+                gljOprObj.setGLJPrice(t,d);
+                t.totalPrice = scMathUtil.roundForObj(t.quantity * t.marketPrice,getDecimal('bills.totalPrice'));
+                datas.push(t);
+            }
+        }
+        return _.sortByAll(datas,'code');
+    },
+    getEvaluateMaterialDatas:function () {
+        let datas = [];
+        let gljMap = _.indexBy(projectObj.project.projectGLJ.datas.gljList,'id');
+        for(let e of projectObj.project.evaluate_list.datas){
+            let t = {
+                ID:e.ID,
+                projectID: e.projectID,
+                is_related:e.is_related,//关联,1关,0不关
+                projectGLJID:e.projectGLJID,//关联工料机ID
+                seq:e.seq,//序号
+                code:e.code,
+                name:e.name,
+                specs:e.specs,
+                unit:e.unit,
+                type:e.type,
+                marketPrice:e.market_price,
+                quantity:e.quantity,
+                locked:e.locked,//锁定,1锁,0不锁
+                remark:e.remark,
+                originPlace:e.originPlace,//产地
+                vender:e.vender //厂家
+            };
+            let pglj = gljMap[e.projectGLJID];
+            if(e.is_related && pglj){
+                gljOprObj.setGLJPrice(t,pglj);
+                t.originPlace = pglj.originPlace;
+                t.vender = pglj.vender;
+                t.remark = pglj.remark;
+                t.quantity = pglj.quantity;
+            }
+            t.totalPrice = scMathUtil.roundForObj(parseFloat(t.quantity) * parseFloat(t.marketPrice) ,getDecimal('bills.totalPrice'));
+            datas.push(t);
+        }
+        return _.sortByAll(datas,'code');
+    },
+
+    updateConfigMaterial:function (dataCode,value,recode) {
+        let task = [];
+        for(let t of projectObj.project.projectGLJ.datas.gljList){
+            this.GLJIDMap[t.id] = t;
+        }
+        let glj = this.GLJIDMap[recode.id];
+        if(!glj) return;
+        let pdata = {doc:{},action:'update'};
+        pdata['type'] = 'glj_list';
+        pdata.doc[dataCode] = value;
+        pdata['id'] = glj.id;
+        task.push(pdata);
+        if(dataCode == "is_evaluate"){
+            this.getEvaluateUpdateTasks(value,glj,task);
+            this.updateEvaluateMaterial(task);
+        }
+
+    },
+
+    updateEvaluateMaterial :async function(data,refreshEvaluate=true){
+        try {
+            $.bootstrapLoading.start();
+            let result =  await ajaxPost('/glj/updateEvaluateMaterial',{tasks:data});
+            //先刷新缓存
+            let [gljs,sendPriceChange] = this.refreshCache(data);
+            if(refreshEvaluate == true){
+                let [rationNodes,impactGLJs] =  projectObj.project.projectGLJ.batchChangeIsEvaluate(gljs);
+                projectObj.project.calcProgram.calcNodesAndSave(rationNodes, function () {
+                    projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots);
+                });
+            }
+            projectGljObject.refreshViewsData();
+            gljOprObj.refreshView();
+            if(sendPriceChange == true) projectGljObject.onUnitFileChange();
+
+
+        }catch (e){
+            console.log(e)
+        }finally {
+            $.bootstrapLoading.end();
+        }
+    },
+
+    refreshCache:function (tasks) {
+        let gljs = [];
+        let sendPriceChange = false;
+        for(let t of tasks){
+            if(t.type == "evaluate_list"){
+                if(t.action == "update"){
+                    let e = _.find(projectObj.project.evaluate_list.datas,{'ID':t.ID});
+                    if(e) updateProperty(e,t.doc);
+                }
+                if(t.action == "add") projectObj.project.evaluate_list.datas.push(t.doc);
+                if(t.action == "delete") _.remove(projectObj.project.evaluate_list.datas,{'ID':t.ID});
+            }else {
+                if(_.isEmpty(this.GLJIDMap)) this.GLJIDMap = _.indexBy(projectObj.project.projectGLJ.datas.gljList,'id');
+                //剩下两个类型只有更新操作
+                if(t.type == "unit_price"){
+                    let g = this.GLJIDMap[t.projectGLJID];
+                    if(g) {
+                        let f = updateProperty(g.unit_price,t.doc);
+                        if(f == true) sendPriceChange = true;
+                        gljs.push(g);
+                    }
+                }
+                if(t.type == "glj_list"){
+                    let g = this.GLJIDMap[t.id];
+                    if(g){
+                        let f = updateProperty(g,t.doc);
+                        if(f == true) sendPriceChange = true;
+                        gljs.push(g);
+                    }
+                }
+            }
+        }
+        this.GLJIDMap = {};
+        return [gljs,sendPriceChange];
+        function updateProperty(obj,doc) {
+            let updatePrice = false;
+            for(let k in doc){
+                obj[k] = doc[k];
+                if(k == 'base_price' || k == 'market_price') updatePrice = true;
+            }
+            return updatePrice;
+        }
+    },
+    getEvaluateUpdateTasks:function (value,glj,task) {
+        if(value == 1){ //勾选暂估选项,查看已有的暂估材料列表中是否有名称,编号等完全相同的记录,有则直接关联,无则添加
+            let evaluate = null;
+            let pindex = gljUtil.getIndex(glj);
+            for(let e of projectObj.project.evaluate_list.datas){
+                let eIndex = gljUtil.getIndex(e);
+                if(pindex == eIndex){
+                    evaluate = e;
+                    break;
+                }
+            }
+            if(evaluate){//有找到则更新,没有则添加
+                let edata = {type:'evaluate_list',doc:{},action:"update",ID:evaluate.ID};
+                edata.doc = {projectGLJID:glj.id,is_related:1};
+                task.push(edata);
+                let udata = {type:'unit_price',doc:{},action:"update",projectGLJID:glj.id,id : glj.unit_price.id};
+                //if(evaluate.base_price != glj.unit_price.base_price) udata.doc['base_price'] = evaluate.base_price;
+                if(evaluate.market_price != glj.unit_price.market_price) udata.doc['market_price'] = evaluate.market_price;
+                if(!_.isEmpty(udata.doc)) task.push(udata);
+            }else {
+                let ndata = {type:'evaluate_list',doc:{},action:"add"};
+                ndata.doc['ID'] = uuid.v1();
+                ndata.doc['projectGLJID'] = glj.id;
+                ndata.doc['is_related'] = 1;
+                ndata.doc['locked'] = 0;
+                ndata.doc['seq'] = glj.code;
+                ndata.doc['projectID'] = glj.project_id;
+                ndata.doc['code'] = glj.code;
+                ndata.doc['name'] = glj.name;
+                ndata.doc['specs'] = glj.specs;
+                ndata.doc['unit'] = glj.unit;
+                ndata.doc['quantity'] = glj.quantity;
+                ndata.doc['type'] = glj.type;
+                ndata.doc['market_price'] = glj.unit_price.market_price;
+               // ndata.doc['base_price'] = glj.unit_price.base_price;
+                ndata.doc['originPlace'] = glj.originPlace;
+                ndata.doc['vender'] = glj.vender;
+                ndata.doc['remark'] = glj.remark;
+                task.push(ndata);
+            }
+        }else if(value == 0){
+            let t_evaluate = null;
+            for(let e of projectObj.project.evaluate_list.datas){
+                if(e.projectGLJID == glj.id && e.is_related == 1){
+                    t_evaluate = e;
+                    break;
+                }
+            }
+            if(t_evaluate){
+                let tdata = {type:'evaluate_list',doc:{is_related:0,quantity:'0'},action:"update",ID:t_evaluate.ID};
+                task.push(tdata);
+            }
+        }
+    },
+    onEvaluateMaterialSelectionChange:function (sender, args) {
+        let me = configMaterialObj;
+        let newSel = args.newSelections[0];
+        let oldSel = args.oldSelections?args.oldSelections[0]:{};
+        if(newSel.row != oldSel.row){
+            me.showEvaluateRelateDatas();
+            me.relateFilterAgain = false;
+        }
+    },
+    onEvaluateMaterialValueChange:function (e,info) {
+        let me = configMaterialObj,row = info.row, col = info.col;
+        let dataCode = me.evaluateMaterialSetting.header[col].dataCode;
+        let value = info.newValue;
+        let evaluate = me.evaluateMaterialDatas[row];
+
+        if (value&&! sheetCommonObj.checkData(col,me.evaluateMaterialSetting,value)) {
+            alert('输入的数据类型不对,请重新输入!');
+            return me.showEvaluateMaterialDatas();
+        }
+
+        if(dataCode == 'locked')  value = value == true?1:0;
+        if(dataCode == 'marketPrice'){
+            dataCode = 'market_price';
+            if(evaluate.is_related){//关联的情况下,直接修改工料机价格
+                return projectObj.project.projectGLJ.updatePrice(evaluate,dataCode,value,'rg', projectGljObject.refreshViewsData);
+            }
+        }
+        if(dataCode === 'quantity'){//修改数量需做4舍5入
+            value=  scMathUtil.roundToString(value,getDecimal('glj.quantity'));
+        }
+
+        let edata = {type:'evaluate_list',doc:{},action:"update",ID:evaluate.ID};
+        if(evaluate[dataCode] == value) return me.showEvaluateMaterialDatas();
+        edata.doc[dataCode] = value;
+        me.updateEvaluateMaterial([edata],false);
+    },
+    onEvaluateRelateValueChange:function (e,info){
+        let me = configMaterialObj,row = info.row, col = info.col;
+        let value = info.newValue;
+        let sel = me.evaluateMaterialSheet.getSelections()[0];
+        let srow = sel.row == -1||sel.row == ""?0:sel.row;
+        let task = [];
+        value = value == true?1:0;
+        if(me.evaluateMaterialDatas.length>srow){
+            let evaluate = me.evaluateMaterialDatas[srow];
+            let relate = me.evaluateRelateDatas[row];
+            let pdata = {id:relate.id,doc:{is_evaluate:value},action:'update',type:"glj_list"};
+            task.push(pdata);
+            let tdata = {type:'evaluate_list',doc:{},action:"update",ID:evaluate.ID};
+            if(value == 0){//如果是1的话
+                tdata.doc = {is_related:0,quantity:'0'};
+            }else {
+                //如果已经关联了其它项目工料机,要把那个项目工料机的是否暂估标记为否
+                if(evaluate.is_related == 1)  task.push({id:evaluate.projectGLJID,doc:{is_evaluate:0},action:'update',type:"glj_list"});
+                //更新暂估材料的工料机ID,和关联标记
+                tdata.doc = {projectGLJID:relate.id,is_related:1};
+                //更新新关联工料机的市场价格
+                let udata = {type:'unit_price',doc:{},action:"update",projectGLJID:relate.from.id,id : relate.from.unit_price.id};
+                //if(evaluate.base_price != relate.from.unit_price.base_price) udata.doc['base_price'] = evaluate.base_price;
+                if(evaluate.marketPrice != relate.from.unit_price.market_price) udata.doc['market_price'] = evaluate.marketPrice;
+                if(!_.isEmpty(udata.doc)) task.push(udata);
+            }
+            task.push(tdata);
+            me.updateEvaluateMaterial(task);
+        }
+    },
+    deleteEvaluateMaterial:function (row) {
+        let me = configMaterialObj;
+        let evaluate = me.evaluateMaterialDatas[row],task=[];
+        if(evaluate){
+            task.push({type:'evaluate_list',action:"delete",ID:evaluate.ID});
+            if(evaluate.is_related == 1){//如果关联了工料机,则要把工料机标记为不是暂估
+                task.push({id:evaluate.projectGLJID,doc:{is_evaluate:0},action:'update',type:"glj_list"})
+            }
+            me.updateEvaluateMaterial(task);
+        }
+    },
+    onEvaluateMaterialEditStarting:function (sender, args) {
+        let me = configMaterialObj;
+        let row = args.row,col = args.col;
+        let evaluate = me.evaluateMaterialDatas[row];
+        let dataCode = me.evaluateMaterialSetting.header[col].dataCode;
+        if(evaluate.locked){
+            args.cancel = true;
+        }else if(dataCode == 'quantity' && evaluate.is_related){//在关联的情况下,数量不可编辑
+            args.cancel = true;
+        }
+    },
+    onEvaluateRelateEditStarting:function (sender, args) {
+        let me = configMaterialObj;
+        let row = args.row,col = args.col;
+        args.cancel = true;
+    },
+    initRightClick : function() {
+        let me = this;
+        $.contextMenu({
+            selector: '#config_material_sheet',
+            build: function ($trigger, e) {
+                me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, me.configSpread);
+                return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                    me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "addFromGLJ":{
+                    name: '从人材机汇总中选择',
+                    icon: 'fa-sign-in',
+                    disabled: function () {
+                        return false;
+                    },
+                    callback: function (key, opt) {
+                        $("#selectPGLJ").modal('show');
+                    }
+                },
+                "deleteAdjust": {
+                    name: "删除",
+                    icon: 'fa-trash-o',
+                    disabled: function () {
+                        return me.rightClickTarget.row === undefined;
+                    },
+                    callback: function (key, opt) {
+                        let row = me.rightClickTarget.row;
+                        me.deleteEvaluateMaterial(row);
+                    }
+                }
+            }
+        });
+    }
+};
+
+let pgljSelObj={
+    spread:null,
+    sheet:null,
+    datas:[],
+    setting:{
+        header: [
+            {headerName: "选择", headerWidth: 45, dataCode: "select", hAlign: "center", dataType: "String",cellType:'checkBox'},
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "类型", headerWidth: 30, dataCode: "short_name", hAlign: "center", dataType: "String"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell'},
+            {headerName: "规格型号", headerWidth: 100, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "总消耗量", headerWidth: 90, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+            {headerName: "供货方式", headerWidth: 70, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
+            {headerName: "暂估", headerWidth: 45, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox'},
+            {headerName: "产地", headerWidth: 80, dataCode: "originPlace", hAlign: "left", dataType: "String"},
+            {headerName: "厂家", headerWidth: 80, dataCode: "vender", hAlign: "left", dataType: "String"},
+            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
+        ],
+        view: {
+            lockColumns: ["is_evaluate"]
+        }
+    },
+    checkType:"取消",//记住点击过的按钮的text
+    initSpread:function () {
+        if(!this.spread){
+            this.spread = SheetDataHelper.createNewSpread($("#pglj_from_sheet")[0]);
+            sheetCommonObj.spreadDefaultStyle(this.spread);
+        }
+        this.sheet = this.spread.getSheet(0);
+        sheetCommonObj.initSheet(this.sheet,this.setting);
+        this.sheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onEditStarting);
+        this.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, this.onClipboardPasting);
+        this.sheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onValueChanged);
+        this.sheet.setRowHeight(0, 36, 1);
+        disableRightMenu("pglj_from_sheet",this.spread);
+    },
+    onEditStarting:function (e,args) {
+        args.cancel = true;
+    },
+    onClipboardPasting:function (e,args) {
+        args.cancel = true;
+    },
+    onValueChanged:function (e,args) {
+        let me = pgljSelObj;
+        let value = args.newValue;
+        value = value == true?1:0;
+        me.datas[args.row].select = value;
+    },
+    showDatas:function () {
+        this.datas = [];
+        let gljList = projectObj.project.projectGLJ.datas.gljList;
+        gljList = this.filterGLJ(gljList);
+        gljList = sortProjectGLJ(gljList);
+        for(let glj of gljList){
+            this.datas.push(this.getSheetDatas(glj));
+        }
+        this.refreshDatas();
+    },
+    filterGLJ:function (gljList) {
+        let typeMap = {};
+        for(let ch of $(".pglj_sel_input:checked")){
+            typeMap[$(ch).val()] = true;
+        }
+        let inputV = $("#pglj_sel_input").val();
+        return _.filter(gljList,function (item) {
+            if(item.quantity === 0 || item.quantity === '0') return false;
+            let firstS = (item.type+"").substring(0,1);
+            if(!typeMap[firstS]) return false;
+            if(inputV!=""){//输入的关键字过滤
+                if(item.code.indexOf(inputV)==-1 && item.name.indexOf(inputV)==-1) return false
+            }
+            return true;
+        });
+    },
+    refreshDatas:function () {
+        this.checkByType(this.checkType);
+        sheetCommonObj.showData(this.sheet, this.setting,this.datas);
+        this.sheet.setRowCount(this.datas.length);
+    },
+    getSheetDatas(glj){
+        let projectGLJ = projectObj.project.projectGLJ;
+        let materialIdList = projectGLJ.datas.constData.materialIdList;
+        let data = materialAdjustObj.getCommonObject(glj);
+        data.select = glj.is_evaluate;
+        data.from = glj;
+        data.short_name = projectGLJ.getShortNameByID(glj.type);
+        // 只有材料才显示是否暂估
+       // if (materialIdList.indexOf(glj.type) >= 0) data.is_evaluate = glj.is_evaluate;
+        data.is_evaluate = glj.is_evaluate;
+        return data;
+    },
+    checkByType:function (type) {
+        for(let d of this.datas){
+            d.select = 0;
+            switch (type){
+                case "全选":
+                    d.select = 1;
+                    break;
+                case "全选主材":
+                    if(d.type == 4) d.select = 1;
+                    break;
+                case "全选设备":
+                    if(d.type == 5) d.select = 1;
+                    break;
+                case "取消":
+                    d.select = d.is_evaluate;
+                    break;
+            }
+        }
+        //this.refreshDatas();
+    },
+    confirmSelect:function () {
+        let tasks = [];
+        let evaluateMap = _.indexBy(projectObj.project.evaluate_list.datas,"projectGLJID");
+        let evaluateKeyMap = {};//关键字映射表
+        for(let e of projectObj.project.evaluate_list.datas){
+            let eIndex = gljUtil.getIndex(e);
+            evaluateKeyMap[eIndex] = e;
+        }
+        for(let d of this.datas){
+            if(d.select == 1){//如果是选中状态
+                if(d.is_evaluate == 1) {//如果是暂估,查看是否已经存在关联的暂估材料
+                    let evl = evaluateMap[d.id];
+                    if(evl){
+                        //这里应该是错误检查的保证,按正常是不应该出现这种情况的
+                        if(evl.is_related !=1) tasks.push({type:'evaluate_list',doc:{projectGLJID:d.id,is_related:1},action:"update",ID:evl.ID});
+                    }else {
+                        tasks.push(getNewEval(d))
+                    }
+                }else {//如果不是暂估,要改成暂估
+                    let pdata = {id:d.id,doc:{is_evaluate:1},action:'update',type:"glj_list"};
+                    tasks.push(pdata);
+                    let evaluate = evaluateKeyMap[gljUtil.getIndex(d)];
+                    if(evaluate) {//如果已经存在5个关键字相同的暂估材料,则自动关联起来
+                        let edata = {type:'evaluate_list',doc:{projectGLJID:d.id,is_related:1},action:"update",ID:evaluate.ID};
+                        tasks.push(edata);
+                        let udata = {type:'unit_price',doc:{},action:"update",projectGLJID:d.id,id : d.from.unit_price.id};
+                        if(evaluate.market_price != d.from.unit_price.market_price) udata.doc['market_price'] = evaluate.market_price;
+                        if(!_.isEmpty(udata.doc)) tasks.push(udata);
+                    }else {//如果不存在,则生成一条新的
+                        tasks.push(getNewEval(d));
+                    }
+                }
+            }else {//未选中状态的,检查一下是否存在关联的情况,取消关联
+                if(d.is_evaluate == 1)  tasks.push({id:d.id,doc:{is_evaluate:0},action:'update',type:"glj_list"});
+                let evl = evaluateMap[d.id];
+                if(evl){
+                    if(evl.is_related ==1) tasks.push({type:'evaluate_list',doc:{is_related:0},action:"update",ID:evl.ID});
+                }
+                let evaluate = evaluateKeyMap[gljUtil.getIndex(d)];
+                if(evaluate) {
+                    if(evaluate.is_related ==1) tasks.push({type:'evaluate_list',doc:{is_related:0},action:"update",ID:evaluate.ID});
+                }
+            }
+        }
+        if(tasks.length > 0) configMaterialObj.updateEvaluateMaterial(tasks);
+
+
+        function getNewEval(d) {
+            let ndata = {type:'evaluate_list',doc:{},action:"add"};
+            ndata.doc['ID'] = uuid.v1();
+            ndata.doc['projectGLJID'] = d.id;
+            ndata.doc['is_related'] = 1;
+            ndata.doc['locked'] = 0;
+            ndata.doc['seq'] = d.code;
+            ndata.doc['projectID'] = d.from.project_id;
+            ndata.doc['code'] = d.code;
+            ndata.doc['name'] = d.name;
+            ndata.doc['specs'] = d.specs;
+            ndata.doc['unit'] = d.unit;
+            ndata.doc['quantity'] = d.quantity;
+            ndata.doc['type'] = d.type;
+            ndata.doc['market_price'] = d.from.unit_price.market_price;
+            ndata.doc['originPlace'] = d.originPlace;
+            ndata.doc['vender'] = d.vender;
+            ndata.doc['remark'] = d.remark;
+            return ndata;
+        }
+        
+        
+    }
+};
+
+
+
+$(function () {
+  $("#filterAgain").click(function(){
+      configMaterialObj.relateFilterAgain = true;//重新过滤标记
+      configMaterialObj.showEvaluateRelateDatas();
+  })
+
+    $('#selectPGLJ').on('shown.bs.modal',function(e){
+        pgljSelObj.checkType="取消";
+        pgljSelObj.initSpread();
+        pgljSelObj.showDatas();
+    });
+
+    $(".pglj_sel_input").change(function () {
+        let check = $(this).prop("checked");
+        if($(this).val() == 0){//勾选的是全选,其它的勾选项跟着改变
+            for(let a of $(".pglj_sel_input")){
+                $(a).prop("checked",check)
+            }
+        }else {//勾选其它选项
+            let a_checked = true;
+            for(let o of $(".pglj_sel_input_other")){//如果其它的有一个不勾选,则所有项也不打勾
+                if($(o).prop("checked") === false){
+                    a_checked = false;
+                    break;
+                }
+            }
+            $("#pglj_sel_all").prop("checked",a_checked);
+        }
+
+        pgljSelObj.showDatas();
+    });
+
+    $("#pglj_sel_btn_find").click(function () {
+        pgljSelObj.showDatas();
+    });
+
+    $(".pglj_sel_check_btn").click(function () {
+        pgljSelObj.checkType = $(this).text();
+        pgljSelObj.refreshDatas();
+    })
+
+    $("#pglj_sel_confirm").click(function () {
+        pgljSelObj.confirmSelect();
+    })
+
+});
+
+

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

@@ -53,6 +53,7 @@ projectGljObject={
     initSpreads:function(){
         if(this.projectGljSpread==null) this.initProjectGljSpread();
         if(materialAdjustObj.spread == null) materialAdjustObj.initSpread();
+        if(configMaterialObj.configSpread == null) configMaterialObj.initSpread();
     },
     initProjectGljSpread:function () {
         if(!this.projectGljSpread){
@@ -406,6 +407,7 @@ projectGljObject={
         let me = projectGljObject,updateMap = {};
         let projectGLJ = projectObj.project.projectGLJ;
         for(let c of changeInfo){
+            if(c.dataCode == 'is_evaluate') continue; //暂估,暂时跳过
             let recode = sheetName =="materialTreeSheet"?me.materialTree.items[c.row].data:me.projectGljSheetData[c.row];
             if(recode[c.dataCode] == c.value){
                 continue;
@@ -525,15 +527,23 @@ projectGljObject={
             let adjustType = projectObj.project.projectInfo.property.gljAdjustType || 'priceInfo';
             $('#adjustType').val(adjustType);
             $('#project-glj-main').hide();
+            $('#config_material').hide();
+        }else if(me.displayType == filterType.ZGCL){
+            $('#material_adjust').hide();
+            $('#adjustType').hide();
+            $('#project-glj-main').hide();
+            $('#config_material').show();
         } else {
             $('#material_adjust').hide();
             $('#adjustType').hide();
+            $('#config_material').hide();
             $('#project-glj-main').show();
         }
     },
     refreshViewsData:function(){
         let me = projectGljObject;
         if(me.displayType == filterType.AMAE) return materialAdjustObj.refreshSheetDatas();
+        if(me.displayType == filterType.ZGCL) return configMaterialObj.refreshSheetDatas();
         me.refreshDataSheet();
     },
     refreshDataSheet:function () {
@@ -928,6 +938,11 @@ projectGljObject={
             }
             if(dataCode === 'is_evaluate'||dataCode === 'is_adjust_price'||dataCode === 'is_main_material'||dataCode === 'no_tax_eqp'||dataCode == 'is_eval_material'){
                 value = value == true?1:0;
+                if(dataCode === 'is_evaluate'){
+                    configMaterialObj.updateConfigMaterial(dataCode,value,recode);//暂估材料,主要材料等新需求
+                    return
+                }
+
             }
             if(dataCode === 'materialType' && (value == null || value=="")){//删除三材类别时,清空三材系数
                 value = null;
@@ -938,6 +953,7 @@ projectGljObject={
             }
             extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
             if(recode[dataCode] == value) return;
+
             let updateData = {id: recode.id, field: dataCode, value: value, extend: extend};
             projectGLJ.pGljUpdate(updateData,callback);
         };
@@ -1116,10 +1132,28 @@ function getProjectResizeEles() {
     };
     return pojGljResizeEles;
 }
-
+function getConficMaterialResizeEles() {
+    let conficMaterialResizeEles = {};
+    conficMaterialResizeEles.eleObj = {
+        module: 'conficMaterial',
+        resize: $('#configMaterialResize'),
+        top: $('#configMaterialTop'),
+        topSpread: $('#config_material_sheet'),
+        bottom: $('#configMaterialBottom'),
+        bottomSpread: $('#related_sheet')
+    };
+    conficMaterialResizeEles.limit = {
+        min: 150,
+        max: `$(window).height()-$('.header').height()-$('#projectGljToolsBar').height()-150-5`,//5: resize.height()
+        notTopSpread: 0,
+        notBottomSpread: 0,
+        totalHeight: `$(window).height()-$('.header').height()-$('#projectGljToolsBar').height()-5`,
+        bottomNav:`$('#configMaterialBottom ul').height() + $('#filterToolDiv').height()+10`
+    };
+    return conficMaterialResizeEles;
+}
 
 function loadProjectGljSize() {
-
     if($('#project-glj-main').is(':visible')){
         let me = projectGljObject;
         let pojGljResizeEles = getProjectResizeEles();
@@ -1130,6 +1164,14 @@ function loadProjectGljSize() {
     }else if($('#material_adjust').is(':visible')){
         $('#material_adjust_sheet').height($(window).height()-$('.header').height()-$('#projectGljToolsBar').height()+3);
         if(materialAdjustObj.spread)materialAdjustObj.spread.refresh();
+    }else if($('#config_material').is(':visible')){
+        let  configMaterialResizeEles = getConficMaterialResizeEles();
+        SlideResize.loadVerticalHeight(configMaterialResizeEles.eleObj.module, configMaterialResizeEles.eleObj, configMaterialResizeEles.limit, function () {
+            configMaterialObj.configSpread? configMaterialObj.configSpread.refresh():'';
+            configMaterialObj.relatedSpread? configMaterialObj.relatedSpread.refresh():'';
+            /*
+            me.mixRatioSpread?me.mixRatioSpread.refresh():'';*/
+        });
     }
 
 }
@@ -1164,6 +1206,14 @@ $(function () {
         projectGljObject.projectGljSpread.refresh();
         projectGljObject.mixRatioSpread?projectGljObject.mixRatioSpread.refresh():'';
     });
+
+    let tr = getConficMaterialResizeEles();
+    SlideResize.verticalSlide(tr.eleObj, tr.limit, function(){
+        configMaterialObj.configSpread? configMaterialObj.configSpread.refresh():'';
+        configMaterialObj.relatedSpread? configMaterialObj.relatedSpread.refresh():'';
+    });
+
+
     $('#tab_project_glj').on('shown.bs.tab', function (e) {
         sessionStorage.setItem('mainTab', '#tab_project_glj');
         let me = projectGljObject;