Explorar o código

feat: 导入信息价关键字excel(主表+副表)

vian %!s(int64=3) %!d(string=hai) anos
pai
achega
4d1235f560

+ 40 - 0
modules/all_models/std_price_info_items.js

@@ -2,6 +2,26 @@
 const mongoose = require('mongoose');
 
 const Schema = mongoose.Schema;
+
+const keywordSchema = new Schema({
+    keyword: {
+        type: String,
+        default: ''
+    }, // 关键字
+    coe: {
+        type: String,
+        default: ''
+    }, // 系数(关键字效果)
+    group: {
+        type: String,
+        default: ''
+    }, // 组别
+    optionCode: {
+        type: String,
+        default: ''
+    }, // 选项号
+}, { _id: false });
+
 const priceInfoItems = new Schema({
     ID: String,
     libID: String,
@@ -37,6 +57,26 @@ const priceInfoItems = new Schema({
     remark: {
         type: String,
         default: ''
+    },
+    // 别名编码
+    classCode: {
+        type: String,
+        default: ''
+    },
+    // 计算式
+    expString: {
+        type: String,
+        default: ''
+    },
+    // 月份、价格备注
+    dateRemark: {
+        type: String,
+        default: ''
+    },
+    // 关键字
+    keywordList: {
+        type: [keywordSchema],
+        default: []
     }
 }, { versionKey: false });
 mongoose.model('std_price_info_items', priceInfoItems, 'std_price_info_items');

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

@@ -132,7 +132,9 @@ class PriceInfoController extends BaseController {
             try {
                 const libID = fields.libID !== undefined && fields.libID.length > 0 ?
                     fields.libID[0] : null;
-                if (!libID) {
+                const importType = fields.importType !== undefined && fields.importType.length > 0 ?
+                    fields.importType[0] : null;
+                if (!libID || !importType) {
                     throw '参数错误。';
                 }
                 const file = files.file !== undefined ? files.file[0] : null;
@@ -152,7 +154,7 @@ class PriceInfoController extends BaseController {
                     throw 'excel没有对应数据。';
                 }
                 // 提取excel数据并入库
-                await facade.importExcelData(libID, sheet[0].data);
+                importType === 'originalData' ? await facade.importExcelData(libID, sheet[0].data) : await facade.importKeyData(libID, sheet[0].data, sheet[1].data);
                 // 删除文件
                 if (uploadFullName && fs.existsSync(uploadFullName)) {
                     fs.unlink(uploadFullName);

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

@@ -231,6 +231,85 @@ async function importExcelData(libID, sheetData) {
         throw 'excel没有有效数据。'
     }
 }
+
+// 导入excel关键字数据(主表+副表),目前只针对珠海,根据列号导入
+/* 
+主表:主从对应码	别名编码	材料名称	规格	单位	含税价(元)	除税价(元)	月份备注	计算式
+副表:主从对应码	关键字	单位	关键字效果	组别	选项号
+ */
+async function importKeyData(libID, mainData, subData) {
+    const lib = await priceInfoLibModel.findOne({ ID: libID }).lean();
+    if (!lib) {
+        throw new Error('库不存在');
+    }
+    const zh = await priceInfoAreaModel.findOne({ name: { $regex: '珠海' } }).lean();
+    if (!zh) {
+        throw new Error('该库不存在珠海地区');
+    }
+    // 删除珠海地区所有材料
+    await priceInfoItemModel.deleteMany({ libID, areaID: zh.ID });
+
+    const classItems = await priceInfoClassModel.find({ libID, areaID: zh.ID }).lean();
+    // 分类树前四位编码 - 分类节点ID映射表
+    let otherClassID = '';
+    const classMap = {};
+    classItems.forEach(item => {
+        if (item.name) {
+            if (!otherClassID && /其他/.test(item.name)) {
+                otherClassID = item.ID;
+            }
+            const code = item.name.substr(0, 4);
+            if (/\d{4}/.test(code)) {
+                classMap[code] = item.ID;
+            }
+        }
+    });
+
+    // 主从对应码 - 关键字数组映射
+    const keywordMap = {};
+    for (let row = 1; row < subData.length; row++) {
+        const rowData = subData[row];
+        const keywordItem = {
+            code: rowData[0] || '',
+            keyword: rowData[1] || '',
+            coe: rowData[3] || '',
+            group: rowData[4] || '',
+            optionCode: rowData[5] || '',
+        };
+        (keywordMap[keywordItem.code] || (keywordMap[keywordItem.code] = [])).push(keywordItem);
+    }
+
+    const priceItems = [];
+    for (let row = 1; row < mainData.length; row++) {
+        const rowData = mainData[row];
+        const code = rowData[0] || '';
+        const matchCode = code.substr(0, 4);
+        const classID = classMap[matchCode] || otherClassID;
+        const priceItem = {
+            code,
+            libID,
+            classID,
+            ID: uuidV1(),
+            compilationID: lib.compilationID,
+            areaID: zh.ID,
+            period: lib.period,
+            classCode: rowData[1] || '',
+            name: rowData[2] || '',
+            specs: rowData[3] || '',
+            unit: rowData[4] || '',
+            taxPrice: rowData[5] || '',
+            noTaxPrice: rowData[6] || '',
+            dateRemark: rowData[7] || '',
+            expString: rowData[8] ||  '',
+            keywordList: keywordMap[code] || [],
+        }
+        priceItems.push(priceItem);
+    }
+    if (priceItems.length) {
+        await priceInfoItemModel.insertMany(priceItems);
+    }
+}
+
 /* async function importExcelData(libID, sheetData) {
     const libs = await getLibs({ ID: libID });
     const compilationID = libs[0].compilationID;
@@ -454,6 +533,7 @@ module.exports = {
     processChecking,
     crawlDataByCompilation,
     importExcelData,
+    importKeyData,
     getAreas,
     updateAres,
     insertAreas,

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

@@ -29,6 +29,7 @@
                                     <th width="160">添加时间</th>
                                     <th width="70">操作</th>
                                     <th width="70">原始数据</th>
+                                    <th width="70">关键字</th>
                                 </tr>
                             </thead>
                             <tbody id="showArea">
@@ -52,9 +53,14 @@
                                     </td>
                                     <td>
                                         <a class="btn btn-secondary btn-sm import-data lock-btn-control disabled"
-                                            onclick='handleImportClick("<%= lib.ID%>")' href="javacript:void(0);"
+                                            onclick='handleImportClick("<%= lib.ID%>", "originalData")' href="javacript:void(0);"
                                             title="导入数据"><i class="fa fa-sign-in fa-rotate-90"></i>导入</a>
                                     </td>
+                                    <td>
+                                        <a class="btn btn-secondary btn-sm import-data lock-btn-control disabled"
+                                            onclick='handleImportClick("<%= lib.ID%>", "keys")' href="javacript:void(0);"
+                                            title="导入关键字"><i class="fa fa-sign-in fa-rotate-90"></i>导入</a>
+                                    </td>
                                 </tr>
                                 <% } %>
                             </tbody>

+ 3 - 0
web/maintain/price_info_lib/js/index.js

@@ -653,11 +653,14 @@ const PRICE_BOOK = (() => {
     const setting = {
         header: [
             { headerName: '编码', headerWidth: 100, dataCode: 'code', dataType: 'String', hAlign: 'left', vAlign: 'center' ,formatter: "@"},
+            { headerName: '别名编码', headerWidth: 70, dataCode: 'classCode', dataType: 'String', hAlign: 'left', vAlign: 'center' ,formatter: "@"},
             { headerName: '名称', headerWidth: 200, dataCode: 'name', dataType: 'String', hAlign: 'left', vAlign: 'center' },
             { headerName: '规格型号', headerWidth: 120, dataCode: 'specs', dataType: 'String', hAlign: 'left', vAlign: 'center' },
             { headerName: '单位', headerWidth: 80, dataCode: 'unit', dataType: 'String', hAlign: 'center', vAlign: 'center' },
             { headerName: '不含税价', headerWidth: 80, dataCode: 'noTaxPrice', dataType: 'String', hAlign: 'right', vAlign: 'center' },
             { headerName: '含税价', headerWidth: 80, dataCode: 'taxPrice', dataType: 'String', hAlign: 'right', vAlign: 'center' },
+            { headerName: '月份备注', headerWidth: 140, dataCode: 'dateRemark', dataType: 'String', hAlign: 'left', vAlign: 'center' },
+            { headerName: '计算式', headerWidth: 100, dataCode: 'expString', dataType: 'String', hAlign: 'left', vAlign: 'center' },
         ],
     };
     // 初始化表格

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

@@ -79,9 +79,12 @@ function handleDeleteConfirm() {
     }
 }
 
+let importType = 'originalData';
+
 // 点击导入按钮
-function handleImportClick(libID) {
+function handleImportClick(libID, type) {
     setCurLib(libID);
+    importType = type;
     $('#import').modal('show');
 }
 
@@ -97,6 +100,7 @@ function handleImportConfirm() {
         }
         formData.append('file', file.files[0]);
         formData.append('libID', curLib.id);
+        formData.append('importType', importType);
         $.ajax({
             url: '/priceInfo/importExcel',
             type: 'POST',