Explorar o código

feat: 导出信息价主表excel

vian hai 1 ano
pai
achega
ec1d37ed29

+ 23 - 2
modules/price_info_lib/controllers/index.js

@@ -219,9 +219,9 @@ class PriceInfoController extends BaseController {
 
     async calcPriceIndex(req, res) {
         try {
-            const { period, libID ,compilationID} = JSON.parse(req.body.data);
+            const { period, libID, compilationID } = JSON.parse(req.body.data);
             const areaID = '971fb9a0-0f93-11eb-b53c-45271c1df90f';//写死珠海地区
-            const data = await facade.calcPriceIndex(libID,period, areaID,compilationID);
+            const data = await facade.calcPriceIndex(libID, period, areaID, compilationID);
             res.json({ error: 0, message: 'getCLass success', data });
         } catch (err) {
             console.log(err);
@@ -262,6 +262,27 @@ class PriceInfoController extends BaseController {
         }
     }
 
+    async exportPriceData(request, response) {
+        const libID = request.query.libID;
+        try {
+            const excelData = await facade.exportExcelData(libID);
+            const buffer = excel.build([{ name: "信息价主表", data: excelData }]);
+            const filePath = './public/exportInfo.xlsx';
+            fs.writeFileSync(filePath, buffer, 'binary');
+            const stats = fs.statSync(filePath);
+            // 下载相关header
+            response.set({
+                'Content-Type': 'application/octet-stream',
+                'Content-Disposition': 'attachment; filename=infoPrice.xlsx',
+                'Content-Length': stats.size
+            });
+            fs.createReadStream(filePath).pipe(response);
+            fs.unlink(filePath);
+        } catch (error) {
+            response.end(error);
+        }
+    }
+
 }
 
 module.exports = {

+ 52 - 37
modules/price_info_lib/facade/index.js

@@ -312,7 +312,7 @@ async function importKeyData(libID, mainData, subData) {
             taxPrice: rowData[5] || '',
             noTaxPrice: rowData[6] || '',
             dateRemark: rowData[7] || '',
-            expString: rowData[8] ||  '',
+            expString: rowData[8] || '',
             keywordList: keywordMap[code] || [],
         }
         priceItems.push(priceItem);
@@ -538,84 +538,98 @@ async function editClassData(updateData) {
 }
 
 //计算指标平均值
-function calcIndexAvg (period, areaID,compilationID,preCodeMap){
-    const newData = []; 
-    for(const code in preCodeMap){
+function calcIndexAvg(period, areaID, compilationID, preCodeMap) {
+    const newData = [];
+    for (const code in preCodeMap) {
         const indexArr = preCodeMap[code];
         let total = 0;
 
-        for(const index of indexArr){
-            total  =   scMathUtil.roundForObj(total + index,2); 
+        for (const index of indexArr) {
+            total = scMathUtil.roundForObj(total + index, 2);
         }
-        const avg = scMathUtil.roundForObj(total/indexArr.length,2); 
-        newData.push({ID:uuidV1(),code,period,areaID,compilationID,index:avg})
+        const avg = scMathUtil.roundForObj(total / indexArr.length, 2);
+        newData.push({ ID: uuidV1(), code, period, areaID, compilationID, index: avg })
     }
     return newData
 }
 
 //一个月里有classCode相同,但是价格不同的情况,取平均值
-function getClassCodePriceAvgMap  (items){
+function getClassCodePriceAvgMap(items) {
     const classCodeMap = {};
-    for(const b of items){
-        classCodeMap[b.classCode]?classCodeMap[b.classCode].push(b):classCodeMap[b.classCode]=[b];
+    for (const b of items) {
+        classCodeMap[b.classCode] ? classCodeMap[b.classCode].push(b) : classCodeMap[b.classCode] = [b];
     }
 
-    for(const classCode in classCodeMap){
+    for (const classCode in classCodeMap) {
         const baseItems = classCodeMap[classCode];
         const item = baseItems[0];
-        if(baseItems.length > 1){
+        if (baseItems.length > 1) {
             let sum = 0;
-            for(const b of baseItems){
-                sum += parseFloat(b.noTaxPrice);       
-            }      
-            classCodeMap[classCode] = {code:item.code,name:item.name,price:scMathUtil.roundForObj(sum/baseItems.length,2)};
-        }else{
-            classCodeMap[classCode] = {code:item.code,name:item.name,price:parseFloat(item.noTaxPrice)}
+            for (const b of baseItems) {
+                sum += parseFloat(b.noTaxPrice);
+            }
+            classCodeMap[classCode] = { code: item.code, name: item.name, price: scMathUtil.roundForObj(sum / baseItems.length, 2) };
+        } else {
+            classCodeMap[classCode] = { code: item.code, name: item.name, price: parseFloat(item.noTaxPrice) }
         }
 
     }
 
     return classCodeMap
-  
+
 }
 
-async function calcPriceIndex(libID,period, areaID,compilationID){
-    const baseItems = await priceInfoItemModel.find({areaID,period:'2022年-01月'}).lean();//以珠海 22年1月的数据为基准
-    const currentItems =  await priceInfoItemModel.find({areaID,period}).lean();
+async function calcPriceIndex(libID, period, areaID, compilationID) {
+    const baseItems = await priceInfoItemModel.find({ areaID, period: '2022年-01月' }).lean();//以珠海 22年1月的数据为基准
+    const currentItems = await priceInfoItemModel.find({ areaID, period }).lean();
     const preCodeMap = {};//编码前4位-指数映射
     const baseAvgMap = getClassCodePriceAvgMap(baseItems);
     const currentAvgMap = getClassCodePriceAvgMap(currentItems);
-    
+
     let message = '';
 
-    for(const classCode in currentAvgMap){
+    for (const classCode in currentAvgMap) {
         const c = currentAvgMap[classCode];
-        const preCode = c.code.substr(0,4);
+        const preCode = c.code.substr(0, 4);
         let index = 1;
         const baseItem = baseAvgMap[classCode];
-        const tem = {index,classCode,name:c.name,code:c.code};
-        
-        if(baseItem && baseItem.price){//一个月份里有多个值时,先取平均再计算
-            index =  scMathUtil.roundForObj(c.price/baseItem.price,2);
+        const tem = { index, classCode, name: c.name, code: c.code };
+
+        if (baseItem && baseItem.price) {//一个月份里有多个值时,先取平均再计算
+            index = scMathUtil.roundForObj(c.price / baseItem.price, 2);
             tem.baseName = baseItem.name;
         }
         tem.index = index;
-        if(Math.abs(index - 1) > 0.2){
+        if (Math.abs(index - 1) > 0.2) {
             const string = `classCode:${tem.classCode},编号:${tem.code},基础名称:${tem.baseName},当前库中名称:${tem.name},指数:${tem.index};\n`;
-            message +=string;
+            message += string;
             console.log(string)
-        } 
+        }
 
-      preCodeMap[preCode]?preCodeMap[preCode].push(index):preCodeMap[preCode]=[index];
+        preCodeMap[preCode] ? preCodeMap[preCode].push(index) : preCodeMap[preCode] = [index];
     }
-    const newIndexData = calcIndexAvg(period, areaID,compilationID,preCodeMap)
+    const newIndexData = calcIndexAvg(period, areaID, compilationID, preCodeMap)
     //删除旧数据
-    await priceInfoIndexModel.deleteMany({areaID,period});
+    await priceInfoIndexModel.deleteMany({ areaID, period });
     //插入新数据
     await priceInfoIndexModel.insertMany(newIndexData);
     return message;
 }
 
+async function exportExcelData(libID) {
+    const priceItems = await priceInfoItemModel.find({ libID }).lean();
+    // 整理数据
+    let priceData = [];
+    for (const tmp of priceItems) {
+        const item = [tmp.code || '', tmp.classCode || '', tmp.name || '', tmp.specs || '', tmp.unit || '', tmp.taxPrice || '', tmp.noTaxPrice || '', tmp.remark || '', tmp.expString || ''];
+        priceData.push(item);
+    }
+    const excelData = [['主从对应码', '别名编码', '材料名称', '规格型号', '单位', '含税价(元)', '除税价(元)', '多价备注', '计算式']];
+    excelData.push.apply(excelData, priceData);
+
+    return excelData;
+}
+
 module.exports = {
     getLibs,
     createLib,
@@ -633,5 +647,6 @@ module.exports = {
     calcPriceIndex,
     getPriceData,
     editPriceData,
-    editClassData
+    editClassData,
+    exportExcelData
 }

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

@@ -26,6 +26,8 @@ module.exports = function (app) {
     router.post("/editPriceData", priceInfoController.auth, priceInfoController.init, priceInfoController.editPriceData);
     router.post("/editClassData", priceInfoController.auth, priceInfoController.init, priceInfoController.editClassData);
 
+    router.get("/export", priceInfoController.auth, priceInfoController.init, priceInfoController.exportPriceData);
+
     app.use("/priceInfo", router);
 };
 

+ 2 - 1
web/maintain/price_info_lib/html/main.html

@@ -28,7 +28,7 @@
                                     <th width="160">费用定额</th>
                                     <th width="160">添加时间</th>
                                     <th width="70">操作</th>
-                                    <th width="70">原始数据</th>
+                                    <th width="150">原始数据</th>
                                     <th width="70">关键字</th>
                                 </tr>
                             </thead>
@@ -52,6 +52,7 @@
                                                 class="fa fa-unlock-alt"></i></a>
                                     </td>
                                     <td>
+                                        <a class="btn btn-success btn-sm export-data lock-btn-control disabled" href="javascript:void(0);" onclick='handleExportClick("<%= lib.ID%>")' title="导出数据"><i class="fa fa-sign-out fa-rotate-270"></i>导出</a>
                                         <a class="btn btn-secondary btn-sm import-data lock-btn-control disabled"
                                             onclick='handleImportClick("<%= lib.ID%>", "originalData")' href="javacript:void(0);"
                                             title="导入数据"><i class="fa fa-sign-in fa-rotate-90"></i>导入</a>

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

@@ -88,6 +88,11 @@ function handleImportClick(libID, type) {
     $('#import').modal('show');
 }
 
+// 点击导出按钮
+function handleExportClick(libID) {
+    window.location.href = '/priceInfo/export?libID=' + libID;
+}
+
 // 导入确认
 function handleImportConfirm() {
     $.bootstrapLoading.start();