ソースを参照

广东接口,成果检验平台问题

vian 5 年 前
コミット
d42df9e7ba

+ 9 - 2
modules/main/controllers/project_controller.js

@@ -244,8 +244,15 @@ module.exports = {
             data: null
         };
         try {
-            const { str, encoding } = JSON.parse(req.body.data);
-            responseData.data = iconv.encode(str, encoding);
+            const { source, encoding, toBase64 } = JSON.parse(req.body.data);
+            const data = {};
+            source.forEach(str => {
+                const u8 = iconv.encode(str, encoding);
+                data[str] = toBase64 
+                    ? Buffer.from(u8).toString('base64')
+                    : u8;
+            });
+            responseData.data = data;
         } catch (err) {
             responseData.err = 1;
             responseData.msg = typeof error === 'object' ? '编码失败' : error;

+ 5 - 0
public/common_constants.js

@@ -129,6 +129,10 @@ const commonConstants = (() => {
         //甲定乙供
         JDYG: '甲定乙供'
     };
+    const SourceType = {
+        BILLS: 'bills',
+        RATION: 'ration',
+    };
     return {
         fixedFlag,
         billType,
@@ -137,5 +141,6 @@ const commonConstants = (() => {
         TaxType,
         supplyType,
         supplyText,
+        SourceType,
     }
 })();

+ 9 - 0
public/common_util.js

@@ -84,6 +84,14 @@ function deleteEmptyObject(arr) {
             return sorted;
         }
     }
+        /**
+     * 根据编码方式获取编码数据
+     * @param {Set} source - 字符串集合数据源
+     * @param {String} encoding - 编码方式
+     */
+    async function getEncodedData(source, encoding, toBase64 = false) {
+        return await ajaxPost('/project/getEncodedData', { source, encoding, toBase64 });
+    }
 
     return {
         isDef,
@@ -92,5 +100,6 @@ function deleteEmptyObject(arr) {
         similarEqual,
         getRequired,
         getSortedTreeData,
+        getEncodedData,
     };
 });

+ 0 - 10
web/building_saas/main/js/models/exportStdInterfaceBase.js

