zs 2 年 前
コミット
724bcb7fd9
2 ファイル変更224 行追加135 行削除
  1. 2 2
      package.json
  2. 222 133
      src/service/cpcMessage.service.ts

+ 2 - 2
package.json

@@ -26,12 +26,12 @@
     "compressing": "^1.9.0",
     "encoding": "^0.1.13",
     "exceljs": "^4.3.0",
-    "fast-xml-parser": "^4.2.2",
     "free-midway-component": "^1.0.35",
     "midway-schedule": "^2.15.0",
     "moment": "^2.29.4",
     "mongoose": "^7.0.4",
-    "swagger-ui-dist": "^4.18.2"
+    "swagger-ui-dist": "^4.18.2",
+    "xml-js": "^1.6.11"
   },
   "devDependencies": {
     "@midwayjs/cli": "^2.0.0",

+ 222 - 133
src/service/cpcMessage.service.ts

@@ -10,12 +10,13 @@ import { CpcMessage } from '../entity/cpcMessage.entity';
 import { Config } from '@midwayjs/core';
 import _ = require('lodash');
 const compressing = require('compressing');
-const encoding = require('encoding');
-const fxp = require('fast-xml-parser');
+const cOnvert = require('xml-js');
 import * as fs from 'node:fs';
 import * as Path from 'node:path';
+const moment = require('moment');
 import { Apply } from '../entity/apply.entity';
 import { Patent } from '../entity/patent.entity';
+import { CpcMessageerror } from '../entity/cpcMessageerror.entity';
 const sep = Path.sep;
 import { Types } from 'mongoose';
 const ObjectId = Types.ObjectId;
@@ -31,6 +32,9 @@ export class CpcMessageService extends BaseService<modelType> {
   @InjectEntityModel(Patent)
   PatentModel: ReturnModelType<typeof Patent>;
 
+  @InjectEntityModel(CpcMessageerror)
+  errorModel: ReturnModelType<typeof CpcMessageerror>;
+
   @Config('export.root_path')
   import_root_path;
 
@@ -44,7 +48,7 @@ export class CpcMessageService extends BaseService<modelType> {
     if (ext !== 'zip') {
       throw new ServiceError(
         '只接收压缩格式为zip的压缩包',
-        FrameworkErrorEnum.BAD_QUERY
+        FrameworkErrorEnum.SERVICE_FAULT
       );
     }
     // 解压
@@ -55,119 +59,154 @@ export class CpcMessageService extends BaseService<modelType> {
     }
     // 修改,多个专利:需要扫描下解压后的文件夹,然后循环处理下面所有的内容
     const tempDirRootPath = `${uncompressFilePath}${sep}`;
-    const tempDir = await fs.readdirSync(tempDirRootPath);
-    const errorList = [];
-    for (const tempDirPath of tempDir) {
-      const thisDirPath = `${tempDirRootPath}${tempDirPath}`;
-      const patentNumber = tempDirPath;
-      try {
-        // 找到
-        let filePaths = [];
-        try {
-          const arr = patentNumber.split('.');
-          const fileNametwo = _.head(arr);
-          const exttwo = _.last(arr);
-          const tempDirtwo = `${tempDirRootPath}${fileNametwo}`;
-          if (exttwo === 'zip') {
-            await compressing.zip.uncompress(thisDirPath, tempDirtwo);
-            filePaths = await this.findFileNameLoop(`${tempDirtwo}${sep}`);
-          }
-        } catch (error) {
-          errorList.push({ key: patentNumber, word: '解析文件具体位置失败' });
-          continue;
-        }
-        if (filePaths.length <= 0) {
-          errorList.push({ key: patentNumber, word: '未找到文件' });
-          continue;
-        }
-        // 2021-10-16 修改: 取出第一层的xml文件,即:路径最短的;除文件名外,字符串长度最小的
-        let xmlPaths = filePaths.filter(f => f.includes('.xml'));
-        if (xmlPaths.length > 0) {
-          // 去掉文件名
-          xmlPaths = xmlPaths.map(i => {
-            const arr = i.split(sep);
-            arr.pop();
-            const obj = { dir: arr.join(sep), fullPath: i };
-            return obj;
-          });
-          // 按路径字符串长度排序
-          xmlPaths = xmlPaths.sort((a, b) => {
-            const anum = a.dir.length;
-            const bnum = b.dir.length;
-            return anum - bnum;
-          });
-        }
-        const xmlPath = _.get(_.head(xmlPaths), 'fullPath');
-        if (!xmlPath) {
-          errorList.push({ key: patentNumber, word: '未找到xml文件' });
-          continue;
-        }
-        let xmlData;
+    let tempDir = fs.readdirSync(tempDirRootPath);
+    let errorList = [];
+    // 2023-02-06: zip格式修改: zip套dir => zip套zip, zip解压出dir;
+    // 也就是需要将zip再次解压一遍,并将所有的zip删除即可
+    const isAllZip = tempDir.some(f => f.includes('zip'));
+    if (isAllZip) {
+      for (const p of tempDir) {
+        if (!p.includes('.zip')) continue;
+        const zipFullPath = `${uncompressFilePath}${sep}${p}`;
+        const zipArr = p.split('.');
+        const name = _.head(zipArr);
         try {
-          xmlData = await this.dealXml(xmlPath);
+          await compressing.zip.uncompress(
+            zipFullPath,
+            `${uncompressFilePath}${sep}${name}`
+          );
         } catch (error) {
+          await this.dirDelete(uncompressFilePath);
           errorList.push({
-            key: patentNumber,
-            word: `解析xml数据中的 申请号 和 专利名称 失败 于:${xmlPath}`,
+            patent_key: p,
+            content: '內部解压包,解压发生错误',
           });
-          continue;
         }
-        if (!xmlData) {
-          errorList.push({ key: patentNumber, word: '未找到xml的数据' });
-          continue;
-        }
-        let result;
-        try {
-          result = await this.getPatent(xmlData);
-        } catch (error) {
-          errorList.push({ key: patentNumber, word: '查询专利信息失败' });
-          continue;
-        }
-        // 找不到就算了,弹回去了
-        if (!result || !_.get(result, 'patent')) {
-          errorList.push({
-            key: patentNumber,
-            word: '未通过 申请号 或 专利名称 找到指定专利',
-          });
-          continue;
-        }
-        const patent = _.get(result, 'patent');
+      }
+      // 删除zip
+      await this.deleteZip(uncompressFilePath);
+      tempDir = fs.readdirSync(tempDirRootPath);
+    }
+    for (const tempDirPath of tempDir) {
+      if (tempDirPath.includes('.zip')) continue;
+      const thisDirPath = Path.resolve(tempDirRootPath, tempDirPath);
+      const patentNumber = tempDirPath;
+      // 找到
+      let filePaths = [];
+      try {
+        filePaths = await this.findFileNameLoop(thisDirPath);
+      } catch (error) {
+        errorList.push({
+          patent_key: patentNumber,
+          content: '格式不对',
+        });
+        continue;
+      }
+      if (filePaths.length <= 0) {
+        errorList.push({ patent_key: patentNumber, content: '未找到文件' });
+        continue;
+      }
+      // 2021-10-16 修改: 取出第一层的xml文件,即:路径最短的;除文件名外,字符串长度最小的
+      let xmlPaths = filePaths.filter(f => f.includes('.xml'));
+      if (xmlPaths.length > 0) {
+        // 去掉文件名
+        xmlPaths = xmlPaths.map(i => {
+          const arr = i.split(sep);
+          arr.pop();
+          const obj = { dir: arr.join(sep), fullPath: i };
+          return obj;
+        });
+        xmlPaths = xmlPaths.filter(f => f.fullPath.includes('list.xml'));
+      }
+      const xmlPath = _.get(_.head(xmlPaths), 'fullPath');
+      if (!xmlPath) {
+        errorList.push({ patent_key: patentNumber, content: '未找到xml文件' });
+        continue;
+      }
+      let xmlData;
+      try {
+        xmlData = await this.dealXml(xmlPath);
+      } catch (error) {
+        errorList.push({
+          patent_key: patentNumber,
+          content: `解析xml数据中的 申请号 和 专利名称 失败 于:${xmlPath}`,
+          ...xmlData,
+        });
+        continue;
+      }
+      if (!xmlData) {
+        errorList.push({
+          patent_key: patentNumber,
+          content: '未找到xml的数据',
+        });
+        continue;
+      }
+      /**
+       * @property {Array} patent 专利信息
+       * @property {Boolean || null} needChange 是否修改数据
+       */
+      let result;
+      try {
+        result = await this.getPatent(xmlData);
+      } catch (error) {
+        errorList.push({
+          patent_key: patentNumber,
+          content: '查询专利信息失败',
+          ...xmlData,
+        });
+        continue;
+      }
+      // 2022-09-02 数组处理模式 ↑
+      const patents = _.get(result, 'patent');
+      if (!patents || patents.length <= 0) {
+        errorList.push({
+          patent_key: patentNumber,
+          content: '未通过 申请号 或 专利名称 找到指定专利',
+          ...xmlData,
+        });
+        continue;
+      }
+      for (const patent of patents) {
+        // 2022-09-02 原处理进入循环中处理
         let warningData;
         try {
           warningData = await this.getWarningData(patent);
         } catch (error) {
           errorList.push({
-            key: patentNumber,
-            word: '组织专利信息警告数据失败',
+            patent_key: patentNumber,
+            content: '组织专利信息警告数据失败',
+            ...xmlData,
           });
           continue;
         }
-        const tifPaths = filePaths.filter(f => f.includes('.tif'));
-        if (tifPaths && tifPaths.length > 0) {
+        // 2023-02-07 原来是.tif,现在是.pdf
+        const uploadPaths = filePaths.filter(f => f.includes('.pdf'));
+        if (uploadPaths && uploadPaths.length > 0) {
           try {
-            await this.toUploadTif(warningData, tifPaths);
+            await this.toUploadFile(warningData, uploadPaths);
           } catch (error) {
-            errorList.push({ key: patentNumber, word: '存储数据失败' });
+            errorList.push({
+              patent_key: patentNumber,
+              content: '存储数据失败',
+              ...xmlData,
+            });
             continue;
           }
         }
-        // 查看是否需要更改申请号
-        const needChange = _.get(result, 'needChange');
-        if (needChange) {
-          try {
-            await this.ApplyModel.updateOne({ _id: patent._id }, patent);
-          } catch (error) {
-            continue;
-          }
-        }
-      } finally {
-        try {
-          await this.dirDelete(`${thisDirPath}`);
-        } catch (error) {
-          this.ctx.logger.error('清除缓存失败');
-        }
       }
     }
+    try {
+      await this.dirDelete(uncompressFilePath);
+    } catch (error) {
+      this.ctx.logger.error('清除缓存失败');
+    }
+    // 2022-09-05 将错误信息添加到表中
+    errorList = errorList.map(i => ({
+      ...i,
+      zip_url: uri,
+      create_date: moment().format('YYYY-MM-DD HH:mm:ss'),
+    }));
+    await this.errorModel.insertMany(errorList);
     if (errorList.length > 0) return errorList;
     return 'ok';
   }
@@ -177,8 +216,9 @@ export class CpcMessageService extends BaseService<modelType> {
    * @param {Array} data 警告数据,未保存
    * @param {Array} files tif图片文件路径数组
    */
-  async toUploadTif(data, files) {
+  async toUploadFile(data, files) {
     const filePaths = [];
+    let name = '';
     const savePath = new ObjectId();
     for (const file of files) {
       let arr = file.split(sep);
@@ -192,6 +232,7 @@ export class CpcMessageService extends BaseService<modelType> {
       const randomStr = new ObjectId();
       // 新文件名带后缀
       const newFileName = `${randomStr}.${ext}`;
+      name = newFileName;
       // 上传后部分路径
       const shortPath = `platform${sep}patent${sep}${savePath}${sep}`;
       // 上传全路径
@@ -210,7 +251,11 @@ export class CpcMessageService extends BaseService<modelType> {
       filePaths.push(dataPath);
     }
     for (const i of data) {
-      i.file_url = filePaths;
+      i.warn_file = {
+        name: name,
+        uri: filePaths,
+      };
+      i.send_date = moment().format('YYYY-MM-DD');
     }
     const res = await this.model.insertMany(data);
     return res;
@@ -243,19 +288,41 @@ export class CpcMessageService extends BaseService<modelType> {
    */
   async getWarningData(patent) {
     const object: any = {};
+    const arr = [];
     if (_.get(patent, 'create_number'))
       object.create_number = _.get(patent, 'create_number');
-    if (_.get(patent, 'id')) object.patent_id = _.get(patent, 'id');
+    if (_.get(patent, '_id')) object.patent_id = _.get(patent, '_id');
     if (_.get(patent, 'name')) object.patent_name = _.get(patent, 'name');
     // 找人的信息
-    const users = _.get(patent, 'inventor');
-    const arr = [];
-    for (const user of users) {
-      if (!_.get(user, 'user_id') || !_.get(user, 'name')) continue;
-      const { user_id, name } = user;
+    const users = _.get(patent, 'users');
+    if (users && _.isArray(users)) {
+      for (const user of users) {
+        if (!_.get(user, 'user_id') || !_.get(user, 'name')) continue;
+        const { user_id, name } = user;
+        const obj = _.cloneDeep(object);
+        obj.receive_id = user_id;
+        obj.receive_name = name;
+        arr.push(obj);
+      }
+      // 2021-11-18 添加,user,mech,admin,agentmech是否存在,如果存在,也添加预警信息
+      const list = ['user', 'mech', 'admin', 'agentmech'];
+      const suffix = ['id', 'name'];
+      for (const prefix of list) {
+        const marr = suffix.map(i => `${prefix}_${i}`);
+        const r = marr.every(i => _.get(patent, i));
+        if (r) {
+          const obj = _.cloneDeep(object);
+          for (const key of suffix) {
+            obj[`to_${key}`] = _.get(patent, `${prefix}_${key}`);
+          }
+          arr.push(obj);
+        }
+      }
+    } else if (users) {
       const obj = _.cloneDeep(object);
-      obj.to_id = user_id;
-      obj.to_name = name;
+      const name = _.get(patent, 'user_name');
+      obj.receive_id = users;
+      obj.receive_name = name;
       arr.push(obj);
     }
     return arr;
@@ -266,28 +333,35 @@ export class CpcMessageService extends BaseService<modelType> {
    * @param {Object} object xml的数据
    */
   async getPatent(object) {
-    const { name, create_number } = object;
-    let res;
-    let needChange = false;
-    res = await this.ApplyModel.findOne({ create_number });
-    // 如果在申请中,使用名称找到,则之后需要将该数据的专利号改为xml中的专利号
-    if (!res) {
-      res = await this.ApplyModel.findOne({ name });
-      needChange = true;
-    }
-    if (!res) {
-      res = await this.PatentModel.findOne({ create_number });
-    }
-    if (!res) {
-      res = await this.PatentModel.findOne({ name });
+    let { create_number } = object;
+    const name = object.name;
+    create_number = `CN${create_number}`;
+    const arr = create_number.split('');
+    arr.splice(arr.length - 1, 0, '.');
+    create_number = arr.join('');
+    const needChange = false;
+    // 2022-09-02 改为多条数据查询,不再针对一个数据
+    // 1,名称相同,关联人不同:
+    const listPA = await this.ApplyModel.find({
+      $or: [{ create_number }, { name }],
+    });
+    for (const i of listPA) {
+      const { create_number: ocn, _id } = i;
+      // create_number 不一致,就去更改
+      if (ocn !== create_number)
+        await this.ApplyModel.updateOne({ _id }, { create_number });
     }
+    const listPI = await this.PatentModel.find({
+      $or: [{ create_number }, { name }],
+    });
+    const res = [...listPA, ...listPI];
     const returnObject: any = {};
-    if (res) {
+    if (res.length > 0) {
+      returnObject.patent = JSON.parse(JSON.stringify(res));
       if (needChange) {
-        res.create_number = create_number;
+        returnObject.create_number = create_number;
         returnObject.needChange = needChange;
       }
-      returnObject.patent = res;
       return returnObject;
     }
     return null;
@@ -298,20 +372,20 @@ export class CpcMessageService extends BaseService<modelType> {
    * @param {String} filePath xml的文件路径
    */
   async dealXml(filePath) {
-    const buffer = await fs.readFileSync(filePath);
-    let str = encoding.convert(buffer, 'UTF-8', 'GBK');
-    if (!str)
+    const buffer = await fs.readFileSync(filePath, { encoding: 'utf8' });
+    if (!buffer)
       throw new ServiceError(
         '读取xml文件失败',
         FrameworkErrorEnum.REQUEST_FAULT
       );
-    str = str.toString();
-    const json = fxp.parse(str);
+    const json = JSON.parse(
+      cOnvert.xml2json(buffer, { compact: true, spaces: 4 })
+    );
     const create_number = _.get(
       json,
-      'data-bus.TONGZHISXJ.SHUXINGXX.SHENQINGH'
+      'data-bus.TONGZHISXJ.SHUXINGXX.SHENQINGH._text'
     );
-    const name = _.get(json, 'data-bus.TONGZHISXJ.SHUXINGXX.FAMINGMC');
+    const name = _.get(json, 'data-bus.TONGZHISXJ.SHUXINGXX.FAMINGMC._text');
     if (!name) return null;
     return { name, create_number };
   }
@@ -322,14 +396,14 @@ export class CpcMessageService extends BaseService<modelType> {
    * @param {String} uri temp路径
    */
   async findFileNameLoop(uri) {
-    const filePath = `${_.trimEnd(uri, sep)}${sep}`;
+    const filePath = uri;
     if (!fs.existsSync(filePath)) {
       return [];
     }
     const files = fs.readdirSync(filePath);
     let result = [];
     for (const file of files) {
-      const curPath = `${filePath}${file}`;
+      const curPath = Path.resolve(filePath, file);
       if (fs.statSync(curPath).isDirectory()) {
         const arr = await this.findFileNameLoop(curPath);
         result.push(...arr);
@@ -337,7 +411,8 @@ export class CpcMessageService extends BaseService<modelType> {
         result.push(curPath);
       }
     }
-    result = result.filter(f => f.includes('.tif') || f.includes('.xml'));
+    // 2023-02-07 原来是.tif,现在是.pdf
+    result = result.filter(f => f.includes('.pdf') || f.includes('.xml'));
     return result;
   }
 
@@ -359,4 +434,18 @@ export class CpcMessageService extends BaseService<modelType> {
       fs.rmdirSync(filePath);
     }
   }
+  /**
+   * 删除路径下的所有zip
+   * @param {String} filePath 路径
+   */
+  async deleteZip(filePath) {
+    if (!fs.existsSync(filePath)) return;
+    const files = fs.readdirSync(filePath);
+    for (const file of files) {
+      if (!file.includes('.zip')) continue;
+      const curPath = `${filePath}${sep}${file}`;
+      if (!fs.existsSync(curPath)) continue;
+      fs.unlinkSync(curPath);
+    }
+  }
 }