Browse Source

广东接口相关

vian 5 years ago
parent
commit
78414b2b40

+ 18 - 7
modules/pm/facade/pm_facade.js

@@ -1586,15 +1586,18 @@ async function importProject(importObj, userID, compilationID) {
     }
     }
     //给单位工程设置一些数据
     //给单位工程设置一些数据
     async function setupTender(data) {
     async function setupTender(data) {
-        //小数位数 需要修改,所以深拷贝
-        data.property.decimal = JSON.parse(JSON.stringify(defaultDecimal));
-        // 定额工程量、人材机消耗量精度设为最大6
-        data.property.decimal.ration.quantity = 6;
-        data.property.decimal.glj.quantity = 6;
+        if (!data.property.decimal) {     
+            //小数位数 需要修改,所以深拷贝
+            data.property.decimal = JSON.parse(JSON.stringify(defaultDecimal));
+            // 定额工程量、人材机消耗量精度设为最大6
+            data.property.decimal.ration.quantity = 6;
+            data.property.decimal.glj.quantity = 6;
+        }
         //清单工程量精度 需要修改,所以深拷贝
         //清单工程量精度 需要修改,所以深拷贝
         data.property.billsQuantityDecimal = JSON.parse(JSON.stringify(billsQuantityDecimal));
         data.property.billsQuantityDecimal = JSON.parse(JSON.stringify(billsQuantityDecimal));
-        // 清单工程量精度设置最大4
-        data.property.billsQuantityDecimal.forEach(data => data.decimal = 4);
+        // 清单工程量精度默认为4
+        const billsQuantityDecimalValue = data.property.billsQuantityDecimalValue || 4;
+        data.property.billsQuantityDecimal.forEach(data => data.decimal = billsQuantityDecimalValue);
         //呈现选项
         //呈现选项
         data.property.displaySetting = displaySetting;
         data.property.displaySetting = displaySetting;
 
 
@@ -1661,6 +1664,10 @@ async function importTenderDetail(tenderData) {
     if (tenderData.bills.length) {
     if (tenderData.bills.length) {
         await billsModel.insertMany(tenderData.bills);
         await billsModel.insertMany(tenderData.bills);
     }
     }
+    // 工程量明细
+    if (tenderData.quantityDetails.length) {
+        await quantityDetailModel.insertMany(tenderData.quantityDetails);
+    }
     //投标文件中,才会有下面这些数据
     //投标文件中,才会有下面这些数据
     if (enterDetail(tenderData)) {
     if (enterDetail(tenderData)) {
         //匹配标准数据,更新一些标准数据
         //匹配标准数据,更新一些标准数据
@@ -1747,6 +1754,7 @@ async function setupStdData(tenderData) {
             r.stdID = stdRation.ID;
             r.stdID = stdRation.ID;
             r.prefix = stdRation.rationRepId == tenderData.tender.defaultRationLib ? '' : '借';
             r.prefix = stdRation.rationRepId == tenderData.tender.defaultRationLib ? '' : '借';
             r.content = stdRation.jobContent;
             r.content = stdRation.jobContent;
+            r.manageFeeRate = stdRation.manageFeeRate;
             if (stdRation.feeType) {
             if (stdRation.feeType) {
                 r.programID = stdRation.feeType;
                 r.programID = stdRation.feeType;
             } else {
             } else {
@@ -1808,6 +1816,9 @@ async function setupStdData(tenderData) {
             up.glj_id = stdGLJ.ID;
             up.glj_id = stdGLJ.ID;
             up.type = stdGLJ.gljType;
             up.type = stdGLJ.gljType;
             up.short_name = stdGLJ.shortName;
             up.short_name = stdGLJ.shortName;
+            if (stdGLJ.taxRate) {
+                up.taxRate = stdGLJ.taxRate;
+            }
         }
         }
     });
     });
     //更新组成物数据
     //更新组成物数据

+ 56 - 52
web/over_write/js/guangdong_2018.js

@@ -159,55 +159,59 @@ if (typeof gljOprObj !== 'undefined') {
 // 需要用固定类别关联的费用字典,用固定类别来映射
 // 需要用固定类别关联的费用字典,用固定类别来映射
 // 数据节选自标准pdf文件《《建设工程政府投资项目造价数据标准》信息公开版》,附录C-费用名称与费用代号
 // 数据节选自标准pdf文件《《建设工程政府投资项目造价数据标准》信息公开版》,附录C-费用名称与费用代号
 // 若映射表中没有映射关系,则费用字典取名称首字母
 // 若映射表中没有映射关系,则费用字典取名称首字母
-const FlagFeeCodeMap = {
-    // 分部分项工程
-    [commonConstants.fixedFlag.SUB_ENGINERRING]: 'QDF',
-    // 措施项目
-    [commonConstants.fixedFlag.MEASURE]: 'CSF',
-    // 其他项目
-    [commonConstants.fixedFlag.OTHER]: 'QTF',
-    // 措施项目的子项
-    [commonConstants.fixedFlag.GREEN_MEASURE_FEE]: 'AQWMSGF', // 绿色施工安全防护措施费
-    [commonConstants.fixedFlag.OTHER_MEASURE_FEE]: 'QTCSF', // 其他措施费
-    // 其他项目的子项
-    [commonConstants.fixedFlag.PROVISIONAL]: 'ZLF', // 暂列金额
-    [commonConstants.fixedFlag.ESTIMATE]: 'ZGJ', // 暂估价
-    [commonConstants.fixedFlag.MATERIAL_PROVISIONAL]: 'ZGC', // 材料(工程设备)暂估价
-    [commonConstants.fixedFlag.ENGINEERING_ESITIMATE]: 'ZGGC', // 专业工程暂估价
-    [commonConstants.fixedFlag.DAYWORK]: 'LXF', // 计日工
-    [commonConstants.fixedFlag.TURN_KEY_CONTRACT]: 'ZCBFWF', // 总承包服务费
-    [commonConstants.fixedFlag.BUDGET_INCLUDE_WORK_FEE]: 'YSBGF', // 预算包干费
-    [commonConstants.fixedFlag.PROJECT_HIGH_QUALITY_FEE]: 'GCYZF', // 工程优质费
-    [commonConstants.fixedFlag.BUDGET_ESTIMATE_DIFF]: 'GSFDC', // 概算幅度差
-    [commonConstants.fixedFlag.CLAIM_VISA]: 'SPYXCQZ', // 索赔与现场签证
-    [commonConstants.fixedFlag.CLAIM]: 'SPFY', // 索赔费用
-    [commonConstants.fixedFlag.VISA]: 'XCQZFY', // 现场签证
-    [commonConstants.fixedFlag.OTHER_FEE]: 'QTFY', // 其他费用
-    // 税金
-    [commonConstants.fixedFlag.TAX]: 'SJ',
-    // 工程造价
-    [commonConstants.fixedFlag.ENGINEERINGCOST]: 'ZZJ',
-};
-// 需要用计算基数关联的费用字典
-const FormulaFeeCodeMap = {
-    '{分部分项工程费}': 'QDF',
-    '{分部分项人工费}': 'QRG',
-    '{分部分项材料费}': 'QCL',
-    '{分部分项施工机具费}': 'QJX',
-    '{分部分项主材费}': 'QZCF',
-    '{分部分项设备费}': 'QSBF',
-    '{分部分项人工工日}': 'FBFXRGGR', // 标准没有,自增
-    '{建筑面积}': 'JZMZ', // 自增
-    '{措施项目费}': 'CSF',
-    '{其他项目费}': 'QTF',
-    '{甲供人工费}': 'JGRGF', // 自增
-    '{甲供材料费}': 'JGC',
-    '{甲供施工机具费}': 'JGSGJJF', // 自增
-    '{甲定人工费}': 'JDRGF', // 自增
-    '{甲定材料费}': 'JDCLF', // 自增
-    '{甲定施工机具费}': 'JDSGJJF', // 自增
-    '{甲定主材费}': 'JDZCF', // 自增
-    '{甲定设备费}': 'JDSBF', // 自增
-    '{暂估材料费(从子目汇总)}': 'ZGCLFCZMHZ', // 自增
-    '{税金}': 'SJ',
-};
+let FlagFeeCodeMap = {};
+let FormulaFeeCodeMap = {};
+if (typeof commonConstants !== 'undefined') {
+    FlagFeeCodeMap = {
+        // 分部分项工程
+        [commonConstants.fixedFlag.SUB_ENGINERRING]: 'QDF',
+        // 措施项目
+        [commonConstants.fixedFlag.MEASURE]: 'CSF',
+        // 其他项目
+        [commonConstants.fixedFlag.OTHER]: 'QTF',
+        // 措施项目的子项
+        [commonConstants.fixedFlag.GREEN_MEASURE_FEE]: 'AQWMSGF', // 绿色施工安全防护措施费
+        [commonConstants.fixedFlag.OTHER_MEASURE_FEE]: 'QTCSF', // 其他措施费
+        // 其他项目的子项
+        [commonConstants.fixedFlag.PROVISIONAL]: 'ZLF', // 暂列金额
+        [commonConstants.fixedFlag.ESTIMATE]: 'ZGJ', // 暂估价
+        [commonConstants.fixedFlag.MATERIAL_PROVISIONAL]: 'ZGC', // 材料(工程设备)暂估价
+        [commonConstants.fixedFlag.ENGINEERING_ESITIMATE]: 'ZGGC', // 专业工程暂估价
+        [commonConstants.fixedFlag.DAYWORK]: 'LXF', // 计日工
+        [commonConstants.fixedFlag.TURN_KEY_CONTRACT]: 'ZCBFWF', // 总承包服务费
+        [commonConstants.fixedFlag.BUDGET_INCLUDE_WORK_FEE]: 'YSBGF', // 预算包干费
+        [commonConstants.fixedFlag.PROJECT_HIGH_QUALITY_FEE]: 'GCYZF', // 工程优质费
+        [commonConstants.fixedFlag.BUDGET_ESTIMATE_DIFF]: 'GSFDC', // 概算幅度差
+        [commonConstants.fixedFlag.CLAIM_VISA]: 'SPYXCQZ', // 索赔与现场签证
+        [commonConstants.fixedFlag.CLAIM]: 'SPFY', // 索赔费用
+        [commonConstants.fixedFlag.VISA]: 'XCQZFY', // 现场签证
+        [commonConstants.fixedFlag.OTHER_FEE]: 'QTFY', // 其他费用
+        // 税金
+        [commonConstants.fixedFlag.TAX]: 'SJ',
+        // 工程造价
+        [commonConstants.fixedFlag.ENGINEERINGCOST]: 'ZZJ',
+    };
+    // 需要用计算基数关联的费用字典
+    FormulaFeeCodeMap = {
+        '{分部分项工程费}': 'QDF',
+        '{分部分项人工费}': 'QRG',
+        '{分部分项材料费}': 'QCL',
+        '{分部分项施工机具费}': 'QJX',
+        '{分部分项主材费}': 'QZCF',
+        '{分部分项设备费}': 'QSBF',
+        '{分部分项人工工日}': 'FBFXRGGR', // 标准没有,自增
+        '{建筑面积}': 'JZMZ', // 自增
+        '{措施项目费}': 'CSF',
+        '{其他项目费}': 'QTF',
+        '{甲供人工费}': 'JGRGF', // 自增
+        '{甲供材料费}': 'JGC',
+        '{甲供施工机具费}': 'JGSGJJF', // 自增
+        '{甲定人工费}': 'JDRGF', // 自增
+        '{甲定材料费}': 'JDCLF', // 自增
+        '{甲定施工机具费}': 'JDSGJJF', // 自增
+        '{甲定主材费}': 'JDZCF', // 自增
+        '{甲定设备费}': 'JDSBF', // 自增
+        '{暂估材料费(从子目汇总)}': 'ZGCLFCZMHZ', // 自增
+        '{税金}': 'SJ',
+    };
+}

+ 20 - 19
web/over_write/js/guangdong_2018_export.js

@@ -545,7 +545,7 @@ const XMLStandard = (function () {
                 // 总说明 编制说明
                 // 总说明 编制说明
                 {
                 {
                     name: 'Explains',
                     name: 'Explains',
-                    value: projectData.property.compilationIllustrationProject
+                    value: projectData.property.compilationIllustration
                 }
                 }
             ];
             ];
             //唯一约束
             //唯一约束
@@ -1493,7 +1493,7 @@ const XMLStandard = (function () {
         function ExpressElement(quantityDetail) {
         function ExpressElement(quantityDetail) {
             const attrs = [
             const attrs = [
                 // 序号
                 // 序号
-                { name: 'OrderNumber', dName: '序号', required: true, value: quantityDetail.name },
+                { name: 'OrderNumber', dName: '序号', required: true, value: quantityDetail.seq },
                 // 工程量计算式
                 // 工程量计算式
                 { name: 'Express', dName: '工程量计算式', required: true, value: quantityDetail.regex },
                 { name: 'Express', dName: '工程量计算式', required: true, value: quantityDetail.regex },
                 // 工程量
                 // 工程量
@@ -1515,7 +1515,11 @@ const XMLStandard = (function () {
             _base.Element.call(this, 'WorkContent', attrs, '工序内容');
             _base.Element.call(this, 'WorkContent', attrs, '工序内容');
         }
         }
         // 定额子目
         // 定额子目
-        function Norm(ration, libCode, kind, specialty) {
+        function Norm(ration, libCode, kind) {
+            // 通过定额库编码,读取编码中间的数字,如房建定额库编码是“GD 1 2018",工程专业取“1”。
+            const reg = /GD (\d+)/;
+            const matched = libCode.match(reg);
+            const specialty = matched && matched[1] || '1';
             const attrs = [
             const attrs = [
                 // 定额编码
                 // 定额编码
                 { name: 'Number', dName: '定额编码', required: true, value: ration.code },
                 { name: 'Number', dName: '定额编码', required: true, value: ration.code },
@@ -1649,9 +1653,6 @@ const XMLStandard = (function () {
         // 其他项目费明细
         // 其他项目费明细
         function SundryCostsItem(node) {
         function SundryCostsItem(node) {
             const bills = node.data;
             const bills = node.data;
-            if (bills.name === '材料暂估价') {
-                debugger;
-            }
             const attrs = [
             const attrs = [
                 // 名称
                 // 名称
                 { name: 'Name', dName: '名称', required: true, value: bills.name },
                 { name: 'Name', dName: '名称', required: true, value: bills.name },
@@ -1951,9 +1952,11 @@ const XMLStandard = (function () {
                 { name: 'NoTaxOrgPrice', type: _type.DECIMAL, value: price.basePrice },
                 { name: 'NoTaxOrgPrice', type: _type.DECIMAL, value: price.basePrice },
                 // 除税编制价(市场价)
                 // 除税编制价(市场价)
                 { name: 'NoTaxPrice', type: _type.DECIMAL, value: price.marketPrice },
                 { name: 'NoTaxPrice', type: _type.DECIMAL, value: price.marketPrice },
-                // 含税定额价 不存在这个字段,输出"0"
-                { name: 'TaxOrgPrice', type: _type.DECIMAL, value: '0' },
-                // 含税编制价 暂时取市场价
+                // 含税定额价 含税与不含税是对应项目的计税方式(一般、简易)
+                // 人材机含税和不含税的数据在项目创建时就确定,并且都赋在一个属性上
+                // 因此导出都取项目中的basePriceh额marketPrice就行
+                { name: 'TaxOrgPrice', type: _type.DECIMAL, value: price.basePrice },
+                // 含税编制价 
                 { name: 'TaxPrice', type: _type.DECIMAL, value: price.marketPrice },
                 { name: 'TaxPrice', type: _type.DECIMAL, value: price.marketPrice },
                 // 引进部分
                 // 引进部分
                 { name: 'ForeignCurrency', type: _type.DECIMAL, value: '0' },
                 { name: 'ForeignCurrency', type: _type.DECIMAL, value: '0' },
@@ -2193,7 +2196,6 @@ const XMLStandard = (function () {
                     await _util.setTimeoutSync(() => { }, _config.TIMEOUT_TIME);
                     await _util.setTimeoutSync(() => { }, _config.TIMEOUT_TIME);
                 }
                 }
                 // 获取单位工程详细数据
                 // 获取单位工程详细数据
-                debugger;
                 tenderDetail = await _util.getTenderDetail(tData.ID, userID);
                 tenderDetail = await _util.getTenderDetail(tData.ID, userID);
                 // 先计算人材机总消耗量,以供后面需要
                 // 先计算人材机总消耗量,以供后面需要
                 gljUtil.calcProjectGLJQuantity(tenderDetail.projectGLJ.datas,
                 gljUtil.calcProjectGLJQuantity(tenderDetail.projectGLJ.datas,
@@ -2393,7 +2395,7 @@ const XMLStandard = (function () {
                 .entries(workMap)
                 .entries(workMap)
                 .map(([contentText, rationNodes]) => {
                 .map(([contentText, rationNodes]) => {
                     const workContent = new WorkContent(contentText, _util.getAggregateFee(rationNodes));
                     const workContent = new WorkContent(contentText, _util.getAggregateFee(rationNodes));
-                    workContent.children = rationNodes.map(node => loadRation(node, kind, specialty));
+                    workContent.children = rationNodes.map(node => loadRation(node, kind));
                     return workContent;
                     return workContent;
                 });
                 });
             workElement.children.push(...workContents);
             workElement.children.push(...workContents);
@@ -2402,7 +2404,7 @@ const XMLStandard = (function () {
 
 
         // 加载工程量计算表
         // 加载工程量计算表
         function loadQuantityExpressions(quantityDetails, isBills, ID) {
         function loadQuantityExpressions(quantityDetails, isBills, ID) {
-            if (quantityDetails.length) {
+            if (!quantityDetails.length) {
                 return [];
                 return [];
             }
             }
             quantityDetails.sort((a, b) => a.seq - b.seq);
             quantityDetails.sort((a, b) => a.seq - b.seq);
@@ -2418,10 +2420,10 @@ const XMLStandard = (function () {
             return theLib ? theLib.libCode : '';
             return theLib ? theLib.libCode : '';
         }
         }
         // 加载定额
         // 加载定额
-        function loadRation(node, kind, specialty) {
+        function loadRation(node, kind) {
             // 定额
             // 定额
             const libCode = getLibCode(node.data, tenderDetail.projectInfo.engineeringInfo.ration_lib);
             const libCode = getLibCode(node.data, tenderDetail.projectInfo.engineeringInfo.ration_lib);
-            const norm = new Norm(node.data, libCode, kind, specialty);
+            const norm = new Norm(node.data, libCode, kind);
             // 工程量计算表
             // 工程量计算表
             const expressElement = loadQuantityExpressions(tenderDetail.quantity_detail.datas, false, node.data.ID);
             const expressElement = loadQuantityExpressions(tenderDetail.quantity_detail.datas, false, node.data.ID);
             if (expressElement.length) {
             if (expressElement.length) {
@@ -2436,15 +2438,15 @@ const XMLStandard = (function () {
             let rationGLJs = tenderDetail.ration_glj.datas.filter(rGLJ => rGLJ.rationID === node.data.ID);
             let rationGLJs = tenderDetail.ration_glj.datas.filter(rGLJ => rGLJ.rationID === node.data.ID);
             rationGLJs = gljUtil.sortRationGLJ(rationGLJs); // 定额人材机排序
             rationGLJs = gljUtil.sortRationGLJ(rationGLJs); // 定额人材机排序
             const rationGLJElements = rationGLJs
             const rationGLJElements = rationGLJs
-                .filter(rGLJ => {
+                /* .filter(rGLJ => {
                     // 总消耗量为0的,不输出
                     // 总消耗量为0的,不输出
                     const totalQuantity = gljUtil.getTotalQuantity(rGLJ, node.data, Decimal.GLJ, Decimal.QUANTITY);
                     const totalQuantity = gljUtil.getTotalQuantity(rGLJ, node.data, Decimal.GLJ, Decimal.QUANTITY);
                     const parsedTotalQuantity = parseFloat(totalQuantity);
                     const parsedTotalQuantity = parseFloat(totalQuantity);
                     return parsedTotalQuantity;
                     return parsedTotalQuantity;
-                })
+                }) */
                 .map(rGLJ => {
                 .map(rGLJ => {
-                    const totalQuantity = gljUtil.getTotalQuantity(rGLJ, node.data, Decimal.GLJ, Decimal.QUANTITY);
-                    return new LabourMaterialsEquipmentsMachinesElement(rGLJ, totalQuantity)
+                    //const totalQuantity = gljUtil.getTotalQuantity(rGLJ, node.data, Decimal.GLJ, Decimal.QUANTITY);
+                    return new LabourMaterialsEquipmentsMachinesElement(rGLJ, rGLJ.quantity)
                 });
                 });
             norm.children.push(...rationGLJElements);
             norm.children.push(...rationGLJElements);
             // 子目单价计算(定额计算程序)
             // 子目单价计算(定额计算程序)
@@ -2487,7 +2489,6 @@ const XMLStandard = (function () {
 
 
             const sundry = new Sundry();
             const sundry = new Sundry();
             // 其他项目费
             // 其他项目费
-            debugger;
             const other = tenderDetail.mainTree.roots.find(node => node.getFlag() === fixedFlag.OTHER);
             const other = tenderDetail.mainTree.roots.find(node => node.getFlag() === fixedFlag.OTHER);
             const sundryCosts = new SundryItem('SundryCosts', other.data);
             const sundryCosts = new SundryItem('SundryCosts', other.data);
             sundryCosts.children = loadGroupAndItems(
             sundryCosts.children = loadGroupAndItems(

+ 105 - 21
web/over_write/js/guangdong_2018_import.js

@@ -56,6 +56,20 @@ const importXML = (() => {
         // 费率、指数、比例(%)类小数精度
         // 费率、指数、比例(%)类小数精度
         RATE: 3,
         RATE: 3,
     };
     };
+    // 根据上方精度要求得到的项目属性,小数位数的值
+    const tenderPropertyDecimal = {
+        bills: { unitPrice: Decimal.FEE, totalPrice: Decimal.FEE },
+        ration: { quantity: Decimal.QUANTITY, unitPrice: Decimal.FEE, totalPrice: Decimal.FEE },
+        glj: { quantity: Decimal.GLJ, unitPriceHasMix: Decimal.FEE, unitPrice: Decimal.FEE },
+        feeRate: Decimal.RATE,
+        quantity_detail: 4,
+        material: 5,//三材系数
+        process: 6
+    };
+    const tenderPropertyBillsQuantityDecimal = Decimal.QUANTITY;
+    // 工程量表达式相关
+    const GCLMXHj = 'GCLMXHJ';
+    const QDL = 'QDL';
 
 
     /* 
     /* 
      * 从导入的xml文件中提取有用的数据
      * 从导入的xml文件中提取有用的数据
@@ -74,7 +88,7 @@ const importXML = (() => {
             name: getValue(projectSrc, ['_Name']),
             name: getValue(projectSrc, ['_Name']),
             engs: extractEngs(projectSrc, xmlObjMap),
             engs: extractEngs(projectSrc, xmlObjMap),
             property: {
             property: {
-                compilationIllustrationProject: getValue(projectSrc, ['_Explains'])
+                compilationIllustration: getValue(projectSrc, ['_Explains'])
             },
             },
             basicInformation: extractBasicInfo(projectSrc)
             basicInformation: extractBasicInfo(projectSrc)
         };
         };
@@ -181,6 +195,7 @@ const importXML = (() => {
                 projType: projectType.Tender,
                 projType: projectType.Tender,
                 name: getValue(src, ['_Name']),
                 name: getValue(src, ['_Name']),
                 code: getValue(src, ['_Number']),
                 code: getValue(src, ['_Number']),
+                compilationIllustration: getValue(src, ['_Explains']),
                 engineering: getValue(src, ['_ProjectType']),
                 engineering: getValue(src, ['_ProjectType']),
                 projectFeature: extractProjectFeature(src),
                 projectFeature: extractProjectFeature(src),
                 workSummary: extractWorkSummary(src),
                 workSummary: extractWorkSummary(src),
@@ -293,15 +308,19 @@ const importXML = (() => {
             jobContent: getJobContent(workElementSrc),
             jobContent: getJobContent(workElementSrc),
             unit: getValue(workElementSrc, ['_Unit']),
             unit: getValue(workElementSrc, ['_Unit']),
             quantity: getValue(workElementSrc, ['_Quantity']),
             quantity: getValue(workElementSrc, ['_Quantity']),
-            feeRate: getValue(workElementSrc, ['_Rate']),
             mainBills: getBool(getValue(workElementSrc, ['_Major'])),
             mainBills: getBool(getValue(workElementSrc, ['_Major'])),
             feeCode: getValue(workElementSrc, ['_Code']),
             feeCode: getValue(workElementSrc, ['_Code']),
             remark: getValue(workElementSrc, ['_Remark']),
             remark: getValue(workElementSrc, ['_Remark']),
+            quantityDetails: extractQuantityDetails(workElementSrc),
             rations: extractRations(workElementSrc)
             rations: extractRations(workElementSrc)
         };
         };
         if (type === billType.BILL) {
         if (type === billType.BILL) {
-            // 分项不需要基数
+            // 分项不需要基数、费率
             bills.calcBase = getValue(workElementSrc, ['_QtyFormula']);
             bills.calcBase = getValue(workElementSrc, ['_QtyFormula']);
+            const feeRate = getValue(workElementSrc, ['_Rate']);
+            if (+feeRate) {
+                bills.feeRate = feeRate;
+            }
         }
         }
         // 投标和控制价,需要导入最高限价
         // 投标和控制价,需要导入最高限价
         if ([FileKind.tender, FileKind.control].includes(importFileKind)) {
         if ([FileKind.tender, FileKind.control].includes(importFileKind)) {
@@ -369,6 +388,15 @@ const importXML = (() => {
             }));
             }));
         }
         }
     }
     }
+    // 提取工程量明细(清单、定额底下都可能会有)
+    function extractQuantityDetails(src) {
+        return arrayValue(src, ['ExpressElement']).map(itemSrc => ({
+            seq: getValue(itemSrc, ['_OrderNumber']),
+            regex: getValue(itemSrc, ['_Express']),
+            result: getValue(itemSrc, ['_Quantity']),
+            isSummation: +getValue(itemSrc, ['_Kind'])
+        }));
+    }
     // 提取定额
     // 提取定额
     function extractRations(workElementSrc) {
     function extractRations(workElementSrc) {
         if (importFileKind !== FileKind.tender) {
         if (importFileKind !== FileKind.tender) {
@@ -458,6 +486,7 @@ const importXML = (() => {
             const feesFromCalcItem = getFeesFromCalculationOfItem(rationSrc);
             const feesFromCalcItem = getFeesFromCalculationOfItem(rationSrc);
             ration.fees = mergeFees(fees, feesFromCalcItem);
             ration.fees = mergeFees(fees, feesFromCalcItem);
             ration.rationGLJs = extractRationGLJs(rationSrc);
             ration.rationGLJs = extractRationGLJs(rationSrc);
+            ration.quantityDetails = extractQuantityDetails(rationSrc);
             return ration;
             return ration;
         }
         }
     }
     }
@@ -834,7 +863,10 @@ const importXML = (() => {
             gljLibIDs: tenderData.gljLibIDs,
             gljLibIDs: tenderData.gljLibIDs,
             shareInfo: []
             shareInfo: []
         };
         };
-        transformedTender.property.gljAdjustType = getAdjustType(tenderData)
+        transformedTender.property.compilationIllustration = tenderData.compilationIllustration;
+        transformedTender.property.gljAdjustType = getAdjustType(tenderData);
+        transformedTender.property.decimal = tenderPropertyDecimal;
+        transformedTender.property.billsQuantityDecimalValue = tenderPropertyBillsQuantityDecimal;
         detailData.tender = transformedTender;
         detailData.tender = transformedTender;
         return detailData;
         return detailData;
     }
     }
@@ -862,7 +894,6 @@ const importXML = (() => {
     }
     }
     // 合并清单,将提取出来的清单相关数据,合并进项目清单(模板)
     // 合并清单,将提取出来的清单相关数据,合并进项目清单(模板)
     function mergeBills(tenderData, billsTemplate) {
     function mergeBills(tenderData, billsTemplate) {
-        debugger;
         const mergedBills = [...billsTemplate];
         const mergedBills = [...billsTemplate];
         const roots = billsTemplate.filter(bills => bills.ParentID === -1);
         const roots = billsTemplate.filter(bills => bills.ParentID === -1);
         let lastRoot = roots.find(root => root.NextSiblingID === -1);
         let lastRoot = roots.find(root => root.NextSiblingID === -1);
@@ -924,6 +955,7 @@ const importXML = (() => {
         // 合并大项费用
         // 合并大项费用
         function mergeWorkSummary(workSummary) {
         function mergeWorkSummary(workSummary) {
             // 首层数据与清单模板根据费用字典进行匹配,匹配到的则赋值一些属性,匹配不到则将其及其所有子数据插入到模板最末大项费用
             // 首层数据与清单模板根据费用字典进行匹配,匹配到的则赋值一些属性,匹配不到则将其及其所有子数据插入到模板最末大项费用
+            debugger;
             workSummary.forEach(summaryBills => {
             workSummary.forEach(summaryBills => {
                 const matched = roots.find(root => FlagFeeCodeMap[getFlag(root)] === summaryBills.feeCode);
                 const matched = roots.find(root => FlagFeeCodeMap[getFlag(root)] === summaryBills.feeCode);
                 if (matched) {
                 if (matched) {
@@ -948,13 +980,13 @@ const importXML = (() => {
         // 合并措施项目
         // 合并措施项目
         function mergeCSXM(csxmSrc) {
         function mergeCSXM(csxmSrc) {
             const fixedBills = billsTemplate.find(bills => getFlag(bills) === fixedFlag.MEASURE);
             const fixedBills = billsTemplate.find(bills => getFlag(bills) === fixedFlag.MEASURE);
-            fixedBills.fees = csxmSrc.fees;
+            fixedBills.fees = mergeFees(fixedBills.fees, csxmSrc.fees);
             mergeitems(fixedBills, csxmSrc.items);
             mergeitems(fixedBills, csxmSrc.items);
         }
         }
         // 合并其他项目
         // 合并其他项目
         function mergeOther(otherSrc) {
         function mergeOther(otherSrc) {
             const fixedBills = billsTemplate.find(bills => getFlag(bills) === fixedFlag.OTHER);
             const fixedBills = billsTemplate.find(bills => getFlag(bills) === fixedFlag.OTHER);
-            fixedBills.fees = otherSrc.fees;
+            fixedBills.fees = mergeFees(fixedBills.fees, otherSrc.fees);
             // 合并其他项目费
             // 合并其他项目费
 
 
             // SundryCosts其他项目费会包含暂列金额等后续会再次出现的数据,因此合并SundryCosts的数据时,过滤掉一部分数据
             // SundryCosts其他项目费会包含暂列金额等后续会再次出现的数据,因此合并SundryCosts的数据时,过滤掉一部分数据
@@ -1091,7 +1123,7 @@ const importXML = (() => {
                 const fee = getFee(bills.fees, ['common', 'totalFee']);
                 const fee = getFee(bills.fees, ['common', 'totalFee']);
                 const feeRate = bills.feeRate && parseFloat(bills.feeRate) !== 0 ? parseFloat(bills.feeRate) : 0;
                 const feeRate = bills.feeRate && parseFloat(bills.feeRate) !== 0 ? parseFloat(bills.feeRate) : 0;
                 if (fee && parseFloat(fee) !== 0 && feeRate) {
                 if (fee && parseFloat(fee) !== 0 && feeRate) {
-                    bills.calcBase = scMathUtil.roundForObj(parseFloat(fee) * 100 / feeRate, 2);
+                    bills.calcBase = scMathUtil.roundForObj(parseFloat(fee) * 100 / feeRate, Decimal.FEE);
                 } else {
                 } else {
                     bills.calcBase = fee !== '0' ? fee : '';
                     bills.calcBase = fee !== '0' ? fee : '';
                 }
                 }
@@ -1109,6 +1141,10 @@ const importXML = (() => {
     }
     }
     // 转换清单
     // 转换清单
     function transformBills(tenderData, billsTemplate) {
     function transformBills(tenderData, billsTemplate) {
+        const rst = {
+            bills: [],
+            billsQuantityDetails: []
+        };
         const billsData = mergeBills(tenderData, billsTemplate);
         const billsData = mergeBills(tenderData, billsTemplate);
         setupFeeCode(billsData);
         setupFeeCode(billsData);
         transformCalcBase(billsData);
         transformCalcBase(billsData);
@@ -1128,8 +1164,9 @@ const importXML = (() => {
                     }
                     }
                 } else {
                 } else {
                     // 综合合价的小数位数
                     // 综合合价的小数位数
-                    const totalFeeDecimal = totalFee.match(/\.\d+/);
-                    unitFee = scMathUtil.roundForObj(totalFee / bills.quantity, totalFeeDecimal ? totalFeeDecimal[0] : 0);
+                    //const totalFeeDecimal = totalFee.match(/\.\d+/);
+                    //unitFee = scMathUtil.roundForObj(totalFee / bills.quantity, totalFeeDecimal ? totalFeeDecimal[0] : 0);
+                    unitFee = scMathUtil.roundForObj(totalFee / bills.quantity, Decimal.FEE);
                 }
                 }
                 const commonFee = bills.fees.find(fee => fee.fieldName === 'common');
                 const commonFee = bills.fees.find(fee => fee.fieldName === 'common');
                 if (commonFee) {
                 if (commonFee) {
@@ -1137,10 +1174,26 @@ const importXML = (() => {
                 }
                 }
             }
             }
             bills.projectID = tenderData.ID;
             bills.projectID = tenderData.ID;
-            bills.quantityEXP = bills.quantity;
-            // TODO 删除items rations feeCode
+            // 工程量明细
+            transformQuantityDetails(tenderData.ID, bills.quantityDetails, bills.ID, 'billID');
+            bills.quantityEXP = bills.quantityDetails && bills.quantityDetails.length ? GCLMXHj : bills.quantity;
+            if (bills.quantityDetails) {
+                rst.billsQuantityDetails.push(...bills.quantityDetails);
+            }
+            rst.bills.push(bills);
         });
         });
-        return billsData;
+
+        return rst;
+    }
+    // 转换工程量明细数据
+    function transformQuantityDetails(tenderID, quantityDetails, refID, typeKey) {
+        if (quantityDetails) {
+            quantityDetails.forEach(item => {
+                item.ID = uuid.v1();
+                item[typeKey] = refID; // billID、rationID
+                item.projectID = tenderID;
+            }); 
+        }
     }
     }
     // 转换人材机汇总相关数据(人材机汇总、承包人材料、评标材料、暂估价材料、组成物、单价文件)
     // 转换人材机汇总相关数据(人材机汇总、承包人材料、评标材料、暂估价材料、组成物、单价文件)
     function transformGLJList(tenderData, IDPlaceholder, projectGLJMap) {
     function transformGLJList(tenderData, IDPlaceholder, projectGLJMap) {
@@ -1184,7 +1237,6 @@ const importXML = (() => {
                 rst.projectGLJ.push(projectGLJ);
                 rst.projectGLJ.push(projectGLJ);
                 // 单价文件数据:
                 // 单价文件数据:
                 rst.unitPrice.push(generateUnitPrice(projectGLJ));
                 rst.unitPrice.push(generateUnitPrice(projectGLJ));
-                // TODO 删除ratios
             });
             });
         }
         }
         // 转换与项目人材机关联的材料
         // 转换与项目人材机关联的材料
@@ -1261,7 +1313,8 @@ const importXML = (() => {
         const rst = {
         const rst = {
             ration: [],
             ration: [],
             rationGLJ: [],
             rationGLJ: [],
-            rationCoe: []
+            rationCoe: [],
+            rationQuantityDetails: []
         };
         };
         billsData
         billsData
             .filter(bills => bills.rations && bills.rations.length)
             .filter(bills => bills.rations && bills.rations.length)
@@ -1273,12 +1326,17 @@ const importXML = (() => {
                     ration.projectID = tenderData.ID;
                     ration.projectID = tenderData.ID;
                     ration.billsItemID = bills.ID;
                     ration.billsItemID = bills.ID;
                     ration.contain = getContain(bills, ration);
                     ration.contain = getContain(bills, ration);
+                    // 工程量明细
+                    transformQuantityDetails(tenderData.ID, ration.quantityDetails, ration.ID, 'rationID');
+                    ration.quantityEXP = getQuantityEXP(bills, ration);
+                    if (ration.quantityDetails) {
+                        rst.rationQuantityDetails.push(...ration.quantityDetails);
+                    }
                     rst.ration.push(ration);
                     rst.ration.push(ration);
                     // 定额人材机
                     // 定额人材机
                     rst.rationGLJ.push(...transformRationGLJs(bills, ration));
                     rst.rationGLJ.push(...transformRationGLJs(bills, ration));
                     // 定额系数
                     // 定额系数
                     rst.rationCoe.push(generateRationCoe(ration));
                     rst.rationCoe.push(generateRationCoe(ration));
-                    // TODO 删除rationGljs
                 });
                 });
             });
             });
         return rst;
         return rst;
@@ -1336,6 +1394,24 @@ const importXML = (() => {
                 option_list: []
                 option_list: []
             }
             }
         }
         }
+        // 获取定额的工程量表达式
+        function getQuantityEXP(bills, ration) {
+            if (ration.quantityDetails && ration.quantityDetails.length) {
+                return GCLMXHj;
+            }
+            // 定额根单位与清单根单位相同,则定额工程量表达式为QDL;否则定额工程量表达式为:定额工程量 * 定额单位量词
+            // eg: 清单单位:m  定额单位:100m
+            const reg = /\d+(\D+.*)/;
+            const billsRootUnit = bills.unit && bills.unit.replace(reg, '$1') || '';
+            const rationRootUnit = ration.unit && ration.unit.replace(reg, '$1') || '';
+            if (billsRootUnit === rationRootUnit) {
+                return QDL;
+            }
+            const numReg = /(\d+)\D+.*/;
+            const num = ration.unit && ration.unit.replace(numReg, '$1') || '1';
+            return ration.quantity * num;
+
+        }
     }
     }
     // 删除一些无用属性,减少通信数据量
     // 删除一些无用属性,减少通信数据量
     function clean(detailData) {
     function clean(detailData) {
@@ -1344,8 +1420,8 @@ const importXML = (() => {
             ration,
             ration,
             projectGLJ
             projectGLJ
         } = detailData;
         } = detailData;
-        bills.forEach(item => delete item.items && delete item.rations && delete item.feeCode);
-        ration.forEach(item => delete item.rationGLJs);
+        bills.forEach(item => delete item.items && delete item.rations && delete item.feeCode && delete item.quantityDetails);
+        ration.forEach(item => delete item.rationGLJs && delete item.quantityDetails);
         projectGLJ.forEach(item => delete item.ratios);
         projectGLJ.forEach(item => delete item.ratios);
     }
     }
     // 需要给清单、定额价格字段赋上调价数据,不然打开项目后会被重算: project_view.js -> loadProjectData方法内
     // 需要给清单、定额价格字段赋上调价数据,不然打开项目后会被重算: project_view.js -> loadProjectData方法内
@@ -1366,14 +1442,22 @@ const importXML = (() => {
     }
     }
     // 转换详细的项目数据,清单、定额、定额人材机、项目人材机、单价文件等
     // 转换详细的项目数据,清单、定额、定额人材机、项目人材机、单价文件等
     function transformDetail(tenderData, IDPlaceholder, billsTemplate) {
     function transformDetail(tenderData, IDPlaceholder, billsTemplate) {
-        const bills = transformBills(tenderData, billsTemplate);
+        const { bills, billsQuantityDetails } = transformBills(tenderData, billsTemplate);
         // 转换定额的处理依赖转换后的项目人材机数据,因此需要先转换项目人材机相关的数据
         // 转换定额的处理依赖转换后的项目人材机数据,因此需要先转换项目人材机相关的数据
         const projectGLJMap = {};
         const projectGLJMap = {};
         const relatedljGLJData = transformGLJList(tenderData, IDPlaceholder, projectGLJMap);
         const relatedljGLJData = transformGLJList(tenderData, IDPlaceholder, projectGLJMap);
-        const relatedRationData = transformRations(tenderData, bills, projectGLJMap);
+        const {
+            ration,
+            rationGLJ,
+            rationCoe,
+            rationQuantityDetails
+        } = transformRations(tenderData, bills, projectGLJMap);
         const detailData = {
         const detailData = {
             bills,
             bills,
-            ...relatedRationData,
+            ration,
+            rationGLJ,
+            rationCoe,
+            quantityDetails: [...billsQuantityDetails, ... rationQuantityDetails],
             ...relatedljGLJData
             ...relatedljGLJData
         };
         };
         clean(detailData);
         clean(detailData);