@@ -854,15 +854,6 @@ const XML_EXPORT_BASE = (() => {
         return infos;
     }
 
-    /**
-     * 根据编码方式获取编码数据
-     * @param {String} str - 字符串数组数据源
-     * @param {String} encoding - 编码方式
-     */
-    async function getEncodedData(str, encoding) {
-        return await ajaxPost('/project/getEncodedData', { str, encoding });
-    }
-
     const UTIL = Object.freeze({
         deWeightHints,
         isDef,
@@ -893,7 +884,6 @@ const XML_EXPORT_BASE = (() => {
         setupCode,
         propertyCheck,
         softCheck,
-        getEncodedData,
     });
 
     // 开始标签

+ 76 - 30
web/over_write/js/guangdong_2018_export.js

@@ -449,7 +449,7 @@ const XMLStandard = (function () {
                 // 工程类型
                 {
                     name: 'ProjectType', dName: '工程类型', required: true,
-                    value: getProjectType(projectData, true)
+                    value: _util.getValueByKey(basicInformation, 'projectType')
                 },
                 // 建设性质
                 {
@@ -499,7 +499,7 @@ const XMLStandard = (function () {
                 // 数据交换标准编号
                 {
                     name: 'StandardNumber', required: true,
-                    value: 'DBJ/T XX-XX-2018'
+                    value: 'DBJ/T 15-145-2018'
                 },
                 // 建设(编制)范围
                 {
@@ -1096,7 +1096,7 @@ const XMLStandard = (function () {
                 },
                 // 地区类别 取建设项目-基本信息-地区类别,基本信息那已经自检一次,这里不自检 //type: _type.INT, required: true, enumeration: Object.values(AreaKind), enumerationHint: Object.keys(AreaKind)
                 {
-                    name: 'AreaKind', dName: '地区类别', 
+                    name: 'AreaKind', dName: '地区类别',
                     value: AreaKind[_util.getValueByKey(basicInformation, 'regionalCategories')]
                 },
                 // 金额
@@ -1449,7 +1449,7 @@ const XMLStandard = (function () {
                 // 计算基数
                 { name: 'QtyFormula', value: getQtyFormula(node) },
                 // 单价(元)
-                { name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
+                //{ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
                 // 设备单价(元)指清单项目所采用设备的综合单价
                 { name: 'EquipmentPrice', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'equipment.unitFee') },
                 // 最低限价(元)
@@ -1457,7 +1457,7 @@ const XMLStandard = (function () {
                 // 最高限价(元)
                 { name: 'PriceHigh', type: _type.DECIMAL, value: bills.maxPrice },
                 // 费率(%)
-                { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
+                //{ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
                 // 合价(元)
                 { name: 'Total', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.totalFee') },
                 // 主要清单
@@ -1479,6 +1479,13 @@ const XMLStandard = (function () {
                 // 备注
                 { name: 'Remark', value: bills.remark }
             ];
+            // 单价费率,单价与费率在同一个费用项目中不允许同时存在。(对于套定额的清单,则输出单价不输出费率rate;对于基数计算的,则输出费率不输出单价)
+            const showPrice = !!(node.children && node.children.length && node.children[0].sourceType === commonConstants.SourceType.RATION)
+            if (showPrice) {
+                attrs.push({ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') });
+            } else {
+                attrs.push({ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' });
+            }
             _base.Element.call(this, 'WorkElement', attrs, '清单');
         }
         // 工程量计算表
@@ -1659,9 +1666,9 @@ const XMLStandard = (function () {
                 // 计算基数
                 { name: 'QtyFormula', value: getQtyFormula(node) },
                 // 单价
-                { name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
+                //{ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
                 // 费率
-                { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
+                //{ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
                 // 金额
                 { name: 'Total', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.totalFee') },
                 // 费用代号
@@ -1671,7 +1678,14 @@ const XMLStandard = (function () {
                 // 备注
                 { name: 'Remark', value: bills.remark }
             ];
-            _base.Element.call(this, 'SundryCostsItem', attrs, '其他项目费明细');
+            // 单价费率,单价与费率在同一个费用项目中不允许同时存在。(对于套定额的清单,则输出单价不输出费率rate;对于基数计算的,则输出费率不输出单价)
+            const showPrice = !!(node.children && node.children.length && node.children[0].sourceType === commonConstants.SourceType.RATION);
+            if (showPrice) {
+                attrs.push({ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') });
+            } else {
+                attrs.push({ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' });
+            }
+            _base.Element.call(this, 'SundryCostsItem', attrs, '清单');
         }
         // 暂列金额标题
         function ProvisionalSumsGroup(node) {
@@ -1701,9 +1715,9 @@ const XMLStandard = (function () {
                 // 计算基数
                 { name: 'QtyFormula', value: getQtyFormula(node) },
                 // 单价
-                { name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
+                //{ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
                 // 费率
-                { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
+                // { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
                 // 金额
                 { name: 'Total', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.totalFee') },
                 // 汇总类型
@@ -1711,6 +1725,13 @@ const XMLStandard = (function () {
                 // 备注
                 { name: 'Remark', value: bills.remark }
             ];
+            // 单价费率,单价与费率在同一个费用项目中不允许同时存在。(对于套定额的清单,则输出单价不输出费率rate;对于基数计算的,则输出费率不输出单价)
+            const showPrice = !!(node.children && node.children.length && node.children[0].sourceType === commonConstants.SourceType.RATION);
+            if (showPrice) {
+                attrs.push({ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') });
+            } else {
+                attrs.push({ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' });
+            }
             _base.Element.call(this, 'ProvisionalSumsItem', attrs, '暂列金额明细');
         }
         // 材料设备暂估价明细
@@ -1724,7 +1745,7 @@ const XMLStandard = (function () {
                 // 型号规格
                 { name: 'Specification', value: glj.specs },
                 // 单位
-                { name: 'Unit', dName: '单位', required: true, value: bills.unit },
+                { name: 'Unit', dName: '单位', required: true, value: glj.unit },
                 // 工程量(总消耗量)
                 { name: 'Quantity', type: _type.DECIMAL, value: glj.quantity },
                 // 单价 取市场价
@@ -1768,9 +1789,9 @@ const XMLStandard = (function () {
                 // 计算基数
                 { name: 'QtyFormula', value: getQtyFormula(node) },
                 // 单价
-                { name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
+                //{ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
                 // 费率
-                { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
+                //{ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
                 // 金额
                 { name: 'Total', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.totalFee') },
                 // 汇总类型
@@ -1778,6 +1799,12 @@ const XMLStandard = (function () {
                 // 备注
                 { name: 'Remark', value: bills.remark }
             ];
+            const showPrice = !!(node.children && node.children.length && node.children[0].sourceType === commonConstants.SourceType.RATION);
+            if (showPrice) {
+                attrs.push({ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') });
+            } else {
+                attrs.push({ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' });
+            }
             _base.Element.call(this, 'SpecialtyProvisionalPriceItem', attrs, '专业工程暂估价明细');
         }
         // 计日工标题
@@ -1884,9 +1911,9 @@ const XMLStandard = (function () {
                 // 计算基数
                 { name: 'QtyFormula', value: getQtyFormula(node) },
                 // 单价
-                { name: 'Price', value: _util.getFee(bills.fees, 'common.unitFee') },
+                //{ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') },
                 // 费率
-                { name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
+                //{ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' },
                 // 金额
                 { name: 'Total', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.totalFee') },
                 // 依据
@@ -1896,6 +1923,12 @@ const XMLStandard = (function () {
                 // 备注
                 { name: 'Remark', value: bills.remark }
             ];
+            const showPrice = !!(node.children && node.children.length && node.children[0].sourceType === commonConstants.SourceType.RATION);
+            if (showPrice) {
+                attrs.push({ name: 'Price', type: _type.DECIMAL, value: _util.getFee(bills.fees, 'common.unitFee') });
+            } else {
+                attrs.push({ name: 'Rate', type: _type.DECIMAL, value: !commonUtil.isEmptyVal(bills.feeRate) ? bills.feeRate : '100' });
+            }
             _base.Element.call(this, eleName, attrs, '索赔费用明细');
         }
         // 规费
@@ -2132,10 +2165,14 @@ const XMLStandard = (function () {
             // 建设项目
             const constructionProject = new ConstructionProject(projectData, summaryInfo);
             // 系统信息
+            // 软件相关信息进行base64编码(gbk to base64)
+            const hardwareID = _util.generateHardwareId();
+            const encodedData = await commonUtil.getEncodedData([projectData.softInfo, hardwareID], 'gbk', true);
+            const ID1 = encodedData[projectData.softInfo];
+            const ID2 = encodedData[hardwareID];
             const systemInfo = new SystemInfo({
-                // 软件相关信息进行base64编码
-                ID1: Base64.encode(projectData.softInfo),
-                ID2: Base64.encode(_util.generateHardwareId()),
+                ID1,
+                ID2,
                 makeDate: moment(Date.now()).format('YYYY-MM-DDTHH:mm:ss'),
             });
             // 工程信息
@@ -2858,23 +2895,32 @@ const XMLStandard = (function () {
             for (const file of files) {
                 zip.file(file.fileName, file.blob, { binary: true });
             }
-            const zipFile = await zip.generateAsync({ type: 'blob' });
-            // TODO
             // 导出的文件名需要用gbk编码,否则广联达导入不了
-            /* debugger;
+            // encodeFileName不支持异步,先调用一次generateAsync,获取string与Unit8Array的数据源映射            
+            // 不用TextEncoder的原因:https://developer.mozilla.org/zh-CN/docs/Web/API/TextEncoder/TextEncoder
+            // - 在Firefox 48和Chrome 53之前,编码类型标签被接受为TextEncoder对象的参数
+            // - 现在这两个浏览器已经删除了除utf-8之外的任何编码器类型的支持,以符合规范。 传入TextEncoder构造函数的任何类型标签现在都将被忽略,并且将创建一个utf-8 TextEncoder。
+            const source = new Set();
+            await zip.generateAsync({
+                type: 'uint8array',
+                encodeFileName: (string) => {
+                    source.add(string);
+                    return string;
+                }
+            });
+            const encodedData = await commonUtil.getEncodedData([...source], 'gbk');
             const zipFile = await zip.generateAsync({
                 type: 'uint8array',
-                encodeFileName: async function (string) {
-                    if (!string) {
-                        return string;
-                    }
-                    await _util.setTimeoutSync(() => { }, 300);
-                    const encodedStr = await _util.getEncodedData(string, 'gbk');
-                    return encodedStr;
+                encodeFileName: (string) => {
+                    const abSource = encodedData[string].data;
+                    const ab = Uint8Array.from(abSource);
+                    return ab;
                 }
-            }); */
+            });
+            // TypedBuffer to ArrayBuffer to blob
+            const saveAsBlob = new Blob([zipFile.buffer]);
             const exportKindName = _config.EXPORT_KIND_NAME[exportKind];
-            saveAs(zipFile, `广东标准交换数据(${exportKindName}).COS`);
+            saveAs(saveAsBlob, `广东标准交换数据(${exportKindName}).COS`);
         }
     }
 

+ 37 - 23
web/over_write/js/guangdong_2018_import.js

@@ -1542,30 +1542,44 @@ const importXML = (() => {
     async function unzipFile(file) {
         const jsZip = new JSZip();
         // 广联达导出的cos文件,内部文件的文件名是gbk编码,如果不处理的话无法导入
-        const fileNameByteList = [];
-        let index = 0;
-        const zip = await jsZip.loadAsync(file, {
-            // zip文件中有一个标志,用于说明文件名和注释是否使用UTF-8编码。 
-            // 如果未设置,则JSZip无法知道所使用的编码(它通常是操作系统的默认编码)
-            // 因此若文件名编码非utf-8,则会调用decodeFileName。我们将其认为是gbk编码
-            decodeFileName: function (bytes) {
-                if (bytes.length) {
-                    fileNameByteList.push(getUnit8Numbers(bytes));
-                    return String(index++);
-                } else {
-                    return '';
+        let zip;
+        if (typeof TextDecoder === 'undefined') {
+            const gbkTextDecoder = new TextDecoder('gbk');
+            zip = await jsZip.loadAsync(file, {
+                // zip文件中有一个标志,用于说明文件名和注释是否使用UTF-8编码。 
+                // 如果未设置,则JSZip无法知道所使用的编码(它通常是操作系统的默认编码)
+                // 因此若文件名编码非utf-8,则会调用decodeFileName。我们将其认为是gbk编码
+                decodeFileName: function (bytes) {
+                    if (bytes.length) {
+                        return gbkTextDecoder.decode(bytes);
+                    } else {
+                        return '';
+                    }
                 }
-            }
-        });
-        const decodedNames = await util.getDecodedData(fileNameByteList, 'gbk');
-        // 将zip里的文件名替换成gbk解码后的名称
-        decodedNames.forEach((name, index) => {
-            if (zip.files[index]) {
-                zip.files[index].name = name;
-                zip.files[name] = zip.files[index];
-                delete zip.files[index];
-            }
-        })
+            });
+        } else {
+            const fileNameByteList = [];
+            let index = 0;
+            zip = await jsZip.loadAsync(file, {
+                decodeFileName: function (bytes) {
+                    if (bytes.length) {
+                        fileNameByteList.push(getUnit8Numbers(bytes));
+                        return String(index++);
+                    } else {
+                        return '';
+                    }
+                }
+            });
+            const decodedNames = await util.getDecodedData(fileNameByteList, 'gbk');
+            // 将zip里的文件名替换成gbk解码后的名称
+            decodedNames.forEach((name, index) => {
+                if (zip.files[index]) {
+                    zip.files[index].name = name;
+                    zip.files[name] = zip.files[index];
+                    delete zip.files[index];
+                }
+            });
+        }
         const map = {};
         for (const fileName in zip.files) {
             // 将二进制数据转换成字符串