瀏覽代碼

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

zhangweicheng 1 月之前
父節點
當前提交
371a6509f8
共有 31 個文件被更改,包括 1128 次插入487 次删除
  1. 10 2
      modules/common/const/bills_fixed.js
  2. 34 8
      modules/price_info_lib/controllers/index.js
  3. 131 21
      modules/price_info_lib/facade/index.js
  4. 1 0
      modules/price_info_lib/routes/index.js
  5. 1 0
      modules/ration_repository/models/ration_item.js
  6. 5 0
      modules/reports/rpt_component/helper/jpc_helper_common_output.js
  7. 274 251
      modules/users/models/engineering_lib_model.js
  8. 6 0
      public/web/rpt_value_define.js
  9. 8 3
      web/maintain/common/html/layout.html
  10. 21 1
      web/maintain/price_info_lib/html/edit.html
  11. 37 0
      web/maintain/price_info_lib/html/main.html
  12. 2 1
      web/maintain/price_info_lib/js/index.js
  13. 64 0
      web/maintain/price_info_lib/js/main.js
  14. 27 0
      web/maintain/price_info_lib/js/priceArea.js
  15. 20 7
      web/maintain/price_info_lib/js/priceClass.js
  16. 3 3
      web/maintain/price_info_lib/js/priceEmpty.js
  17. 2 1
      web/maintain/price_info_lib/js/priceItem.js
  18. 17 4
      web/maintain/report/html/rpt_tpl_dtl_field_loc.html
  19. 11 0
      web/maintain/report/html/rpt_tpl_dtl_info.html
  20. 2 0
      web/maintain/report/html/rpt_tpl_dtl_pre_hdl.html
  21. 15 0
      web/maintain/report/html/rpt_tpl_dtl_pre_hdl_arterial_highway_rule.html
  22. 21 0
      web/maintain/report/js/jpc_output.js
  23. 210 167
      web/maintain/report/js/rpt_tpl_calculation.js
  24. 9 0
      web/maintain/report/js/rpt_tpl_cfg_helper.js
  25. 4 0
      web/maintain/report/js/rpt_tpl_data_map.js
  26. 24 3
      web/maintain/report/js/rpt_tpl_main.js
  27. 62 2
      web/maintain/report/js/rpt_tpl_pre_handle.js
  28. 29 1
      web/maintain/std_glj_lib/html/gongliao.html
  29. 64 12
      web/maintain/std_glj_lib/js/glj.js
  30. 4 0
      web/users/js/compilation.js
  31. 10 0
      web/users/views/compilation/engineering.html

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

@@ -241,8 +241,13 @@ if (process.env.NODE_ENV.indexOf('hw') !== -1) {
         // 社会稳定风险评估费
         SOCIAL_STABILITY: 205,
         // 建设项目其他费设置
-        CONSTRUCTION_OTHER_SETTING: 206
-
+        CONSTRUCTION_OTHER_SETTING: 206,
+        // 研究试验费
+        RESEARCH_EXPERIMENT: 207,
+        // 压覆重要矿床评估费
+        IMPORTANT_ORE_DEPOSITS: 208,
+        // 招标文件及标底编制费
+        INVITATION_BID_DOC_COMPILATION: 209
 
     };
 }
@@ -324,6 +329,9 @@ const fixedFlagList = [
     { name: '节能评估费', value: fixedFlag.ENERGY_CONSERVATION },
     { name: '社会稳定风险评估费', value: fixedFlag.SOCIAL_STABILITY },
     { name: '建设项目其他费设置', value: fixedFlag.CONSTRUCTION_OTHER_SETTING },
+    { name: '研究试验费', value: fixedFlag.RESEARCH_EXPERIMENT },
+    { name: '压覆重要矿床评估费', value: fixedFlag.IMPORTANT_ORE_DEPOSITS },
+    { name: '招标文件及标底编制费', value: fixedFlag.INVITATION_BID_DOC_COMPILATION },
 ];
 
 export { fixedFlag as default, fixedFlagList as List };

+ 34 - 8
modules/price_info_lib/controllers/index.js

