|
@@ -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);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|