patentwarning.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. 'use strict';
  2. const { CrudService } = require('naf-framework-mongoose/lib/service');
  3. const { BusinessError, ErrorCode } = require('naf-core').Error;
  4. const { ObjectId } = require('mongoose').Types;
  5. const _ = require('lodash');
  6. const assert = require('assert');
  7. const compressing = require('compressing');
  8. const { sep } = require('path');
  9. const path = require('path');
  10. const fs = require('fs');
  11. const encoding = require('encoding'); // 编码转换
  12. const fxp = require('fast-xml-parser'); // xml转换
  13. const mime = require('mime-types'); // 任意类型转换
  14. // 专利运营专利申请预警表
  15. class PatentwarningService extends CrudService {
  16. constructor(ctx) {
  17. super(ctx, 'patentwarning');
  18. this.model = this.ctx.model.Patent.Patentwarning;
  19. this.import_root_path = _.get(this.ctx.app.config.import, 'root_path');
  20. this.patentInfo = this.ctx.model.Patent.Patentinfo;
  21. this.patentApply = this.ctx.model.Patent.Patentapply;
  22. this.personalModel = this.ctx.model.Personal;
  23. }
  24. async import({ uri }) {
  25. uri = uri.replace('/files', this.import_root_path);
  26. const fileFullName = path.basename(uri);
  27. const arr = fileFullName.split('.');
  28. const ext = _.last(arr);
  29. const fileName = _.head(arr);
  30. const uncompressFilePath = `${this.import_root_path}${sep}`;
  31. if (ext !== 'zip') {
  32. throw new BusinessError(ErrorCode.FILE_FAULT, '只接收压缩格式为zip的压缩包');
  33. }
  34. // 解压
  35. try {
  36. await compressing.zip.uncompress(uri, `${uncompressFilePath}`);
  37. } catch (error) {
  38. throw new BusinessError(ErrorCode.FILE_FAULT, '解压失败');
  39. }
  40. // 找到
  41. let filePaths = [];
  42. try {
  43. filePaths = await this.findFileNameLoop(uncompressFilePath, fileName);
  44. } catch (error) {
  45. throw new BusinessError(ErrorCode.SERVICE_FAULT, '解析文件具体位置失败');
  46. }
  47. if (filePaths.length <= 0) {
  48. throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到文件');
  49. }
  50. const xmlPath = filePaths.find(f => f.includes('.xml'));
  51. if (!xmlPath) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到xml文件');
  52. let create_number;
  53. try {
  54. create_number = await this.dealXml(xmlPath);
  55. } catch (error) {
  56. throw new BusinessError(ErrorCode.SERVICE_FAULT, '解析申请号失败');
  57. }
  58. if (!create_number) throw new BusinessError(ErrorCode.FILE_FAULT, '未找到申请号');
  59. let result;
  60. try {
  61. result = await this.getPatentFromInfo(create_number);
  62. } catch (error) {
  63. throw new BusinessError(ErrorCode.SERVICE_FAULT, '查询专利信息失败');
  64. }
  65. // 再找
  66. if (!result) result = await this.getPatentFromApply(create_number);
  67. // 找不到就算了,弹回去了
  68. if (!result) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未通过申请号找到指定专利');
  69. let warningData;
  70. try {
  71. warningData = await this.getWarningData(result);
  72. } catch (error) {
  73. throw new BusinessError(ErrorCode.SERVICE_FAULT, '组织专利信息警告数据失败');
  74. }
  75. const tifPaths = filePaths.filter(f => f.includes('.tif'));
  76. if (tifPaths && tifPaths.length > 0) this.toUploadTif(warningData, tifPaths);
  77. await this.dirDelete(`${uncompressFilePath}${fileName}`);
  78. return 'ok';
  79. }
  80. /**
  81. * 上传图片,保存
  82. * @param {Array} data 警告数据,未保存
  83. * @param {Array} files tif图片文件路径数组
  84. */
  85. async toUploadTif(data, files) {
  86. const filePaths = [];
  87. const savePath = ObjectId();
  88. for (const file of files) {
  89. let arr = file.split(sep);
  90. const fullFileName = _.last(arr);
  91. arr = fullFileName.split('.');
  92. // 文件后缀
  93. const ext = _.last(arr);
  94. console.log('file');
  95. console.log(file);
  96. // 图片文件
  97. const buffer = await fs.readFileSync(file);
  98. // 新文件名
  99. const randomStr = ObjectId();
  100. // 新文件名带后缀
  101. const newFileName = `${randomStr}.${ext}`;
  102. // 上传后部分路径
  103. const shortPath = `platform${sep}patent${sep}${savePath}${sep}`;
  104. // 上传全路径
  105. const path = `${this.import_root_path}${sep}${shortPath}`;
  106. console.log('path');
  107. console.log(`${path}`);
  108. console.log('all');
  109. console.log(`${path}${newFileName}`);
  110. // 检查上传全路径是否存在,不存在就创建文件夹
  111. await this.checkPathAndCreate(path);
  112. // 另存文件
  113. console.log(`${path}${newFileName}`);
  114. await fs.writeFileSync(`${path}${newFileName}`, buffer);
  115. // 替换为files开头
  116. let dataPath = path.replace(this.import_root_path, '/files');
  117. while (dataPath.indexOf('\\') >= 0) {
  118. dataPath = dataPath.replace('\\', '/');
  119. }
  120. // 补全请求用路径的所有路径
  121. dataPath += newFileName;
  122. filePaths.push(dataPath);
  123. }
  124. for (const i of data) {
  125. i.file_url = filePaths;
  126. }
  127. const res = await this.model.insertMany(data);
  128. return res;
  129. }
  130. /**
  131. * 检查路径,没有创建
  132. * @param {Array} filePath 图片路径数组
  133. */
  134. async checkPathAndCreate(filePath) {
  135. const arr = filePath.split(sep);
  136. // w:第一个是盘符,直接和第二个合并
  137. // l:前几个应该都是存在的.也可以合并
  138. let head = _.head(arr);
  139. if (arr[1]) head = `${head}${sep}${arr[1]}`;
  140. arr.shift();
  141. arr[0] = head;
  142. let curPath;
  143. for (const p of arr) {
  144. curPath = `${curPath ? curPath + sep : ''}${p}`;
  145. if (!fs.existsSync(curPath)) {
  146. await fs.mkdirSync(curPath);
  147. }
  148. }
  149. }
  150. /**
  151. * 组织专利预警数据
  152. * @param {Object} patent 专利
  153. */
  154. async getWarningData(patent) {
  155. console.log(patent);
  156. const object = {};
  157. if (_.get(patent, 'create_number'))object.create_number = _.get(patent, 'create_number');
  158. if (_.get(patent, 'id'))object.patent_id = _.get(patent, 'id');
  159. if (_.get(patent, 'name'))object.patent_name = _.get(patent, 'name');
  160. // 找人的信息
  161. let userIds = _.get(patent, 'user_id', _.get(patent, 'inventer'));
  162. if (!userIds) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到专利的发明人');
  163. if (!_.isArray(userIds)) userIds = [ userIds ];
  164. userIds = userIds.map(i => ObjectId(i));
  165. const users = await this.personalModel.find({ _id: userIds });
  166. const arr = [];
  167. for (const user of users) {
  168. if (!_.get(user, '_id') || !_.get(user, 'name')) continue;
  169. const { _id, name } = user;
  170. const obj = _.cloneDeep(object);
  171. obj.to_id = _id;
  172. obj.to_name = name;
  173. arr.push(obj);
  174. }
  175. return arr;
  176. }
  177. /**
  178. * 在patentApply表中找指定的专利
  179. * @param {String} create_number 专利的申请号
  180. */
  181. async getPatentFromApply(create_number) {
  182. const res = await this.patentApply.findOne({ create_number });
  183. return res;
  184. }
  185. /**
  186. * 在patentInfo表中找指定的专利
  187. * @param {String} create_number 专利的申请号
  188. */
  189. async getPatentFromInfo(create_number) {
  190. const res = await this.patentInfo.findOne({ create_number });
  191. return res;
  192. }
  193. /**
  194. * 根据路径找到xml,再找到该xml的申请号
  195. * @param {String} filePath xml的文件路径
  196. */
  197. async dealXml(filePath) {
  198. const buffer = await fs.readFileSync(filePath);
  199. let str = encoding.convert(buffer, 'UTF8', 'GBK');
  200. if (!str) throw new BusinessError(ErrorCode.FILE_FAULT, '读取xml文件失败');
  201. str = str.toString();
  202. const json = fxp.parse(str);
  203. const create_number = _.get(json, 'data-bus.TONGZHISXJ.SHUXINGXX.SHENQINGH');
  204. return create_number;
  205. }
  206. /**
  207. * 找到深层的tif和xml
  208. * 因为命名方式都是以文件名,之后tif的文件夹也在深层fileName.套娃且文件名都是fileName
  209. * @param {String} uri temp路径
  210. * @param {String} fileName 文件名
  211. */
  212. async findFileNameLoop(uri, fileName) {
  213. const filePath = `${uri}${sep}${fileName}`;
  214. if (!fs.existsSync(filePath)) {
  215. return [];
  216. }
  217. const files = fs.readdirSync(filePath);
  218. let result = [];
  219. for (const file of files) {
  220. console.log(_.trimEnd(filePath));
  221. console.log(file);
  222. const curPath = `${_.trimEnd(filePath)}${sep}${file}`;
  223. if (fs.statSync(curPath).isDirectory()) {
  224. const res = await this.findFileNameLoop(curPath, file);
  225. result.push(...res);
  226. } else {
  227. result.push(curPath);
  228. }
  229. }
  230. result = result.filter(f => f.includes('.tif') || f.includes('.xml'));
  231. return result;
  232. }
  233. /**
  234. * 删除路径下的所有内容
  235. * @param {String} filePath 路径
  236. */
  237. async dirDelete(filePath) {
  238. if (fs.existsSync(filePath)) {
  239. const files = fs.readdirSync(filePath);
  240. for (const file of files) {
  241. const curPath = `${filePath}${sep}${file}`;
  242. if (fs.statSync(curPath).isDirectory()) { // recurse
  243. this.dirDelete(curPath);
  244. } else { // delete file
  245. fs.unlinkSync(curPath);
  246. }
  247. }
  248. fs.rmdirSync(filePath);
  249. }
  250. }
  251. }
  252. module.exports = PatentwarningService;