123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const { ObjectId } = require('mongoose').Types;
- const _ = require('lodash');
- const compressing = require('compressing');
- const { sep } = require('path');
- const path = require('path');
- const fs = require('fs');
- const encoding = require('encoding'); // 编码转换
- const fxp = require('fast-xml-parser'); // xml转换
- // 专利运营专利申请预警表
- class PatentwarningService extends CrudService {
- constructor(ctx) {
- super(ctx, 'patentwarning');
- this.model = this.ctx.model.Patent.Patentwarning;
- this.import_root_path = _.get(this.ctx.app.config.import, 'root_path');
- this.patentInfo = this.ctx.model.Patent.Patentinfo;
- this.patentApply = this.ctx.model.Patent.Patentapply;
- this.personalModel = this.ctx.model.User.Personal;
- }
- async import({ uri }) {
- uri = uri.replace('/files', this.import_root_path);
- const fileFullName = path.basename(uri);
- const arr = fileFullName.split('.');
- const ext = _.last(arr);
- const uncompressFilePath = `${this.import_root_path}${sep}temp`;
- if (ext !== 'zip') {
- throw new BusinessError(ErrorCode.FILE_FAULT, '只接收压缩格式为zip的压缩包');
- }
- // 解压
- try {
- await compressing.zip.uncompress(uri, `${uncompressFilePath}`);
- } catch (error) {
- throw new BusinessError(ErrorCode.FILE_FAULT, '解压失败');
- }
- // 修改,多个专利:需要扫描下解压后的文件夹,然后循环处理下面所有的内容
- const tempDirRootPath = `${uncompressFilePath}${sep}`;
- const tempDir = await fs.readdirSync(tempDirRootPath);
- const errorList = [];
- for (const tempDirPath of tempDir) {
- const thisDirPath = `${tempDirRootPath}${sep}${tempDirPath}`;
- const patentNumber = tempDirPath;
- try {
- // 找到
- let filePaths = [];
- try {
- filePaths = await this.findFileNameLoop(thisDirPath);
- } 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;
- // throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到xml文件');
- }
- let xmlData;
- try {
- xmlData = await this.dealXml(xmlPath);
- } catch (error) {
- errorList.push({ key: patentNumber, word: `解析xml数据中的 申请号 和 专利名称 失败 于:${xmlPath}` });
- continue;
- // throw new BusinessError(ErrorCode.SERVICE_FAULT, '解析申请号失败');
- }
- if (!xmlData) {
- errorList.push({ key: patentNumber, word: '未找到xml的数据' });
- continue;
- // throw new BusinessError(ErrorCode.FILE_FAULT, '未找到申请号');
- }
- let result;
- try {
- result = await this.getPatent(xmlData);
- } catch (error) {
- errorList.push({ key: patentNumber, word: '查询专利信息失败' });
- continue;
- // throw new BusinessError(ErrorCode.SERVICE_FAULT, '查询专利信息失败');
- }
- // 找不到就算了,弹回去了
- if (!result || !_.get(result, 'patent')) {
- errorList.push({ key: patentNumber, word: '未通过 申请号 或 专利名称 找到指定专利' });
- continue;
- // throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未通过申请号找到指定专利');
- }
- const patent = _.get(result, 'patent');
- let warningData;
- try {
- warningData = await this.getWarningData(patent);
- } catch (error) {
- errorList.push({ key: patentNumber, word: '组织专利信息警告数据失败' });
- continue;
- // throw new BusinessError(ErrorCode.SERVICE_FAULT, '组织专利信息警告数据失败');
- }
- const tifPaths = filePaths.filter(f => f.includes('.tif'));
- if (tifPaths && tifPaths.length > 0) {
- try {
- await this.toUploadTif(warningData, tifPaths);
- } catch (error) {
- errorList.push({ key: patentNumber, word: '存储数据失败' });
- continue;
- }
- }
- // 查看是否需要更改申请号
- const needChange = _.get(result, 'needChange');
- if (needChange) {
- try {
- await this.patentApply.updateOne({ _id: patent._id }, patent);
- } catch (error) {
- // errorList.push({ key: patentNumber, word: 'xml申请号同步至专利申请号失败' });
- continue;
- }
- }
- } finally {
- try {
- await this.dirDelete(`${thisDirPath}`);
- } catch (error) {
- this.ctx.logger.error('清除缓存失败');
- }
- }
- }
- if (errorList.length > 0) return errorList;
- return 'ok';
- }
- /**
- * 上传图片,保存
- * @param {Array} data 警告数据,未保存
- * @param {Array} files tif图片文件路径数组
- */
- async toUploadTif(data, files) {
- const filePaths = [];
- const savePath = ObjectId();
- for (const file of files) {
- let arr = file.split(sep);
- const fullFileName = _.last(arr);
- arr = fullFileName.split('.');
- // 文件后缀
- const ext = _.last(arr);
- // 图片文件
- const buffer = await fs.readFileSync(file);
- // 新文件名
- const randomStr = ObjectId();
- // 新文件名带后缀
- const newFileName = `${randomStr}.${ext}`;
- // 上传后部分路径
- const shortPath = `platform${sep}patent${sep}${savePath}${sep}`;
- // 上传全路径
- const path = `${this.import_root_path}${sep}${shortPath}`;
- // 检查上传全路径是否存在,不存在就创建文件夹
- await this.checkPathAndCreate(path);
- // 另存文件
- await fs.writeFileSync(`${path}${newFileName}`, buffer);
- // 替换为files开头
- let dataPath = path.replace(this.import_root_path, '/files');
- while (dataPath.indexOf('\\') >= 0) {
- dataPath = dataPath.replace('\\', '/');
- }
- // 补全请求用路径的所有路径
- dataPath += newFileName;
- filePaths.push(dataPath);
- }
- for (const i of data) {
- i.file_url = filePaths;
- }
- const res = await this.model.insertMany(data);
- return res;
- }
- /**
- * 检查路径,没有创建
- * @param {Array} filePath 图片路径数组
- */
- async checkPathAndCreate(filePath) {
- const arr = filePath.split(sep);
- // w:第一个是盘符,直接和第二个合并
- // l:前几个应该都是存在的.也可以合并
- let head = _.head(arr);
- if (arr[1]) head = `${head}${sep}${arr[1]}`;
- arr.shift();
- arr[0] = head;
- let curPath;
- for (const p of arr) {
- curPath = `${curPath ? curPath + sep : ''}${p}`;
- if (!fs.existsSync(curPath)) {
- await fs.mkdirSync(curPath);
- }
- }
- }
- /**
- * 组织专利预警数据
- * @param {Object} patent 专利
- */
- async getWarningData(patent) {
- const object = {};
- 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, 'name')) object.patent_name = _.get(patent, 'name');
- // 找人的信息
- const users = _.get(patent, 'user_id');
- 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.to_id = user_id;
- obj.to_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);
- const name = _.get(patent, 'user_name');
- obj.to_id = users;
- obj.to_name = name;
- arr.push(obj);
- }
- return arr;
- }
- /**
- * 在patentApply/patentInfo表中找指定的专利
- * @param {Object} object xml的数据
- */
- async getPatent(object) {
- const { name, create_number } = object;
- let res;
- let needChange = false;
- res = await this.patentApply.findOne({ create_number });
- // 如果在申请中,使用名称找到,则之后需要将该数据的专利号改为xml中的专利号
- if (!res) {
- res = await this.patentApply.findOne({ name });
- needChange = true;
- }
- if (!res) {
- res = await this.patentInfo.findOne({ create_number });
- }
- if (!res) {
- res = await this.patentInfo.findOne({ name });
- }
- const returnObject = {};
- if (res) {
- if (needChange) {
- res.create_number = create_number;
- returnObject.needChange = needChange;
- }
- returnObject.patent = res;
- return returnObject;
- }
- return null;
- }
- /**
- * 根据路径找到xml,再找到该xml的申请号和专利名称
- * @param {String} filePath xml的文件路径
- */
- async dealXml(filePath) {
- const buffer = await fs.readFileSync(filePath);
- let str = encoding.convert(buffer, 'UTF8', 'GBK');
- if (!str) throw new BusinessError(ErrorCode.FILE_FAULT, '读取xml文件失败');
- str = str.toString();
- const json = fxp.parse(str);
- const create_number = _.get(json, 'data-bus.TONGZHISXJ.SHUXINGXX.SHENQINGH');
- const name = _.get(json, 'data-bus.TONGZHISXJ.SHUXINGXX.FAMINGMC');
- if (!name) return null;
- return { name, create_number };
- }
- /**
- * 找到深层的tif和xml
- * 因为命名方式都是以文件名,之后tif的文件夹也在深层fileName.套娃且文件名都是fileName
- * @param {String} uri temp路径
- */
- async findFileNameLoop(uri) {
- const filePath = `${_.trimEnd(uri, sep)}${sep}`;
- if (!fs.existsSync(filePath)) {
- return [];
- }
- const files = fs.readdirSync(filePath);
- let result = [];
- for (const file of files) {
- const curPath = `${filePath}${file}`;
- if (fs.statSync(curPath).isDirectory()) {
- const arr = await this.findFileNameLoop(curPath);
- result.push(...arr);
- } else {
- result.push(curPath);
- }
- }
- result = result.filter(f => f.includes('.tif') || f.includes('.xml'));
- return result;
- }
- /**
- * 删除路径下的所有内容
- * @param {String} filePath 路径
- */
- async dirDelete(filePath) {
- if (fs.existsSync(filePath)) {
- const files = fs.readdirSync(filePath);
- for (const file of files) {
- const curPath = `${filePath}${sep}${file}`;
- if (fs.statSync(curPath).isDirectory()) {
- // recurse
- this.dirDelete(curPath);
- } else {
- // delete file
- fs.unlinkSync(curPath);
- }
- }
- fs.rmdirSync(filePath);
- }
- }
- }
- module.exports = PatentwarningService;
|