@@ -31,11 +31,8 @@ class PriceInfoController extends BaseController {
         });
         const listItem = `
             <li class="nav-item">
-                <a class="nav-link" href="javascript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#crawl">导入材料价格信息</a>
+                <a class="nav-link" href="javascript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#export-zj">导出材料信息价</a>
             </li>
-            <li class="nav-item" style="display: none">
-            <a class="nav-link" href="javascript:void(0);" aria-haspopup="true" aria-expanded="false" id="export-compilation-price">导出编办材料价格信息</a>
-        </li>
             `
         const renderData = {
             title: '材料信息价库',
@@ -261,8 +258,8 @@ class PriceInfoController extends BaseController {
 
     async getPriceEmptyData(req, res) {
         try {
-            const { libID, compilationID, areaID } = JSON.parse(req.body.data);
-            const data = await facade.getPriceEmptyData(compilationID, libID, areaID);
+            const { libID, compilationID, areaID, matchAll } = JSON.parse(req.body.data);
+            const data = await facade.getPriceEmptyData(compilationID, libID, areaID, matchAll);
             res.json({ error: 0, message: 'getPriceEmptyData success', data });
         } catch (err) {
             console.log(err);
@@ -317,8 +314,8 @@ class PriceInfoController extends BaseController {
     // 匹配总表
     async matchSummary(req, res) {
         try {
-            const { compilationID, libID, areaID } = JSON.parse(req.body.data);
-            await facade.matchSummary(compilationID, libID, areaID);
+            const { compilationID, libID, areaID, matchAll } = JSON.parse(req.body.data);
+            await facade.matchSummary(compilationID, libID, areaID, matchAll);
             res.json({ error: 0, message: 'matchSummary success' });
         } catch (err) {
             console.log(err);
@@ -373,6 +370,35 @@ class PriceInfoController extends BaseController {
         }
     }
 
+    /**
+     * 导出浙江省材料价格信息excel
+     * @param {Object} request
+     * @param {Object} response
+     * @return {void}
+     */
+    async exportZheJiangExcel(request, response) {
+        try {
+            const { from, to } = request.query;
+            const excelData = await facade.getZheJiangSheetData(from, to);
+            const sheetOptions = { '!cols': [{ wch: 15 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 15 }, { wch: 10 }] };
+            const buffer = excel.build([{ name: "sheet", data: excelData }], sheetOptions);
+            const filePath = './public/price.xlsx';
+            fs.writeFileSync(filePath, buffer, 'binary');
+            const stats = fs.statSync(filePath);
+            const filename = '浙江信息价.xlsx';
+            const encoded = encodeURIComponent(filename);
+            response.set({
+                'Content-Type': 'application/octet-stream',
+                'Content-Disposition': `attachment; filename*=UTF-8''${encoded}`,
+                'Content-Length': stats.size
+            });
+            fs.createReadStream(filePath).pipe(response);
+            fs.unlink(filePath);
+        } catch (error) {
+            response.end(error);
+        }
+    }
+
 }
 
 module.exports = {

+ 131 - 21
modules/price_info_lib/facade/index.js

@@ -566,23 +566,33 @@ const getSummaryMap = (items) => {
 }
 
 // 匹配总表
-// 按规则匹配信息价的编码、别名编码、计算式(只匹配珠海建筑,要单独标记珠海地区);
+// 按规则匹配信息价的编码、别名编码
 // 匹配规则:名称+规格型号+单位,与总表一致则自动填入编码、别名编码、计算式(珠海建筑);
-const matchSummary = async (compilationID, libID, areaID) => {
-    const updateBulks = [];
-    const areaFilter = { compilationID };
-    if (areaID) {
-        areaFilter.ID = areaID;
+const matchSummary = async (compilationID, libID, areaID, matchAll) => {
+    if (!compilationID || !libID || !areaID) {
+        return;
     }
-    const areas = await priceInfoAreaModel.find(areaFilter, '-_id ID name').lean();
-    const areaNameMap = {};
-    areas.forEach(area => {
-        areaNameMap[area.ID] = area.name;
-    });
     const filter = { libID };
-    if (areaID) {
+    if (matchAll) {
+        const areas = await priceInfoAreaModel.find({ compilationID }, 'ID name').lean();
+        const area = areas.find(area => area.ID === areaID);
+        if (!area) {
+            return [];
+        }
+        const rootAreaName = area.name.split('-')[0];
+        const areaIDs = [];
+        areas.forEach(area => {
+            const name = area.name.split('-')[0];
+            if (name === rootAreaName) {
+                areaIDs.push(area.ID);
+            }
+        });
+        filter.areaID = { $in: areaIDs };
+    } else {
         filter.areaID = areaID;
     }
+
+    const updateBulks = [];
     const priceItems = await priceInfoItemModel.find(filter, '-_id ID compilationID name specs unit areaID period').lean();
     const summaryItems = await priceInfoSummaryModel.find({}, '-_id ID name specs unit code classCode expString').lean();
     const summaryMap = getSummaryMap(summaryItems);
@@ -594,12 +604,6 @@ const matchSummary = async (compilationID, libID, areaID) => {
                 code: matched.code,
                 classCode: matched.classCode,
             }
-            console.log(matched);
-            console.log(updateObj);
-            const areaName = areaNameMap[priceItem.areaID];
-            /* if (/珠海/.test(areaName)) {
-                updateObj.expString = matched.expString;
-            } */
             updateBulks.push({
                 updateOne: {
                     filter: { ID: priceItem.ID, compilationID: priceItem.compilationID, areaID: priceItem.areaID, period: priceItem.period },
@@ -615,13 +619,29 @@ const matchSummary = async (compilationID, libID, areaID) => {
 }
 
 // 获取空数据(没有别名编码)
-const getPriceEmptyData = async (compilationID, libID, areaID) => {
+const getPriceEmptyData = async (compilationID, libID, areaID, matchAll) => {
     const lib = await priceInfoLibModel.findOne({ ID: libID }).lean();
-    if (!lib) {
+    if (!lib || !areaID) {
         return [];
     }
     const filter = { compilationID, libID, period: lib.period };
-    if (areaID) {
+    if (matchAll) {
+        const areas = await priceInfoAreaModel.find({ compilationID }, 'ID name').lean();
+        const area = areas.find(area => area.ID === areaID);
+        console.log(area);
+        if (!area) {
+            return [];
+        }
+        const rootAreaName = area.name.split('-')[0];
+        const areaIDs = [];
+        areas.forEach(area => {
+            const name = area.name.split('-')[0];
+            if (name === rootAreaName) {
+                areaIDs.push(area.ID);
+            }
+        });
+        filter.areaID = { $in: areaIDs };
+    } else {
         filter.areaID = areaID;
     }
     const priceItems = await priceInfoItemModel.find(filter).lean();
@@ -808,6 +828,95 @@ async function batchUpdate(priceItem, prop, val) {
 
 }
 
+// 根据期数范围,获取期数数据
+function getPeriodData(from, to) {
+    const monthMap = {
+        '1': '01月',
+        '2': '02月',
+        '3': '03月',
+        '4': '04月',
+        '5': '05月',
+        '6': '06月',
+        '7': '07月',
+        '8': '08月',
+        '9': '09月',
+        '10': '10月',
+        '11': '11月',
+        '12': '12月',
+    };
+    if (from > to) {
+        return null;
+    }
+    const reg = /(\d+)-(\d+)/;
+    const fromMatch = from.match(reg);
+    const fromYear = +fromMatch[1];
+    const fromMonth = +fromMatch[2];
+    const toMatch = to.match(reg);
+    const toYear = +toMatch[1];
+    const toMonth = +toMatch[2];
+    let curYear = fromYear;
+    let curMonth = fromMonth;
+    const periods = [];
+    while ((curYear <= toYear && curMonth <= toMonth) || curYear < toYear) {
+        periods.push(`${curYear}年-${monthMap[curMonth]}`);
+        if (curMonth === 12) {
+            curYear++;
+            curMonth = 1;
+        } else {
+            curMonth++;
+        }
+    }
+    return periods;
+}
+
+// 导出浙江信息价excel数据
+async function getZheJiangSheetData(from, to) {
+    const periods = getPeriodData(from, to);
+    if (!periods) {
+        throw '无效的期数区间。';
+    }
+    const compilationID = '5de61133d46f6f000d15d347';
+    const libs = await priceInfoLibModel.find({ compilationID, period: { $in: periods } }, '-_id ID name period').lean();
+    const areas = await priceInfoAreaModel.find({ compilationID }, '-_id ID name').lean();
+    const zjAreas = areas.filter(area => /浙江/.test(area.name) && /全市平均/.test(area.name));
+    // 地区按照serialNo排序
+    zjAreas.sort((a, b) => a.serialNo - b.serialNo);
+    const areaIDs = zjAreas.map(area => area.ID);
+    const libIDs = libs.map(lib => lib.ID);
+    const allPriceItems = await priceInfoItemModel.find({ compilationID, areaID: { $in: areaIDs }, libID: { $in: libIDs } }, '-_id libID areaID code name noTaxPrice').lean();
+    // 材料大类配置
+    const priceClasses = [
+        { name: '水泥', codes: ['5509001', '5509002', '5509003'] },
+        { name: '钢材', codes: ['2001001', '2001002', '2001008', '2003004'] },
+        { name: '砂石料', codes: ['5505016', '5503006', '1516001'] },
+    ]
+    const excelData = [['日期', '地区', '材料大类', '编码', '名称', '价格']];
+    libs.forEach(lib => {
+        // 日期
+        // excelData.push([lib.period || '', '', '', '', '', '']);
+        zjAreas.forEach(area => {
+            // 地区
+            const areaName = area.name.replace('浙江省-', '').replace('全市平均', '');
+            // excelData.push(['', areaName || '', '', '', '', '']);
+            // 材料大类
+            let priceItems = allPriceItems.filter(item => item.libID === lib.ID && item.areaID === area.ID);
+            priceItems = _.sortBy(priceItems, 'code');
+            priceClasses.forEach(priceClass => {
+                // excelData.push(['', '', priceClass.name || '', '', '', '']);
+                priceItems.forEach(item => {
+                    const code = item.code ? item.code.trim() : '';
+                    const name = item.name ? item.name.trim() : '';
+                    const price = item.noTaxPrice ? +item.noTaxPrice : '';
+                    if (priceClass.codes.includes(code)) {
+                        excelData.push([lib.period, areaName || '', priceClass.name || '', code, name, price]);
+                    }
+                });
+            });
+        });
+    });
+    return excelData;
+}
+
 
 module.exports = {
     getLibs,
@@ -835,4 +944,5 @@ module.exports = {
     exportInfoPriceByCompilation,
     getAllLibs,
     batchUpdate,
+    getZheJiangSheetData
 }

+ 1 - 0
modules/price_info_lib/routes/index.js

@@ -32,6 +32,7 @@ module.exports = function (app) {
     router.get("/exportInfoPriceByCompilation", priceInfoController.auth, priceInfoController.init, priceInfoController.exportInfoPriceByCompilation);
     router.post("/getAllLibs", priceInfoController.auth, priceInfoController.init, priceInfoController.getAllLibs);
     router.post("/batchUpdate", priceInfoController.auth, priceInfoController.init, priceInfoController.batchUpdate);
+    router.get("/exportZheJiangExcel", priceInfoController.auth, priceInfoController.init, priceInfoController.exportZheJiangExcel);
 
     app.use("/priceInfo", router);
 };

+ 1 - 0
modules/ration_repository/models/ration_item.js

@@ -1154,6 +1154,7 @@ rationItemDAO.prototype.exportExcelData = async function (rationRepId) {
     const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价', '工作内容', '附注', '单位']];
     excelData.push.apply(excelData, rationData);
 
+    console.log(excelData);
     return excelData;
 };
 

+ 5 - 0
modules/reports/rpt_component/helper/jpc_helper_common_output.js

@@ -31,6 +31,11 @@ let JpcCommonOutputHelper = {
         rst[JV.PROP_FONT] = node[[JV.PROP_FONT]];
         rst[JV.PROP_CONTROL] = node[[JV.PROP_CONTROL]];
         rst[JV.PROP_STYLE] = node[[JV.PROP_STYLE]];
+        if (node.diagonal_down === 'T') {
+            rst.diagonal_down = true;
+        } else if (node.diagonal_up === 'T') {
+            rst.diagonal_up = true;
+        }
         //2. value
         rst[JV.PROP_VALUE] = value;
         JpcFieldHelper.decorateValue(rst, controls);

+ 274 - 251
modules/users/models/engineering_lib_model.js

@@ -9,153 +9,160 @@ import mongoose from "mongoose";
 import BaseModel from "../../common/base/base_model";
 import CompilationModel from "./compilation_model";
 let stdRationLibModel = mongoose.model("std_ration_lib_map");
-import { default as EngineeringConst, List as EngineeringList } from "../../common/const/engineering";
+import {
+  default as EngineeringConst,
+  List as EngineeringList,
+} from "../../common/const/engineering";
 
 class EngineeringLibModel extends BaseModel {
-    /**
-     * 构造函数
-     *
-     * @return {void}
-     */
-    constructor() {
-        let parent = super();
-        parent.model = mongoose.model("engineering_lib");
-        parent.init();
+  /**
+   * 构造函数
+   *
+   * @return {void}
+   */
+  constructor() {
+    let parent = super();
+    parent.model = mongoose.model("engineering_lib");
+    parent.init();
+  }
+
+  /**
+   * 获取标准库数据
+   *
+   * @param {Object} data
+   * @param {Number} engineering
+   * @return {Promise}
+   */
+  async getLib(data, engineering) {
+    let result = {};
+    if (data.length <= 0) {
+      return result;
     }
-
-    /**
-     * 获取标准库数据
-     *
-     * @param {Object} data
-     * @param {Number} engineering
-     * @return {Promise}
-     */
-    async getLib(data, engineering) {
-        let result = {};
-        if (data.length <= 0) {
-            return result;
-        }
-        let id = '';
-        for (let tmp of data) {
-            if (tmp.engineering === engineering) {
-                id = tmp.engineering_id;
-                break;
-            }
-        }
-        if (id === '') {
-            return result;
-        }
-        let condition = { _id: id };
-        return this.findDataByCondition(condition);
+    let id = "";
+    for (let tmp of data) {
+      if (tmp.engineering === engineering) {
+        id = tmp.engineering_id;
+        break;
+      }
     }
-
-    async getLibsByValuationID(valuationID) {
-        return this.findDataByCondition({ valuationID: valuationID }, null, false);
+    if (id === "") {
+      return result;
     }
-
-    async deleteByValuationID(valuationID) {
-        return await this.db.delete({ valuationID: valuationID });
+    let condition = { _id: id };
+    return this.findDataByCondition(condition);
+  }
+
+  async getLibsByValuationID(valuationID) {
+    return this.findDataByCondition({ valuationID: valuationID }, null, false);
+  }
+
+  async deleteByValuationID(valuationID) {
+    return await this.db.delete({ valuationID: valuationID });
+  }
+
+  //添加空的默认的所有标准库
+  /**
+   * @param valuationID
+   * @returns {Promise.<*>}
+   */
+  async addStdLib(valuationID) {
+    let stdLibs = [];
+    for (let eng of EngineeringList) {
+      let tem = {
+        glj_col: { showAdjustPrice: false },
+        valuationID: valuationID,
+        name: eng.name,
+        engineering: eng.value,
+      };
+      stdLibs.push(tem);
     }
-
-
-    //添加空的默认的所有标准库
-    /**
-     * @param valuationID
-     * @returns {Promise.<*>}
-     */
-    async addStdLib(valuationID) {
-        let stdLibs = [];
-        for (let eng of EngineeringList) {
-            let tem = {
-                glj_col: { showAdjustPrice: false },
-                valuationID: valuationID,
-                name: eng.name,
-                engineering: eng.value
-            };
-            stdLibs.push(tem);
-        }
-        let result = await this.db.create(stdLibs);
-        return result;
+    let result = await this.db.create(stdLibs);
+    return result;
+  }
+
+  async addEngineer(data) {
+    data.glj_col = { showAdjustPrice: false };
+    if (data.compilationId && data.compilationId != "") {
+      data.ration_lib = [];
+      let rationList = await stdRationLibModel.find(
+        { compilationId: data.compilationId },
+        ["ID", "dispName"]
+      );
+      for (let i = 0; i < rationList.length; i++) {
+        let tem = {
+          id: rationList[i].ID,
+          name: rationList[i].dispName,
+          onlyProfession: false,
+          isDefault: false,
+        };
+        if (i == 0) tem.isDefault = true;
+        data.ration_lib.push(tem);
+      }
     }
-
-    async addEngineer(data) {
-        data.glj_col = { showAdjustPrice: false };
-        if (data.compilationId && data.compilationId != "") {
-            data.ration_lib = [];
-            let rationList = await stdRationLibModel.find({ compilationId: data.compilationId }, ['ID', 'dispName']);
-            for (let i = 0; i < rationList.length; i++) {
-                let tem = {
-                    id: rationList[i].ID,
-                    name: rationList[i].dispName,
-                    isDefault: false
-                };
-                if (i == 0) tem.isDefault = true;
-                data.ration_lib.push(tem);
-            }
-        }
-        let result = await this.db.create(data);
-        return result;
+    let result = await this.db.create(data);
+    return result;
+  }
+
+  // 拷贝工程专业
+  async copyEngineer(sourceID) {
+    const engineering = await this.db.findOne({ _id: sourceID });
+    const newEngineering = engineering._doc;
+    delete newEngineering._id;
+    newEngineering.visible = false;
+    await this.db.create(newEngineering);
+  }
+
+  /**
+   * 新增标准库
+   *
+   * @param {String} valuationId
+   * @param {Object} data
+   * @return {Promise}
+   */
+  async addLib(engineerId, data) {
+    if (data.glj_col) {
+      data.glj_col = JSON.parse(data.glj_col);
     }
-
-    // 拷贝工程专业
-    async copyEngineer(sourceID) {
-        const engineering = await this.db.findOne({ _id: sourceID });
-        const newEngineering = engineering._doc;
-        delete newEngineering._id;
-        newEngineering.visible = false;
-        await this.db.create(newEngineering);
+    data.isInstall == "true"
+      ? (data.isInstall = true)
+      : (data.isInstall = false);
+    let result = false;
+    data = this.filterLibData(data);
+    try {
+      let engineeringLib = await this.findDataByCondition({ _id: engineerId });
+      if (engineeringLib) {
+        // 存在则直接更新
+        delete data.id;
+        delete data.section;
+        let condition = { _id: engineerId };
+        result = await this.db.update(condition, data);
+        result = result.ok === 1;
+      } else {
+        throw new Error("找不到对应的工程专业");
+      }
+    } catch (error) {
+      console.log(error);
+      result = false;
     }
 
-    /**
-     * 新增标准库
-     *
-     * @param {String} valuationId
-     * @param {Object} data
-     * @return {Promise}
-     */
-    async addLib(engineerId, data) {
-        if (data.glj_col) {
-            data.glj_col = JSON.parse(data.glj_col);
-        }
-        data.isInstall == 'true' ? data.isInstall = true : data.isInstall = false;
-        let result = false;
-        data = this.filterLibData(data);
-        try {
-            let engineeringLib = await this.findDataByCondition({ _id: engineerId });
-            if (engineeringLib) {
-                // 存在则直接更新
-                delete data.id;
-                delete data.section;
-                let condition = { _id: engineerId };
-                result = await this.db.update(condition, data);
-                result = result.ok === 1;
-            } else {
-                throw new Error("找不到对应的工程专业");
-            }
-
-        } catch (error) {
-            console.log(error);
-            result = false;
-        }
-
-        return result;
+    return result;
+  }
+
+  /**
+   * 过滤计价数据
+   *
+   * @param {Object} data
+   * @return {Object}
+   */
+  filterLibData(data) {
+    if (Object.keys(data).length <= 0 || data.section === undefined) {
+      console.log("1");
+      throw "数据有误";
     }
-
-    /**
-     * 过滤计价数据
-     *
-     * @param {Object} data
-     * @return {Object}
-     */
-    filterLibData(data) {
-        if (Object.keys(data).length <= 0 || data.section === undefined) {
-            console.log('1');
-            throw '数据有误';
-        }
-        data.engineering = parseInt(data.engineering);
-        //需求修改,工程专业可以随便输入了
-        //检测专业工程是否合法
-        /*     let match = false;
+    data.engineering = parseInt(data.engineering);
+    //需求修改,工程专业可以随便输入了
+    //检测专业工程是否合法
+    /*     let match = false;
              for(let index in EngineeringConst) {
                  if (EngineeringConst[index] === data.engineering) {
                      match = true;
@@ -166,146 +173,162 @@ class EngineeringLibModel extends BaseModel {
                  throw '工程专业错误';
              }*/
 
-        // 判断标准清单
-        data.bill_lib = this._validLib(data.bill_lib);
+    // 判断标准清单
+    data.bill_lib = this._validLib(data.bill_lib);
 
-        // 判断定额库
-        data.ration_lib = this._validLib(data.ration_lib);
+    // 判断定额库
+    data.ration_lib = this._validLib(data.ration_lib);
 
-        //设置默认定额库
-        this.setDefaultRation(data);
+    //设置默认定额库
+    this.setDefaultRation(data);
 
-        // 判断工料机库
-        data.glj_lib = this._validLib(data.glj_lib);
+    // 判断工料机库
+    data.glj_lib = this._validLib(data.glj_lib);
 
-        // 判断清单指引库
-        data.billsGuidance_lib = this._validLib(data.billsGuidance_lib);
+    // 判断清单指引库
+    data.billsGuidance_lib = this._validLib(data.billsGuidance_lib);
 
-        /*// 判断费率标准
+    /*// 判断费率标准
         data.fee_lib = this._validLib(data.fee_lib);*/
 
-        // 判断人工系数
-        data.artificial_lib = this._validLib(data.artificial_lib);
+    // 判断人工系数
+    data.artificial_lib = this._validLib(data.artificial_lib);
 
-        //判断工程特征库
-        data.feature_lib = this._validLib(data.feature_lib);
+    //判断工程特征库
+    data.feature_lib = this._validLib(data.feature_lib);
 
-        //判断基本信息
-        data.info_lib = this._validLib(data.info_lib);
+    //判断基本信息
+    data.info_lib = this._validLib(data.info_lib);
 
-        //判断累进区间库
-        data.progressive_lib = this._validLib(data.progressive_lib);
+    //判断累进区间库
+    data.progressive_lib = this._validLib(data.progressive_lib);
 
-        //判断车船税
-        data.vvTax_lib = this._validLib(data.vvTax_lib);
+    //判断车船税
+    data.vvTax_lib = this._validLib(data.vvTax_lib);
 
-        //判断递延清单库
-        data.billCode_lib = this._validLib(data.billCode_lib);
+    //判断递延清单库
+    data.billCode_lib = this._validLib(data.billCode_lib);
 
-        //计税方式组合
-        data.tax_group = this._validLib(data.tax_group);
+    //计税方式组合
+    data.tax_group = this._validLib(data.tax_group);
 
-        return data;
-    }
+    return data;
+  }
 
-    /**
-     * 校验库数据
-     *
-     * @param {Object} libData
-     * @return {Object}
-     */
-    _validLib(libData) {
-        let result = [];
-        // 判断标准库
-        if (libData === undefined || libData === null || libData === '') {
-            return result;//throw '标准库不能为空'; 按新需求,标准库等不做非空判断
-        }
-        libData = libData instanceof Array ? libData : [libData];
-        for (let tmp in libData) {
-            result[tmp] = JSON.parse(libData[tmp]);
-        }
-        return result;
+  /**
+   * 校验库数据
+   *
+   * @param {Object} libData
+   * @return {Object}
+   */
+  _validLib(libData) {
+    let result = [];
+    // 判断标准库
+    if (libData === undefined || libData === null || libData === "") {
+      return result; //throw '标准库不能为空'; 按新需求,标准库等不做非空判断
     }
-
-    //设置默认定额库
-    setDefaultRation(data) {
-        if (data.ration_lib && data.ration_lib.length > 0) {
-            if (data.ration_isDefault && data.ration_isDefault != "") {
-                for (let r of data.ration_lib) {
-                    r.id.toString() == data.ration_isDefault ? r.isDefault = true : r.isDefault = false;
-                }
-            } else {
-                data.ration_lib[0].isDefault = true;
-            }
-        }
+    libData = libData instanceof Array ? libData : [libData];
+    for (let tmp in libData) {
+      result[tmp] = JSON.parse(libData[tmp]);
     }
-
-
-    /**
-     * 获取对应标准库数量
-     *
-     * @param {Object} valuationData
-     * @return {Object}
-     */
-    async getLibCount(valuationData) {
-        let result = {};
-        if (valuationData.engineering_list === undefined || valuationData.engineering_list.length <= 0) {
-            return result;
-        }
-
-        // 整理需要查找的数据
-        let findIdList = [];
-        for (let engineering of valuationData.engineering_list) {
-            findIdList.push(engineering.engineering_id);
-        }
-
-        let condition = { _id: { $in: findIdList } };
-        let libData = await this.findDataByCondition(condition, null, false);
-        if (libData === null) {
-            return result;
-        }
-
-        // 整理数据
-        let countData = {};
-        for (let tmp of libData) {
-            countData[tmp._id] = {
-                bill_count: tmp.bill_lib.length,
-                ration_count: tmp.ration_lib.length,
-                glj_count: tmp.glj_lib.length,
-                fee_count: tmp.fee_lib.length,
-                artificial_count: tmp.artificial_lib.length,
-                program_count: tmp.program_lib.length,
-            };
+    return result;
+  }
+
+  //设置默认定额库
+  setDefaultRation(data) {
+    if (data.ration_lib && data.ration_lib.length > 0) {
+      if (data.ration_isDefault && data.ration_isDefault != "") {
+        for (let r of data.ration_lib) {
+          r.id.toString() == data.ration_isDefault
+            ? (r.isDefault = true)
+            : (r.isDefault = false);
+          // 通过表单来识别那些定额库是专业版可用
+          data["ration_onlyProfession_" + r.id.toString()]
+            ? (r.onlyProfession = true)
+            : (r.onlyProfession = false);
         }
+      } else {
+        data.ration_lib[0].isDefault = true;
+      }
+    }
+  }
+
+  /**
+   * 获取对应标准库数量
+   *
+   * @param {Object} valuationData
+   * @return {Object}
+   */
+  async getLibCount(valuationData) {
+    let result = {};
+    if (
+      valuationData.engineering_list === undefined ||
+      valuationData.engineering_list.length <= 0
+    ) {
+      return result;
+    }
 
+    // 整理需要查找的数据
+    let findIdList = [];
+    for (let engineering of valuationData.engineering_list) {
+      findIdList.push(engineering.engineering_id);
+    }
 
-        for (let engineering of valuationData.engineering_list) {
-            if (countData[engineering.engineering_id] !== undefined) {
-                result[engineering.engineering] = countData[engineering.engineering_id];
-            }
-        }
+    let condition = { _id: { $in: findIdList } };
+    let libData = await this.findDataByCondition(condition, null, false);
+    if (libData === null) {
+      return result;
+    }
 
-        return result;
+    // 整理数据
+    let countData = {};
+    for (let tmp of libData) {
+      countData[tmp._id] = {
+        bill_count: tmp.bill_lib.length,
+        ration_count: tmp.ration_lib.length,
+        glj_count: tmp.glj_lib.length,
+        fee_count: tmp.fee_lib.length,
+        artificial_count: tmp.artificial_lib.length,
+        program_count: tmp.program_lib.length,
+      };
     }
 
-    async copyRationLibsToOthers(valuationID, engineeringID) {
-        const compilationModel = new CompilationModel();
-        const compilation = await compilationModel.model.findOne({ $or: [{ 'bill_valuation.id': valuationID }, { 'ration_valuation.id': valuationID }] });
-        if (!compilation) {
-            return;
-        }
-        const valuationIDList = [];
-        const allValuation = compilation.ration_valuation.concat(compilation.bill_valuation);
-        for (const valuation of allValuation) {
-            valuationIDList.push(valuation.id);
-        }
-        const engineering = await this.findDataByCondition({ _id: engineeringID });
-        if (!engineering) {
-            return;
-        }
-        await this.model.updateMany({ valuationID: { $in: valuationIDList } }, { $set: { ration_lib: engineering.ration_lib } });
+    for (let engineering of valuationData.engineering_list) {
+      if (countData[engineering.engineering_id] !== undefined) {
+        result[engineering.engineering] = countData[engineering.engineering_id];
+      }
     }
 
+    return result;
+  }
+
+  async copyRationLibsToOthers(valuationID, engineeringID) {
+    const compilationModel = new CompilationModel();
+    const compilation = await compilationModel.model.findOne({
+      $or: [
+        { "bill_valuation.id": valuationID },
+        { "ration_valuation.id": valuationID },
+      ],
+    });
+    if (!compilation) {
+      return;
+    }
+    const valuationIDList = [];
+    const allValuation = compilation.ration_valuation.concat(
+      compilation.bill_valuation
+    );
+    for (const valuation of allValuation) {
+      valuationIDList.push(valuation.id);
+    }
+    const engineering = await this.findDataByCondition({ _id: engineeringID });
+    if (!engineering) {
+      return;
+    }
+    await this.model.updateMany(
+      { valuationID: { $in: valuationIDList } },
+      { $set: { ration_lib: engineering.ration_lib } }
+    );
+  }
 }
 
 export default EngineeringLibModel;

+ 6 - 0
public/web/rpt_value_define.js

@@ -80,6 +80,8 @@ const JV = {
   PROP_HANDLE_TYPE_LAND_COMPS: "清单土地计算合并",
   PROP_HANDLE_TYPE_COST_TREE_BU_GLJ: "造价书插入补项工料机",
   PROP_HANDLE_TYPE_FLITE_XMJ_IS_BILL_BUDGET: "筛选清单预算项目节",
+  PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE: "干线公路汇总规则",
+  PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE: "干线公路汇总规则类型",
 
   PROP_ADJUST_COLLECTION: "数据调整集",
   PROP_ADJUST_ACTION: "action",
@@ -138,6 +140,8 @@ const JV = {
   PROP_FONT: "font",
   PROP_CONTROL: "control",
   PROP_STYLE: "style",
+  PROP_DIAGONAL_DOWN: "diagonal_down",
+  PROP_DIAGONAL_UP: "diagonal_up",
   PROP_VALUE: "Value",
   PROP_LABEL: "Label",
   PROP_AREA: "area",
@@ -221,6 +225,8 @@ const JV = {
 
   RUN_TYPE_BEFORE_GROUP_TEXT_OUT: "before_group_text_output",
 
+  RUN_TYPE_RESET_CROSS_COLUMNS: 'reset_cross_columns',
+
   PAGE_STATUS: [
     "EveryPage",
     "FirstPage",

+ 8 - 3
web/maintain/common/html/layout.html

@@ -20,9 +20,14 @@
     </nav>
     <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
         <ul class="nav navbar-nav px-1">
-            <li class="nav-item">
-                <a class="nav-link" href="javascript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#add">新建<%= title%></a>
-            </li>
+            <% if (typeof hideNav === 'undefined') { %>
+                <li class="nav-item">
+                    <a class="nav-link" href="javascript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#add">新建<%= title%></a>
+                </li>
+            <% } %>
+            <% if (typeof listItem !=='undefined') { %>
+                <%- listItem %>
+            <% } %>
         </ul>
     </nav>
 </div>

+ 21 - 1
web/maintain/price_info_lib/html/edit.html

@@ -27,13 +27,33 @@
                <div class="form-check" id="match-all">
                 <input class="form-check-input" type="checkbox" value="" id="match-all-input">
                 <label class="form-check-label" for="match-all-input" id="match-all-label">
-                  匹配所有
+                  匹配所有地区
                 </label>
               </div>
             </div>
 
         </nav>
     </div>
+
+    <div class="modal fade" id="batch-summary-dialog" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog" 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">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger">当前操作影响选中同省地区全部月份的信息价,是否继续?</h5>
+                </div>
+                <div class="modal-footer">
+                    <a id="confirm-batch-summary" href="javascript:void(0);" class="btn btn-danger">确认</a>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                </div>
+            </div>
+        </div>
+    </div>
     <div class="wrapper" style="overflow: hidden;">
         <div class="main">
             <div class="left">

+ 37 - 0
web/maintain/price_info_lib/html/main.html

@@ -230,6 +230,43 @@
     </div>
 </div>
 
+<div class="modal fade" id="export-zj" data-backdrop="static" style="display: none;" aria-hidden="true">
+    <div class="modal-dialog" 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">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="mb-3">导出期数:</div>
+                <div class="row">
+                    <div class="col-5 form-group">
+                        <input id="zj-period-start" class="form-control" name="from" placeholder="起始期数" type="text"
+                            value="" autocomplete="off">
+                    </div>
+                    <div class="col-2 form-group">
+                        <label class="split">——</label>
+                    </div>
+                    <div class="col-5 form-group">
+                        <input id="zj-period-end" class="form-control" name="to" placeholder="结束期数" type="text" value=""
+                            autocomplete="off">
+                    </div>
+                </div>
+                <div class="form-text text-danger" id="zj-error" style="display: none">请输入有效期数。</div>
+                <div style="color: gray">期数格式:2020-01、2020-12</div>
+                <div class="mt-3">导出地区:浙江省</div>
+            </div>
+            <div class="modal-footer">
+                <a id="export-zj-confirm" href="javascript: void(0);" class="btn btn-primary">确定</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+
 <script src="/public/web/lock_util.js"></script>
 <script src="/public/web/PerfectLoad.js"></script>
 <script src="/public/constants/price_info_constant.js"></script>

+ 2 - 1
web/maintain/price_info_lib/js/index.js

@@ -1,7 +1,8 @@
 $(document).ready(() => {
     console.log('进入信息价');
     $('[data-toggle="tooltip"]').tooltip();
-    AREA_BOOK.handleSelectionChanged(0);
+    // AREA_BOOK.handleSelectionChanged(0);
+    AREA_BOOK.init();
     const $range = $(document.body);
     lockUtil.lockTools($range, locked);
 });

+ 64 - 0
web/maintain/price_info_lib/js/main.js

@@ -144,6 +144,63 @@ function handleImportConfirm() {
     }
 }
 
+function getPeriodData(from, to) {
+    const monthMap = {
+        '1': '01月',
+        '2': '02月',
+        '3': '03月',
+        '4': '04月',
+        '5': '05月',
+        '6': '06月',
+        '7': '07月',
+        '8': '08月',
+        '9': '09月',
+        '10': '10月',
+        '11': '11月',
+        '12': '12月',
+    };
+    if (from > to) {
+        return null;
+    }
+    const reg = /(\d+)-(\d+)/;
+    const fromMatch = from.match(reg);
+    const fromYear = +fromMatch[1];
+    const fromMonth = +fromMatch[2];
+    const toMatch = to.match(reg);
+    const toYear = +toMatch[1];
+    const toMonth = +toMatch[2];
+    let curYear = fromYear;
+    let curMonth = fromMonth;
+    const periods = [];
+    while ((curYear <= toYear && curMonth <= toMonth) || curYear < toYear) {
+        periods.push(`${curYear}年-${monthMap[curMonth]}`);
+        if (curMonth === 12) {
+            curYear++;
+            curMonth = 1;
+        } else {
+            curMonth++;
+        }
+    }
+    return periods;
+}
+
+// 导出浙江信息价数据
+function handleExportZheJiangConfirm() {
+    const from = $('#zj-period-start').val();
+    const to = $('#zj-period-end').val();
+    if (!(periodReg.test(from) && periodReg.test(to)) && !(quaterReg.test(from) && quaterReg.test(to))) {
+        $('#zj-error').show();
+        return false;
+    }
+    const periods = getPeriodData(from, to);
+    if (!periods) {
+        $('#zj-error').show();
+        return false;
+    }
+    $('#export-zj').modal('hide');
+    window.location.href = `/priceInfo/exportZheJiangExcel?from=${from}&to=${to}`;
+}
+
 // 导出信息价库数据
 function handleExportInfoPriceByLib(libID) {
     setCurLib(libID);
@@ -269,6 +326,8 @@ $(document).ready(function () {
     $('#crawl-confirm').click(throttle(handleCrawlConfirm, throttleTime));
     // 导入excel
     $('#import-confirm').click(throttle(handleImportConfirm, throttleTime));
+    // 导出浙江
+    $('#export-zj-confirm').click(throttle(handleExportZheJiangConfirm, throttleTime))
 
     $('#add').on('hidden.bs.modal', () => {
         $('#name-error').hide();
@@ -276,6 +335,11 @@ $(document).ready(function () {
     });
     $('#edit').on('hidden.bs.modal', () => $('#rename-error').hide());
     $('#crawl').on('hidden.bs.modal', () => $('#crawl-error').hide());
+    $('#export-zj').on('hidden.bs.modal', () => {
+        $('#zj-error').hide()
+        $('#zj-period-start').val('');
+        $('#zj-period-end').val('');
+    });
 
     $('#export-compilation-price').click(() => {
         handleExportInfoPriceByCompilation();

+ 27 - 0
web/maintain/price_info_lib/js/priceArea.js

@@ -78,6 +78,15 @@ const AREA_BOOK = (() => {
     handleEdit(info.changedCells);
   }); */
 
+  const setCurAreaStorage = (curLibID, curAreaID) => {
+    window.localStorage.setItem(`priceArea:${curLibID}`, curAreaID);
+  };
+
+  const geCurAreaStorage = (curLibID) => {
+    const curAreaID = window.localStorage.getItem(`priceArea:${curLibID}`);
+    return curAreaID;
+  };
+
   const curArea = { ID: null, name: '' };
   // 焦点变更处理
   const debounceSelectionChanged = _.debounce(function (e, info) {
@@ -88,10 +97,25 @@ const AREA_BOOK = (() => {
     const areaItem = cache[row];
     curArea.ID = areaItem && areaItem.ID || null;
     curArea.name = areaItem && areaItem.name || '';
+    setCurAreaStorage(libID, curArea.ID);
     CLASS_BOOK.initData(libID, curArea.ID);
   }
   sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, debounceSelectionChanged);
 
+  // 第一次进来初始化显示
+  const init = () => {
+    const curAreaID = geCurAreaStorage(libID);
+    if (!curAreaID) {
+      handleSelectionChanged(0);
+      return;
+    }
+    let row = cache.findIndex(item => item.ID === curAreaID);
+    row = row >= 0 ? row : 0;
+    handleSelectionChanged(row);
+    sheet.setActiveCell(row, 1);
+    sheet.showCell(row, 0, GC.Spread.Sheets.VerticalPosition.center);
+  }
+
   // 新增
   async function insert() {
     const data = {
@@ -202,9 +226,12 @@ const AREA_BOOK = (() => {
   buildContextMenu();
 
   return {
+    init,
     handleSelectionChanged,
     curArea,
     cache,
+    setCurAreaStorage,
+    geCurAreaStorage
   }
 
 })();

+ 20 - 7
web/maintain/price_info_lib/js/priceClass.js

@@ -471,18 +471,22 @@ const CLASS_BOOK = (() => {
 
   }, DEBOUNCE_TIME, { leading: true }));
 
-  const doMatchSummary = async (libID, compilationID, areaID) => {
-    await ajaxPost('/priceInfo/matchSummary', { libID, compilationID, areaID }, 1000 * 60 * 10);
+  const doMatchSummary = async (libID, compilationID, areaID, matchAll) => {
+    await ajaxPost('/priceInfo/matchSummary', { libID, compilationID, areaID, matchAll }, 1000 * 60 * 10);
   }
 
   // 匹配总表
   $matchSummary.click(_.debounce(async () => {
+    const areaID = AREA_BOOK.curArea?.ID;
+    if (!areaID) {
+      alert('请选择地区');
+      return;
+    }
     $.bootstrapLoading.progressStart('匹配总表', true);
     $("#progress_modal_body").text('正在匹配总表,请稍后...');
     try {
-      const matchAll = $('#match-all-input')[0].checked;
-      const areaID = matchAll ? '' : AREA_BOOK.curArea?.ID;
-      await doMatchSummary(libID, compilationID, areaID);
+      const matchAll = Boolean($('#match-all-input')[0].checked);
+      await doMatchSummary(libID, compilationID, areaID, matchAll);
       setTimeout(() => {
         $.bootstrapLoading.progressEnd();
         window.location.reload()
@@ -495,13 +499,22 @@ const CLASS_BOOK = (() => {
   }, DEBOUNCE_TIME, { leading: true }));
 
   // 批量匹配总表
-  $batchMatchSummary.click(_.debounce(async () => {
+  $batchMatchSummary.click(() => {
+    $('#batch-summary-dialog').modal('show');
+  })
+  $('#confirm-batch-summary').click(_.debounce(async () => {
+    const areaID = AREA_BOOK.curArea?.ID;
+    if (!areaID) {
+      alert('请选择地区');
+      return;
+    }
+    $('#batch-summary-dialog').modal('hide');
     $.bootstrapLoading.progressStart('批量匹配总表', true);
     try {
       const libs = await ajaxPost('/priceInfo/getAllLibs');
       for (const lib of libs) {
         $("#progress_modal_body").text(`${lib.name},正在匹配总表,请稍后(${libs.indexOf(lib) + 1}/${libs.length})...`);
-        await doMatchSummary(lib.ID, lib.compilationID, '');
+        await doMatchSummary(lib.ID, lib.compilationID, areaID, true);
         await setTimeoutSync(() => { }, 100);
       }
       await setTimeoutSync(() => {

+ 3 - 3
web/maintain/price_info_lib/js/priceEmpty.js

@@ -102,9 +102,9 @@ const EMPTY_BOOK = (() => {
     curRow = 0;
     $.bootstrapLoading.start();
     try {
-      const matchAll = $('#match-all-input')[0].checked;
-      const areaID = matchAll ? '' : AREA_BOOK.curArea?.ID;
-      totalData = await ajaxPost('/priceInfo/getPriceEmptyData', { libID, compilationID, areaID }, 1000 * 60 * 10);
+      const matchAll = Boolean($('#match-all-input')[0].checked);
+      const areaID = AREA_BOOK.curArea?.ID;
+      totalData = await ajaxPost('/priceInfo/getPriceEmptyData', { libID, compilationID, areaID, matchAll }, 1000 * 60 * 10);
       setTotalMap(totalData);
       const tableData = getTableData(totalData);
       cache.push(...tableData)

+ 2 - 1
web/maintain/price_info_lib/js/priceItem.js

@@ -40,7 +40,8 @@ const PRICE_BOOK = (() => {
     $.bootstrapLoading.start();
     try {
       cache = await ajaxPost('/priceInfo/getPriceData', { classIDList }, 1000 * 60 * 10);
-      cache = _.sortBy(cache, 'classCode');
+      // cache = _.sortBy(cache, 'classCode');
+      // cache = _.sortBy(cache, 'code');
       showData(sheet, cache, setting.header, 5);
       const row = sheet.getActiveRowIndex();
       const keywordList = cache[row] && cache[row].keywordList || [];

+ 17 - 4
web/maintain/report/html/rpt_tpl_dtl_field_loc.html

@@ -86,22 +86,35 @@
                     <label>边框样式</label>
                     <select class="form-control" id="elementBorders" onchange="rpt_tpl_cfg_helper.borderChange(this)"></select>
                 </div>
-                <div class="form-group col-md-2">
+                <div class="form-group col-md-1">
                     <label>左边</label>
                     <input class="form-control input-sm" id="eleBorderLeft" type="number" value="0" step="1" min="0" max="3" disabled>
                 </div>
-                <div class="form-group col-md-2">
+                <div class="form-group col-md-1">
                     <label>右边</label>
                     <input class="form-control input-sm" id="eleBorderRight" type="number" value="0" step="1" min="0" max="3" disabled>
                 </div>
-                <div class="form-group col-md-2">
+                <div class="form-group col-md-1">
                     <label>上边</label>
                     <input class="form-control input-sm" id="eleBorderTop" type="number" value="0" step="1" min="0" max="3" disabled>
                 </div>
-                <div class="form-group col-md-2">
+                <div class="form-group col-md-1">
                     <label>下边</label>
                     <input class="form-control input-sm" id="eleBorderBottom" type="number" value="0" step="1" min="0" max="3" disabled>
                 </div>
+                <div class="form-group col-md-2">
+                    <label>斜线样式</label>
+                    <div class="form-check">
+                        <label class="form-check-label">
+                            <input type="checkbox" class="form-check-input" id="eleDiagonalDown" onchange="rpt_tpl_cfg_helper.diagonalDownChange(this)">
+                            下坡式
+                        </label>&nbsp&nbsp
+                        <label class="form-check-label">
+                            <input type="checkbox" class="form-check-input" id="eleDiagonalUp" onchange="rpt_tpl_cfg_helper.diagonalUpChange(this)">
+                            上坡式
+                        </label>&nbsp&nbsp
+                    </div>
+                </div>
             </div>
             <div class="row" id="element_control">
                 <div class="form-group col-md-2">

+ 11 - 0
web/maintain/report/html/rpt_tpl_dtl_info.html

@@ -135,9 +135,11 @@
                         <option value="complexConstruct">跨项目汇总对比(3个建设项目,一对多对多)</option>
                         <option value="complexConstructMultiple">各阶段项目对比(3个建设项目,多对多对多)</option>
                         <option value="complexSelfConstructMultiple">各阶段项目对比(当前建设项目对本阶段对其他阶段)</option>
+                        <option value="complexSelfConstructGlj">各阶段项目人材机对比(当前建设项目对本阶段对其他阶段)</option>
                         <option value="businessSummary">多个业务汇总</option>
                         <option value="changeProjectSummary">变更业务对比汇总</option>
                         <option value="changeProjectGljSummary">变更业务工料机对比汇总</option>
+                        <option value="compareConstruct">对比建设项目</option>
                     </select>
                     <label class="form-check-label" id="outputDesignDataBar" style="display: none;">
                         <input onchange="zTreeOprObj.onChangeFlag('outputDesignData', this)"  id="outputDesignData" type="checkbox">输出设计清单
@@ -201,6 +203,7 @@
                     <option value="NA">N/A</option>
                     <!-- <option value="audit_compare">审核对比</option> -->
                     <option value="project_compare">步骤对比</option>
+                    <option value="costUnitCompare">造价审核记录对比</option>
                 </select>
 
             </div>
@@ -220,6 +223,14 @@
                    
                 </select>
             </div>
+            <div class="input-group col-2">
+                <div class="input-group-addon">报表格式</div>
+                <select class="form-control input-sm" id="report_format_adjustable"
+                    onchange="zTreeOprObj.onChangeFlag('rptFormatAdjust', this)">
+                    <option value="F">不可调</option>
+                    <option value="T">可调</option>
+                </select>
+            </div>
         </div>
         <p>
         <div class="form-group col-md-6">

+ 2 - 0
web/maintain/report/html/rpt_tpl_dtl_pre_hdl.html

@@ -35,6 +35,8 @@
             <%include ./rpt_tpl_dtl_pre_hdl_addDummy.html %>
             <!--工程量清单数据处理-->
             <%include ./rpt_tpl_dtl_pre_hdl_change_quantities_bills.html %>
+            <!--干线公路汇总规则数据处理-->
+            <%include ./rpt_tpl_dtl_pre_hdl_arterial_highway_rule.html%>
         </div>
     </div>
 </div>

+ 15 - 0
web/maintain/report/html/rpt_tpl_dtl_pre_hdl_arterial_highway_rule.html

@@ -0,0 +1,15 @@
+<div id="div_arterial_highway_rule_bar">
+    <div class="form-group row" id="div_arterial_highway_rule">
+        <div class="input-group col-5">
+            <div class="input-group-addon">汇总规则</div>
+            <select class="form-control input-sm" id="select_arterial_highway_rule"
+                onchange="preHandleArterialHighwayRuleObj.onArterialHighwayRuleChange(this)">
+                <option value="constructID">建设项目</option>
+                <option value="constructionUnitsAndRoadTechniqueGrade">养护管理单位名称和公路等级</option>
+                <option value="roadTechniqueGrade">公路技术等级</option>
+                <option value="routeName">养护路线名称</option>
+                <option value="constructionUnits">养护管理单位名称</option>
+            </select>
+        </div>
+    </div>
+</div>

+ 21 - 0
web/maintain/report/js/jpc_output.js

@@ -313,6 +313,24 @@ let JpcCanvasOutput = {
             }
             return rst;
         }
+        function privateDrawDiagonal(cell) {
+            if (cell.diagonal_down) {
+                ctx.beginPath();
+                ctx.moveTo(cell.area.Left + JpcCanvasOutput.offsetX, cell.area.Top + JpcCanvasOutput.offsetY);
+                ctx.lineWidth = 1;
+                ctx.strokeStyle = 'BLACK';
+                ctx.lineTo(cell.area.Right + JpcCanvasOutput.offsetX, cell.area.Bottom + JpcCanvasOutput.offsetY);
+                ctx.stroke();
+            }
+            if (cell.diagonal_up) {
+                ctx.beginPath();
+                ctx.moveTo(cell.area.Left + JpcCanvasOutput.offsetX, cell.area.Bottom + JpcCanvasOutput.offsetY);
+                ctx.lineWidth = 1;
+                ctx.strokeStyle = 'BLACK';
+                ctx.lineTo(cell.area.Right + JpcCanvasOutput.offsetX, cell.area.Top + JpcCanvasOutput.offsetY);
+                ctx.stroke();
+            }
+        }
         function private_drawCell(cell, fonts, styles, controls, mergedBand) {
             ctx.save();
             ctx.translate(0.5,0.5);
@@ -324,6 +342,9 @@ let JpcCanvasOutput = {
                 private_drawLine(cell, ctx, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles, isNeedMergeBand);
                 private_drawLine(cell, ctx, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles, isNeedMergeBand);
             }
+            if (cell.diagonal_down || cell.diagonal_up) {
+                privateDrawDiagonal(cell);
+            }
             private_drawCellText(cell, fonts, controls);
             ctx.restore();
         }

+ 210 - 167
web/maintain/report/js/rpt_tpl_calculation.js

@@ -3,176 +3,219 @@
  */
 
 let calculationTreeOprObj = {
-    treeObj : null,
-    extCodeTreeObj: null,
-    currentNode: null,
-    currentExtCodeNode: null,
-    iniTree: function(rptTpl) {
-        var me = this;
-        let fieldMapList = me.buildTreeData(rptTpl);
-        me.treeObj = $.fn.zTree.init($("#rpt_tpl_formulas"), caculationSetting, fieldMapList);
-        me.treeObj.expandAll(true);
-        $("#exprDetail")[0].style.display = "none";
-    },
-    iniExtCodeTpl: function () {
-        let me = this, params = {};
-        CommonAjax.postEx("report_tpl_api/getExtCodeTpl", params, 10000, true, function(result){
-            me.extCodeTreeObj = $.fn.zTree.init($("#rpt_ext_code_tpl"), extCodeSetting, result);
-            let nodes = me.extCodeTreeObj.getNodes();
-            for (let node of nodes) {
-                me.extCodeTreeObj.expandNode(node, true, false);
-            }
-            // me.extCodeTreeObj.expandAll(true);
-            }, null, null
+  treeObj: null,
+  extCodeTreeObj: null,
+  currentNode: null,
+  currentExtCodeNode: null,
+  iniTree: function (rptTpl) {
+    var me = this;
+    let fieldMapList = me.buildTreeData(rptTpl);
+    me.treeObj = $.fn.zTree.init(
+      $("#rpt_tpl_formulas"),
+      caculationSetting,
+      fieldMapList
+    );
+    me.treeObj.expandAll(true);
+    $("#exprDetail")[0].style.display = "none";
+  },
+  iniExtCodeTpl: function () {
+    let me = this,
+      params = {};
+    CommonAjax.postEx(
+      "report_tpl_api/getExtCodeTpl",
+      params,
+      10000,
+      true,
+      function (result) {
+        me.extCodeTreeObj = $.fn.zTree.init(
+          $("#rpt_ext_code_tpl"),
+          extCodeSetting,
+          result
         );
-    },
-    buildRunType: function() {
-        let et = $("#exprRunType");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_PAGING + "'>默认运行</option>");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_OUTPUT + "'>每页实时运行</option>");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_ANALYZING + "'>数据分析前运行</option>");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_COMBINE + "'>合并单元格前事件</option>");
-        et.append("<option value='" + JV.RUN_TYPE_AFTER_COMBINE + "'>合并单元格后事件</option>");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_GROUP_TEXT_OUT + "'>分组text输出前事件</option>");
-    },
-    buildTreeData: function (rptTpl) {
-        let me = this, rst = {"Name": "计算式", items: []};
-        if (rptTpl[JV.NODE_FORMULAS]) {
-            for (let cItem of rptTpl[JV.NODE_FORMULAS]) {
-                let node = {};
-                me.copyContent(cItem, node);
-                node[JV.PROP_NAME] = cItem[JV.PROP_NAME];
-                node[JV.PROP_RUN_TYPE] = cItem[JV.PROP_RUN_TYPE];
-                node[JV.PROP_EXPRESSION] = cItem[JV.PROP_EXPRESSION];
-                node["format"] = (cItem["format"])?cItem["format"]:"";
-                rst.items.push(node);
-            }
+        let nodes = me.extCodeTreeObj.getNodes();
+        for (let node of nodes) {
+          me.extCodeTreeObj.expandNode(node, true, false);
         }
-        return rst;
-    },
-    copyContent: function(source, target) {
-        target[JV.PROP_NAME] = source[JV.PROP_NAME];
-        target[JV.PROP_RUN_TYPE] = source[JV.PROP_RUN_TYPE];
-        target[JV.PROP_EXPRESSION] = source[JV.PROP_EXPRESSION];
-        target["format"] = (source["format"])?source["format"]:"";
-    },
-    changeRunType: function (dom) {
-        let me = calculationTreeOprObj;
-        if (me.currentNode) {
-            me.currentNode[JV.PROP_RUN_TYPE] = dom.value;
-        }
-    },
-    setExtCodeTemplate: function (dom) {
-        let me = calculationTreeOprObj;
-        if (me.currentExtCodeNode && me.currentExtCodeNode["Template"] !== '') {
-            $("#exprContent")[0].value = me.currentExtCodeNode["Template"];
-            editor2.setValue($("#exprContent")[0].value);
-        }
-    },
-    addExtCodeTemplate: function (dom) {
-        let me = calculationTreeOprObj;
-        if (me.currentExtCodeNode && me.currentExtCodeNode["Template"] !== '') {
-            $("#exprContent")[0].value += me.currentExtCodeNode["Template"];
-            editor2.setValue($("#exprContent")[0].value);
-        }
-    },
-    changeFormat: function (dom) {
-        let me = calculationTreeOprObj;
-        if (me.currentNode) {
-            me.currentNode["format"] = dom.value;
-        }
-    },
-    changeExpression: function (dom) {
-        let me = calculationTreeOprObj;
-        if (me.currentNode) {
-            me.currentNode[JV.PROP_EXPRESSION] = dom.value;
-        }
-    },
-    onClick: function (event,treeId,treeNode) {
-        let me = calculationTreeOprObj;
-        me.currentNode = treeNode;
-        if (treeNode.level === 0) {
-            $("#exprDetail")[0].style.display = "none";
-        } else {
-            $("#exprDetail")[0].style.display = "";
-            if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_PAGING) {
-                $("#exprRunType")[0].selectedIndex = 0;
-            } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_OUTPUT) {
-                $("#exprRunType")[0].selectedIndex = 1;
-            } else {
-                $("#exprRunType")[0].selectedIndex = 2;
-            }
-            $("#exprFormat")[0].value = (treeNode["format"])?treeNode["format"]:"";
-            $("#exprContent")[0].value = treeNode[JV.PROP_EXPRESSION];
-            editor2.setValue($("#exprContent")[0].value);
-        }
-    },
-    onExtCodeTreeClick: function (event, treeId, treeNode) {
-        let me = calculationTreeOprObj;
-        me.currentExtCodeNode = treeNode;
-    },
-    onBeforeRemove: function(treeId, treeNode){
-        let rst = false;
-        if (treeNode.level > 0) {
-            rst = confirm('请确认是否真的删除?');
-        }
-        return rst;
-    },
-    beforeRename: function(treeId, treeNode, newName, isCancel) {
-        if (isCancel) {
-            return true;
-        }
-        if (treeNode.level === 0) {
-            return false;
-        }
-        return true;
-    },
-    onBeforeDrop: function (treeId, treeNodes, targetNode, moveType) {
-        let rst = false;
-        if (targetNode.level === 1 && (moveType === "next" || moveType === "prev")) {
-            return true;
-        }
-        return rst;
-    },
-    addHoverDom: function(treeId, treeNode) {
-        let me = calculationTreeOprObj, sObj = $("#" + treeNode.tId + "_span");
-        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0 || treeNode.level > 0) {
-            return;
-        } else {
-            let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增' onfocus='this.blur();'></span>";
-            sObj.after(addStr);
-            let btn = $("#addBtn_"+treeNode.tId);
-            btn.bind("click", function(){
-                let newNodes = [], node = {};
-                node[JV.PROP_NAME] = "新计算式";
-                node[JV.PROP_RUN_TYPE] = JV.RUN_TYPE_BEFORE_PAGING;
-                node[JV.PROP_EXPRESSION] = "";
-                node["format"] = "";
-                newNodes.push(node);
-                me.treeObj.addNodes(treeNode, -1, newNodes, true);
-            });
-        }
-    },
-    removeHoverDom: function(treeId, treeNode) {
-        $("#addBtn_"+treeNode.tId).unbind().remove();
-    },
-    extractCalculation: function (rptTpl) {
-        let me = this, newCaclList = [];
-        let topNode = me.treeObj.getNodes()[0];
-        for (let node of topNode.items) {
-            let item = {};
-            me.copyContent(node, item);
-            newCaclList.push(item);
-        }
-        rptTpl[JV.NODE_FORMULAS] = newCaclList;
+        // me.extCodeTreeObj.expandAll(true);
+      },
+      null,
+      null
+    );
+  },
+  buildRunType: function () {
+    let et = $("#exprRunType");
+    et.append(`<option value="${JV.RUN_TYPE_BEFORE_PAGING}">默认运行</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_BEFORE_OUTPUT}">每页实时运行</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_BEFORE_ANALYZING}">数据分析前运行</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_BEFORE_COMBINE}">合并单元格前事件</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_AFTER_COMBINE}">合并单元格后事件</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_BEFORE_GROUP_TEXT_OUT}">分组text输出前事件</option>`);
+    et.append(`<option value="${JV.RUN_TYPE_RESET_CROSS_COLUMNS}">重设交叉表列数</option>`);
+  },
+  buildTreeData: function (rptTpl) {
+    let me = this,
+      rst = { Name: "计算式", items: [] };
+    if (rptTpl[JV.NODE_FORMULAS]) {
+      for (let cItem of rptTpl[JV.NODE_FORMULAS]) {
+        let node = {};
+        me.copyContent(cItem, node);
+        node[JV.PROP_NAME] = cItem[JV.PROP_NAME];
+        node[JV.PROP_RUN_TYPE] = cItem[JV.PROP_RUN_TYPE];
+        node[JV.PROP_EXPRESSION] = cItem[JV.PROP_EXPRESSION];
+        node["format"] = cItem["format"] ? cItem["format"] : "";
+        rst.items.push(node);
+      }
+    }
+    return rst;
+  },
+  copyContent: function (source, target) {
+    target[JV.PROP_NAME] = source[JV.PROP_NAME];
+    target[JV.PROP_RUN_TYPE] = source[JV.PROP_RUN_TYPE];
+    target[JV.PROP_EXPRESSION] = source[JV.PROP_EXPRESSION];
+    target["format"] = source["format"] ? source["format"] : "";
+  },
+  changeRunType: function (dom) {
+    let me = calculationTreeOprObj;
+    if (me.currentNode) {
+      me.currentNode[JV.PROP_RUN_TYPE] = dom.value;
     }
-}
+  },
+  setExtCodeTemplate: function (dom) {
+    let me = calculationTreeOprObj;
+    if (me.currentExtCodeNode && me.currentExtCodeNode["Template"] !== "") {
+      $("#exprContent")[0].value = me.currentExtCodeNode["Template"];
+      editor2.setValue($("#exprContent")[0].value);
+    }
+  },
+  addExtCodeTemplate: function (dom) {
+    let me = calculationTreeOprObj;
+    if (me.currentExtCodeNode && me.currentExtCodeNode["Template"] !== "") {
+      $("#exprContent")[0].value += me.currentExtCodeNode["Template"];
+      editor2.setValue($("#exprContent")[0].value);
+    }
+  },
+  changeFormat: function (dom) {
+    let me = calculationTreeOprObj;
+    if (me.currentNode) {
+      me.currentNode["format"] = dom.value;
+    }
+  },
+  changeExpression: function (dom) {
+    let me = calculationTreeOprObj;
+    if (me.currentNode) {
+      me.currentNode[JV.PROP_EXPRESSION] = dom.value;
+    }
+  },
+  onClick: function (event, treeId, treeNode) {
+    let me = calculationTreeOprObj;
+    me.currentNode = treeNode;
+    if (treeNode.level === 0) {
+      $("#exprDetail")[0].style.display = "none";
+    } else {
+      $("#exprDetail")[0].style.display = "";
+      if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_PAGING) {
+        $("#exprRunType")[0].selectedIndex = 0;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_OUTPUT) {
+        $("#exprRunType")[0].selectedIndex = 1;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_ANALYZING) {
+        $("#exprRunType")[0].selectedIndex = 2;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_COMBINE) {
+        $("#exprRunType")[0].selectedIndex = 3;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_AFTER_COMBINE) {
+        $("#exprRunType")[0].selectedIndex = 4;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_GROUP_TEXT_OUT) {
+        $("#exprRunType")[0].selectedIndex = 5;
+      } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_RESET_CROSS_COLUMNS) {
+        $("#exprRunType")[0].selectedIndex = 6;
+      } else {
+        $("#exprRunType")[0].selectedIndex = 2;
+      }
+      $("#exprFormat")[0].value = treeNode["format"] ? treeNode["format"] : "";
+      $("#exprContent")[0].value = treeNode[JV.PROP_EXPRESSION];
+      editor2.setValue($("#exprContent")[0].value);
+    }
+  },
+  onExtCodeTreeClick: function (event, treeId, treeNode) {
+    let me = calculationTreeOprObj;
+    me.currentExtCodeNode = treeNode;
+  },
+  onBeforeRemove: function (treeId, treeNode) {
+    let rst = false;
+    if (treeNode.level > 0) {
+      rst = confirm("请确认是否真的删除?");
+    }
+    return rst;
+  },
+  beforeRename: function (treeId, treeNode, newName, isCancel) {
+    if (isCancel) {
+      return true;
+    }
+    if (treeNode.level === 0) {
+      return false;
+    }
+    return true;
+  },
+  onBeforeDrop: function (treeId, treeNodes, targetNode, moveType) {
+    let rst = false;
+    if (
+      targetNode.level === 1 &&
+      (moveType === "next" || moveType === "prev")
+    ) {
+      return true;
+    }
+    return rst;
+  },
+  addHoverDom: function (treeId, treeNode) {
+    let me = calculationTreeOprObj,
+      sObj = $("#" + treeNode.tId + "_span");
+    if (
+      treeNode.editNameFlag ||
+      $("#addBtn_" + treeNode.tId).length > 0 ||
+      treeNode.level > 0
+    ) {
+      return;
+    } else {
+      let addStr =
+        "<span class='button add' id='addBtn_" +
+        treeNode.tId +
+        "' title='新增' onfocus='this.blur();'></span>";
+      sObj.after(addStr);
+      let btn = $("#addBtn_" + treeNode.tId);
+      btn.bind("click", function () {
+        let newNodes = [],
+          node = {};
+        node[JV.PROP_NAME] = "新计算式";
+        node[JV.PROP_RUN_TYPE] = JV.RUN_TYPE_BEFORE_PAGING;
+        node[JV.PROP_EXPRESSION] = "";
+        node["format"] = "";
+        newNodes.push(node);
+        me.treeObj.addNodes(treeNode, -1, newNodes, true);
+      });
+    }
+  },
+  removeHoverDom: function (treeId, treeNode) {
+    $("#addBtn_" + treeNode.tId)
+      .unbind()
+      .remove();
+  },
+  extractCalculation: function (rptTpl) {
+    let me = this,
+      newCaclList = [];
+    let topNode = me.treeObj.getNodes()[0];
+    for (let node of topNode.items) {
+      let item = {};
+      me.copyContent(node, item);
+      newCaclList.push(item);
+    }
+    rptTpl[JV.NODE_FORMULAS] = newCaclList;
+  },
+};
 
 $(document).ready(function () {
-    editor2.on('change', function () {
-        let me = calculationTreeOprObj;
-        if (me.currentNode) {
-            me.currentNode[JV.PROP_EXPRESSION] = editor2.getValue();
-        }
-    });
+  editor2.on("change", function () {
+    let me = calculationTreeOprObj;
+    if (me.currentNode) {
+      me.currentNode[JV.PROP_EXPRESSION] = editor2.getValue();
+    }
+  });
 });

+ 9 - 0
web/maintain/report/js/rpt_tpl_cfg_helper.js

@@ -161,6 +161,9 @@ let rpt_tpl_cfg_helper = {
             idx = me.reportCfg.borderArr.indexOf(borderAttr);
             borderDom.selectedIndex = idx;
             me.borderChange(borderDom);
+            // 还有diagonal
+            $("#eleDiagonalDown").get(0).checked = stringUtil.convertStrToBoolean(treeNode[JV.PROP_DIAGONAL_DOWN]);
+            $("#eleDiagonalUp").get(0).checked = stringUtil.convertStrToBoolean(treeNode[JV.PROP_DIAGONAL_UP]);
             //setup control
             let ctrlDom = $("#elementControls").get(0);
             let ctrlAttr = treeNode[JV.PROP_CONTROL];
@@ -358,6 +361,12 @@ let rpt_tpl_cfg_helper = {
             }
         }
     },
+    diagonalUpChange: function(dom) {
+        dataInfoMapTreeOprObj.currentNode[JV.PROP_DIAGONAL_UP] = dom.checked?'T':'F';
+    },
+    diagonalDownChange: function(dom) {
+        dataInfoMapTreeOprObj.currentNode[JV.PROP_DIAGONAL_DOWN] = dom.checked?'T':'F';
+    },
     controlChange: function(dom) {
         if (dataInfoMapTreeOprObj.currentNode) {
             let me = this, ctrlAttr = dom.value;

+ 4 - 0
web/maintain/report/js/rpt_tpl_data_map.js

@@ -693,6 +693,8 @@ let dataInfoMapTreeOprObj = {
     destination[JV.PROP_FONT] = source[JV.PROP_FONT];
     destination[JV.PROP_CONTROL] = source[JV.PROP_CONTROL];
     destination[JV.PROP_STYLE] = source[JV.PROP_STYLE];
+    if (source[JV.PROP_DIAGONAL_DOWN]) destination[JV.PROP_DIAGONAL_DOWN] = source[JV.PROP_DIAGONAL_DOWN];
+    if (source[JV.PROP_DIAGONAL_UP]) destination[JV.PROP_DIAGONAL_UP] = source[JV.PROP_DIAGONAL_UP];
     destination[JV.PROP_PREFIX] = source[JV.PROP_PREFIX];
     destination[JV.PROP_SUFFIX] = source[JV.PROP_SUFFIX];
     if (source[JV.PROP_FORMAT])
@@ -779,6 +781,8 @@ let dataInfoMapTreeOprObj = {
     destination[JV.PROP_FONT] = source[JV.PROP_FONT];
     destination[JV.PROP_CONTROL] = source[JV.PROP_CONTROL];
     destination[JV.PROP_STYLE] = source[JV.PROP_STYLE];
+    if (source[JV.PROP_DIAGONAL_DOWN]) destination[JV.PROP_DIAGONAL_DOWN] = source[JV.PROP_DIAGONAL_DOWN];
+    if (source[JV.PROP_DIAGONAL_UP]) destination[JV.PROP_DIAGONAL_UP] = source[JV.PROP_DIAGONAL_UP];
     destination.Title = "";
     destination[JV.PROP_AREA] = {};
     me.private_copy_area(source[JV.PROP_AREA], destination[JV.PROP_AREA]);

+ 24 - 3
web/maintain/report/js/rpt_tpl_main.js

@@ -519,6 +519,10 @@ let zTreeOprObj = {
     let me = zTreeOprObj;
     zTreeOprObj.treeObj.checkNode(treeNodes[0], false, false);
     treeNodes[0].released = false;
+    // 拷贝后的uuid重复的问题
+    if (isCopy) {
+      treeNodes[0].UUID = `${new Date().getTime()}_${me.generateRandomString()}`;
+    }
     let targetTopNode = me.getParentNodeByNodeLevel(
       targetNode,
       NODE_LEVEL_COMPILATION_NEW
@@ -1297,12 +1301,16 @@ let zTreeOprObj = {
                   $("#element_sumLv_flags")[0].selectedIndex = 14;
                 else if (sumLvType === "complexSelfConstructMultiple")
                   $("#element_sumLv_flags")[0].selectedIndex = 15;
-                else if (sumLvType === "businessSummary")
+                else if (sumLvType === "complexSelfConstructGlj")
                   $("#element_sumLv_flags")[0].selectedIndex = 16;
-                else if (sumLvType === "changeProjectSummary")
+                else if (sumLvType === "businessSummary")
                   $("#element_sumLv_flags")[0].selectedIndex = 17;
-                else if (sumLvType === "changeProjectGljSummary")
+                else if (sumLvType === "changeProjectSummary")
                   $("#element_sumLv_flags")[0].selectedIndex = 18;
+                else if (sumLvType === "changeProjectGljSummary")
+                  $("#element_sumLv_flags")[0].selectedIndex = 19;
+                else if (sumLvType === "compareConstruct")
+                  $("#element_sumLv_flags")[0].selectedIndex = 20;
                 else {
                   $("#element_sumLv_flags")[0].selectedIndex = 0;
                 }
@@ -1378,6 +1386,8 @@ let zTreeOprObj = {
                 let val = me.currentNode.flags["auditType"];
                 if (val === "project_compare") {
                   $("#element_constructSumFlags_audit")[0].selectedIndex = 1;
+                } else if (val === "costUnitCompare") {
+                  $("#element_constructSumFlags_audit")[0].selectedIndex = 2;
                 } else {
                   $("#element_constructSumFlags_audit")[0].selectedIndex = 0;
                 }
@@ -1396,6 +1406,16 @@ let zTreeOprObj = {
               } else {
                 $("#element_costIndexFlags_audit")[0].selectedIndex = 0;
               }
+              if (me.currentNode.flags.hasOwnProperty("rptFormatAdjust")) {
+                let rType = me.currentNode.flags["rptFormatAdjust"];
+                if (rType === "T") {
+                  $("#report_format_adjustable")[0].selectedIndex = 1;
+                } else {
+                  $("#report_format_adjustable")[0].selectedIndex = 0;
+                }
+              } else {
+                $("#report_format_adjustable")[0].selectedIndex = 0;
+              }
             } else {
               $("#element_flags_select")[0].selectedIndex = 0;
               $("#element_prjFlags_select")[0].selectedIndex = 0;
@@ -1410,6 +1430,7 @@ let zTreeOprObj = {
               $("#element_Flags_tplType")[0].selectedIndex = 0;
               $("#element_costIndexFlags_audit")[0].selectedIndex = 0;
               $("#select_aid_report_data_select")[0].selectedIndex = 0;
+              $("#report_format_adjustable")[0].selectedIndex = 0;
             }
 
             if (

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

@@ -255,6 +255,16 @@ const exposed_bills_properties = [
     Order: "ascend",
     individualType: fixed_bills_special_provisional_types,
   },
+  {
+    Name: "清单_是否标准清单",
+    Title: "",
+    Key: "isStdBill",
+    Order: "ascend",
+    individualType: [
+      { Name: "是(1)", Title: "", Value: "1" },
+      { Name: "否(0)", Title: "", Value: "0" },
+    ],
+  },
 ];
 const exposed_ration_properties = [
   { Name: "定额_工程内部ID", Title: "", Key: "ID", Order: "ascend" },
@@ -467,7 +477,10 @@ let preHandleObj = {
       Name: JV.PROP_HANDLE_TYPE_FLITE_XMJ_IS_BILL_BUDGET,
       Title: "",
     });
-    types.push({ Name: JV.PROP_HANDLE_TYPE_BIND_AID_REPORT, Title: "" });
+    types.push({
+      Name: JV.PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE,
+      Title: "",
+    });
 
     // types.push({Name: "纯手工填写", Title: ""});
     me.typeTreeObj = $.fn.zTree.init(
@@ -601,7 +614,7 @@ let preHandleObj = {
           预处理类型: preHandleType,
         };
         break;
-      case JV.PROP_HANDLE_TYPE_BIND_AID_REPORT:
+      case JV.PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE:
         rst = {
           Name: "预处理环节",
           Title: "",
@@ -668,6 +681,9 @@ let preHandleObj = {
         break;
       case JV.PROP_HANDLE_TYPE_FLITE_XMJ_IS_BILL_BUDGET:
         break;
+      case JV.PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE:
+        item[JV.PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE] = "constructID"; // 工程量清单排序
+        break;
       default:
         item[JV.PROP_HANDLE_TYPE] = JV.PROP_HANDLE_TYPE_SORT;
         item[JV.PROP_SORT_TYPE] = "normal";
@@ -695,6 +711,11 @@ let preHandleObj = {
       src[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_CHANGE_QUANTITIES_BILLS
     ) {
       preHandleQuantitiesBillsSortObj.copyNode(src, dest);
+    } else if (
+      src[JV.PROP_HANDLE_TYPE] ===
+      JV.PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE
+    ) {
+      preHandleArterialHighwayRuleObj.copyNode(src, dest);
     }
   },
   private_set_title: function (node) {
@@ -744,6 +765,8 @@ let preHandleObj = {
           preHandleAddDummyObj.refresh_node();
         } else if (typeNode[JV.PROP_NAME] === "转化工程量清单") {
           preHandleQuantitiesBillsSortObj.refresh_node();
+        } else if (typeNode[JV.PROP_NAME] === "干线公路汇总规则") {
+          preHandleArterialHighwayRuleObj.refresh_node();
         }
       }
     }
@@ -761,6 +784,7 @@ let preHandleObj = {
     $("#div_sort_tree")[0].style.display = "none";
     $("#div_sort_self_define")[0].style.display = "none";
     $("#div_quantities_bills_sort_bar")[0].style.display = "none";
+    $("#div_arterial_highway_rule_bar")[0].style.display = "none";
   },
   onPreHandleClick: function (event, treeId, treeNode) {
     //点击预处理环节 节点
@@ -942,6 +966,11 @@ let preHandleObj = {
           case JV.PROP_HANDLE_TYPE_FLITE_XMJ_IS_BILL_BUDGET:
             rst.push(preHandleBillDataMoveObj.extractTabFields(handleObj));
             break;
+          case JV.PROP_HANDLE_TYPE_FLITE_ARTERIAL_HIGHWAY_RULE:
+            rst.push(
+              preHandleArterialHighwayRuleObj.extractTabFields(handleObj)
+            );
+            break;
           default:
             break;
         }
@@ -1880,6 +1909,37 @@ let preHandleQuantitiesBillsSortObj = {
       dom.value;
   },
 };
+// 干线公路汇总规则
+let preHandleArterialHighwayRuleObj = {
+  copyNode: function (src, dest) {
+    dest[JV.PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE] = src.combileRule;
+  },
+  refresh_node: function () {
+    $("#div_arterial_highway_rule_bar")[0].style.display = "";
+    if (preHandleObj.currentNode) {
+      $("#select_arterial_highway_rule")[0].value =
+        preHandleObj.currentNode[JV.PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE] ||
+        "constructID";
+    }
+  },
+  extractTabFields: function (handleObj) {
+    let me = preHandleArterialHighwayRuleObj,
+      rst = {};
+    me.copyNode(handleObj, rst);
+    rst = {
+      预处理类型: "干线公路汇总规则",
+      映射数据对象: "bills",
+      combileRule: handleObj[JV.PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE],
+    };
+    return rst;
+  },
+  onArterialHighwayRuleChange: function (dom) {
+    // 工程量清单排序类型
+    let me = preHandleObj;
+    me.currentNode[JV.PROP_HANDLE_TYPE_ARTERIAL_HIGHWAY_RULE] = dom.value;
+  },
+};
+
 let preHandleFXGLJObj = {
   copyNode: function (src, dest) {
     //

+ 29 - 1
web/maintain/std_glj_lib/html/gongliao.html

@@ -257,6 +257,34 @@
         </div>
     </div>
 
+    <div class="modal fade" id="edit-code" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog" 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">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+
+                    <form>
+                        <div class="form-group row" style="margin-left: 0px;">
+                            <label class="col-auto col-form-label" id="edit-label" style="line-height: 26px;">编号</label>
+                            <div class="col">
+                                <input id="edit-code-text" class="form-control" placeholder="请输入编号" type="text" value="">
+                            </div>
+                        </div>
+                    </form>
+                </div>
+                <div class="modal-footer">
+                    <a id="edit-code-confirm" href="javascript: void(0);" class="btn btn-primary">确定</a>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <!-- JS. -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/jquery-contextmenu/jquery.contextMenu.min.js"></script>
@@ -393,4 +421,4 @@
     autoFlashHeight();
 </script>
 
-</html>
+</html>

+ 64 - 12
web/maintain/std_glj_lib/js/glj.js

@@ -475,7 +475,7 @@ let repositoryGljObj = {
             me.rationLibs = result.data[0].rationLibs;
             $(".navbar-text").append(
               "<a href='/stdGljRepository/main'>人材机库</a><i class='fa fa-angle-right fa-fw'></i>" +
-                result.data[0].dispName
+              result.data[0].dispName
             );
             pageOprObj.gljLibName = result.data[0].dispName;
           }
@@ -849,6 +849,7 @@ let repositoryGljObj = {
     if (row < me.currentCache.length) {
       //标记当前工料机
       me.currentGlj = me.currentCache[row];
+      console.log(me.currentGlj);
       if (allowComponent.includes(me.currentCache[row].gljType)) {
         //展示数据
         if (me.currentGlj.component.length > 0) {
@@ -1434,6 +1435,33 @@ let repositoryGljObj = {
         false
       );
   },
+  editCode: async function () {
+    const sheet = this.workBook.getSheet(0);
+    const row = sheet.getActiveRowIndex();
+    const glj = this.currentCache[row];
+    if (!glj) {
+      alert('请选中工料机!');
+      $('#edit-code').modal('hide');
+      return;
+    }
+    const newCode = $('#edit-code-text').val();
+    if (!newCode) {
+      alert('编号不可为空!');
+      $('#edit-code-text').focus();
+      return;
+    }
+    if (this.gljList.some(item => item.ID !== glj.ID && item.code === newCode)) {
+      alert('编号已存在!');
+      $('#edit-code-text').focus();
+      return;
+    }
+    if (newCode === glj.code) {
+      $('#edit-code').modal('hide');
+      return;
+    }
+    this.mixUpdateRequest([{ ...glj, code: newCode }], [], []);
+    $('#edit-code').modal('hide');
+  },
   onContextmenuOpr: function () {
     let me = repositoryGljObj;
     $.contextMenu({
@@ -1468,8 +1496,23 @@ let repositoryGljObj = {
             sheet.setActiveCell(target.row, target.col);
           }
           return {
-            callback: function () {},
+            callback: function () { },
             items: {
+              edit: {
+                name: "修改编号",
+                disabled: function () {
+                  return (
+                    locked || !(me.currentCache && me.currentCache[target.row])
+                  );
+                },
+                icon: "fa-edit",
+                callback: function (key, opt) {
+                  if (me.currentCache[target.row]) {
+                    $('#edit-code').modal('show');
+                    $('#edit-code-text').val(me.currentCache[target.row].code || '');
+                  }
+                },
+              },
               delete: {
                 name: "删除",
                 disabled: function () {
@@ -1813,8 +1856,8 @@ let repositoryGljObj = {
     if (!priceProperties || priceProperties.length === 0) {
       pasteObj.basePrice =
         !isNaN(parseFloat(pasteObj.basePrice)) &&
-        pasteObj.basePrice &&
-        typeof pasteObj.basePrice !== "undefined"
+          pasteObj.basePrice &&
+          typeof pasteObj.basePrice !== "undefined"
           ? parseFloat(pasteObj.basePrice)
           : 0;
     } else {
@@ -1933,7 +1976,7 @@ let repositoryGljObj = {
         info.cellRange.colCount >= 5 &&
         info.cellRange.colCount <= me.setting.header.length &&
         info.cellRange.col + info.cellRange.colCount - 1 >=
-          me.colMapping.fieldToCol["gljType"]
+        me.colMapping.fieldToCol["gljType"]
       ) {
         for (let i = 0; i < items.length; i++) {
           if (me.isValidObj(items[i])) {
@@ -2320,7 +2363,7 @@ let gljTypeTreeOprObj = {
           pNode.isParent = false;
         }
       },
-      error: function () {},
+      error: function () { },
     });
     return true;
   },
@@ -2358,7 +2401,7 @@ let gljTypeTreeOprObj = {
         success: function (result, textStatus, status) {
           console.log(status + " : " + result);
         },
-        error: function () {},
+        error: function () { },
       });
     }
   },
@@ -2429,10 +2472,10 @@ let gljTypeTreeOprObj = {
         btn.bind("click", function () {
           treeNode.doing = true;
           let rawNode = {
-              ParentID: treeNode.ID,
-              NextSiblingID: -1,
-              Name: "新增子节点",
-            },
+            ParentID: treeNode.ID,
+            NextSiblingID: -1,
+            Name: "新增子节点",
+          },
             lastNodeId = -1;
           if (treeNode.items.length > 0) {
             lastNodeId = treeNode.items[treeNode.items.length - 1].ID;
@@ -2535,7 +2578,7 @@ $(document).ready(function () {
     },
     function () {
       let resizeRate =
-          (SlideResize.resizeWidth * 100) / $("#midContent").width(),
+        (SlideResize.resizeWidth * 100) / $("#midContent").width(),
         sheetRate = 100 - resizeRate;
       $("#slideResizeLeft").css("width", `${resizeRate}%`);
       $("#GLJListSheet").css("width", `${sheetRate}%`);
@@ -2572,4 +2615,13 @@ $(document).ready(function () {
     repositoryGljObj.mixUpdateRequest(updateArr, [], []);
     $("#moveTo").modal("hide");
   });
+
+  // 修改编号弹窗
+  $('#edit-code').on('shown.bs.modal', function () {
+    $('#edit-code-text').focus();
+  });
+
+  $('#edit-code-confirm').click(async () => {
+    await repositoryGljObj.editCode();
+  });
 });

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

@@ -228,11 +228,15 @@ $(document).ready(function () {
       const tem = {
         id: rationLib,
         name: rationLibString,
+        onlyProfession: false,
         isDefault: false,
       };
       htmlString += ` 
                 <tr class='ration_tr' draggable="true">
                     <td><span class="cursor-default">${tem.name}</span></td>
+                     <td><label class="form-check-label"> <input class="form-check-input" name="ration_onlyProfession"  value="${
+                       tem.id
+                     }" type="checkbox"></td> 
                     <td><label class="form-check-label"> <input class="form-check-input" name="ration_isDefault"  value="${
                       tem.id
                     }" type="radio"></td>  

+ 10 - 0
web/users/views/compilation/engineering.html

@@ -252,6 +252,7 @@
                                 <thead>
                                 <tr>
                                     <th>定额库名称</th>
+                                    <th>仅专业版可用</th>
                                     <th>默认</th>
                                     <th>操作</th>
                                 </tr>
@@ -263,6 +264,15 @@
                                     <td>
                                         <span class="cursor-default"><%= ration.name%></span>
                                     </td>
+                                    <td> 
+                                        <label class="form-check-label">
+                                            <% if(ration.onlyProfession==true){%>
+                                                <input  class="form-check-input"  name="ration_onlyProfession_<%= ration.id %>" type="checkbox" checked  value="<%= ration.id %>"> 
+                                            <% }else{ %>
+                                                <input  class="form-check-input"   name="ration_onlyProfession_<%= ration.id %>" type="checkbox"  value="<%= ration.id %>"> 
+                                            <% } %>
+                                        </label>
+                                    </td>
                                     <td>
                                         <label class="form-check-label">
                                             <% if(ration.isDefault == true){%>