ソースを参照

feat: 信息价增加导出浙江各市信息价excel

vian 1 週間 前
コミット
3809db2001

+ 30 - 4
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: '材料信息价库',
@@ -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 = {

+ 91 - 0
modules/price_info_lib/facade/index.js

@@ -808,6 +808,96 @@ 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();
+    console.log(libs);
+    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: ['5509003', '5509001', '5509002', '5509006'] },
+        { name: '钢材', codes: ['2001006', '2003004', '2003008', '2001001', '2001008'] },
+        { name: '砂石料', codes: ['5503005', '5503007', '5503013', '5503014', '5505005', '5505016', '5505025', '5505012', '5505013', '1516001', '5503006', '5505019001', '5505019'] },
+    ]
+    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(['', '', '', code, name, price]);
+                    }
+                });
+            });
+        });
+    });
+    return excelData;
+}
+
 
 module.exports = {
     getLibs,
@@ -835,4 +925,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;
 };
 

+ 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>

+ 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>

+ 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();