initTwo.service.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. import { Provide } from '@midwayjs/core';
  2. import { InjectEntityModel } from '@midwayjs/typeorm';
  3. import * as Excel from 'exceljs';
  4. import * as path from 'path';
  5. import { And, Equal, Like, Not, Repository } from 'typeorm';
  6. import { Region } from '../../entity/system/region.entity';
  7. import { Company } from '../../entity/users/company.entity';
  8. import { DictData } from '../../entity/system/dictData.entity';
  9. import { Supply } from '../../entity/platform/supply.entity';
  10. import { differenceWith, get, isEqual, isObject, isString, last, take, trim } from 'lodash';
  11. import { Demand } from '../../entity/platform/demand.entity';
  12. import _ = require('lodash');
  13. import { Project } from '../../entity/platform/project.entity';
  14. import { Tags } from '../../entity/system/tags.entity';
  15. // 2024-06-24 导入
  16. @Provide()
  17. export class initTwoService {
  18. tags = ['20240624'];
  19. @InjectEntityModel(Tags)
  20. tagsModel: Repository<Tags>;
  21. @InjectEntityModel(Region)
  22. regionModel: Repository<Region>;
  23. @InjectEntityModel(Company)
  24. companyModel: Repository<Company>;
  25. @InjectEntityModel(DictData)
  26. dictDataModel: Repository<DictData>;
  27. @InjectEntityModel(Supply)
  28. supplyModel: Repository<Supply>;
  29. @InjectEntityModel(Demand)
  30. demandModel: Repository<Demand>;
  31. @InjectEntityModel(Project)
  32. projectModel: Repository<Project>;
  33. async initData() {
  34. // return await this.importCompany();
  35. // return await this.importSupply();
  36. // return await this.importDemand();
  37. // return await this.importProject();
  38. }
  39. async addTags() {
  40. const list = [{ title: '20240624' }, { title: '企业' }, { title: '供给' }, { title: '项目' }, { title: '需求' }];
  41. for (const i of list) {
  42. const num = await this.tagsModel.createQueryBuilder().where('title = :title', { title: i.title }).getCount();
  43. if (num <= 0) {
  44. await this.tagsModel.insert(i);
  45. }
  46. }
  47. }
  48. async addImportDataTags() {
  49. // company,supply,project 直接全表更新tags
  50. const ctags: any = [...this.tags, '企业'];
  51. await this.companyModel.update({}, { tags: ctags });
  52. const stags: any = [...this.tags, '供给'];
  53. await this.supplyModel.update({}, { tags: stags });
  54. const ptags: any = [...this.tags, '项目'];
  55. await this.projectModel.update({}, { tags: ptags });
  56. // demand 2024-06-23 至2024-06-25内的所有数据加标签
  57. const demandTags: any = [...this.tags, '需求'];
  58. await this.demandModel.createQueryBuilder().update().set({ tags: demandTags }).where('created_time BETWEEN :start AND :end', { start: '2024-06-23', end: '2024-06-25' }).execute();
  59. }
  60. /**
  61. * 获取excel表头对应的字段
  62. * @returns 表格列对应字段对象
  63. */
  64. companyMeta() {
  65. return {
  66. 2: 'area1',
  67. 3: 'area2',
  68. 4: 'name',
  69. 5: 'products',
  70. 6: 'type',
  71. 7: 'person',
  72. };
  73. }
  74. async importCompany() {
  75. const p = path.resolve(__dirname, '../../../importData/20240624', '重点企业库.xlsx');
  76. const wb = new Excel.Workbook();
  77. await wb.xlsx.readFile(p);
  78. const sheet = wb.getWorksheet('总表');
  79. if (!sheet) return;
  80. const meta = this.companyMeta();
  81. const specialDeal = {
  82. 新区: '新区',
  83. 高新区: '长春高新技术产业开发区',
  84. 经开: '长春经济技术开发区',
  85. 中韩: '中韩国际合作示范区',
  86. 汽开: '长春汽车经济技术开发区',
  87. // 医药高新区: '',
  88. // 中新食品区: '',
  89. };
  90. const allData = [];
  91. sheet.eachRow((row, ri) => {
  92. if (ri === 1 || ri === 2) {
  93. // 不处理
  94. } else {
  95. const obj = {};
  96. row.eachCell((cell, ci) => {
  97. const val = cell.value;
  98. const key = meta[ci];
  99. if (key) obj[key] = val;
  100. });
  101. allData.push(obj);
  102. }
  103. });
  104. // 需要处理下 area1和area2,这俩是需要放到 area中,在region中找到合适的数据后放到area []里
  105. for (const i of allData) {
  106. // #region 地区处理
  107. i.area = ['吉林省'];
  108. if (i.area2 === '医药高新区') {
  109. i.area.push('通化市', '医药高新区');
  110. } else if (i.area2 === '中新食品区') {
  111. i.area.push('吉林市', '医药高新区');
  112. } else {
  113. const builder = this.regionModel.createQueryBuilder();
  114. builder.where(`name like '%${i.area1}%'`);
  115. // builder.andWhere(`name Not Like '%省%'`);
  116. builder.andWhere(`level = 'city'`);
  117. builder.andWhere(`code like '22%'`);
  118. const r1 = await builder.getOne();
  119. const r2 = await this.regionModel.findOne({ where: { name: Like(`%${i.area2}%`), code: Like('22%'), level: Equal('area') } });
  120. if (r1) i.area.push(r1.name);
  121. if (r2) i.area.push(r2.name);
  122. else {
  123. // 需要特殊处理的
  124. const str = specialDeal[i.area2];
  125. if (str) i.area.push(str);
  126. }
  127. }
  128. delete i.area1;
  129. delete i.area2;
  130. // #endregion
  131. // #region 字典处理
  132. if (i.type === '农林牧渔业') {
  133. i.type = '0';
  134. } else if (i.type === '卫生和社会工作') {
  135. i.type = '16';
  136. } else {
  137. const typeDict = await this.dictDataModel.findOne({ where: { label: i.type } });
  138. if (typeDict) {
  139. i.type = typeDict.value;
  140. }
  141. }
  142. // #endregion
  143. }
  144. await this.companyModel.insert(allData);
  145. }
  146. supplyMeta() {
  147. return {
  148. 3: 'industry',
  149. 4: 'field',
  150. 5: 'name',
  151. 6: 'brief',
  152. 7: 'source',
  153. };
  154. }
  155. async importSupply() {
  156. const p = path.resolve(__dirname, '../../../importData/20240624', '供应库.xlsx');
  157. const wb = new Excel.Workbook();
  158. await wb.xlsx.readFile(p);
  159. const sheet = wb.getWorksheet('总库');
  160. if (!sheet) return;
  161. const meta = this.supplyMeta();
  162. const allData = [];
  163. sheet.eachRow((row, ri) => {
  164. if (ri === 1 || ri === 2) {
  165. // 不处理
  166. } else {
  167. const obj = {};
  168. row.eachCell((cell, ci) => {
  169. const val = cell.value;
  170. const key = meta[ci];
  171. if (key) obj[key] = val;
  172. });
  173. allData.push(obj);
  174. }
  175. });
  176. // TODO:将产业,领域换成字典表
  177. // return allData;
  178. await this.supplyModel.insert(allData);
  179. }
  180. demandMeta() {
  181. return {
  182. 4: 'industry',
  183. 5: 'field',
  184. 6: 'area1',
  185. 7: 'area2',
  186. 8: 'company',
  187. 9: 'tec_name',
  188. 10: 'company_brief',
  189. 11: 'question',
  190. 12: 'brief',
  191. 13: 'year',
  192. 14: 'month',
  193. 15: 'contacts',
  194. 16: 'tel',
  195. };
  196. }
  197. async importDemand() {
  198. const p = path.resolve(__dirname, '../../../importData/20240624', '需求库.xlsx');
  199. const wb = new Excel.Workbook();
  200. await wb.xlsx.readFile(p);
  201. const sheet = wb.getWorksheet('3-技术需求库-打印');
  202. if (!sheet) return;
  203. const meta = this.demandMeta();
  204. const specialArea1Deal = {
  205. 延边州: '延边朝鲜族自治州',
  206. };
  207. const specialArea2Deal = {
  208. 新区: '新区',
  209. 高新区: '长春高新技术产业开发区',
  210. 经开: '长春经济技术开发区',
  211. 中韩: '中韩国际合作示范区',
  212. 汽开: '长春汽车经济技术开发区',
  213. 汽开区: '长春汽车经济技术开发区',
  214. // 医药高新区: '',
  215. // 中新食品区: '',
  216. };
  217. const allData = [];
  218. sheet.eachRow((row, ri) => {
  219. if (ri === 1 || ri === 2 || ri === 3) {
  220. // 不处理
  221. } else {
  222. const obj = {};
  223. row.eachCell((cell, ci) => {
  224. const val = cell.value;
  225. const key = meta[ci];
  226. if (key) obj[key] = val;
  227. });
  228. if (get(obj, 'company') && trim(get(obj, 'company')) !== '') allData.push(obj);
  229. }
  230. });
  231. for (const i of allData) {
  232. // #region 地区处理
  233. i.area = ['吉林省'];
  234. if (i.area2 === '医药高新区') {
  235. i.area.push('通化市', '医药高新区');
  236. } else if (i.area2 === '中新食品区') {
  237. i.area.push('吉林市', '医药高新区');
  238. } else {
  239. const builder = this.regionModel.createQueryBuilder();
  240. builder.where(`name like '%${i.area1}%'`);
  241. // builder.andWhere(`name Not Like '%省%'`);
  242. builder.andWhere(`level = 'city'`);
  243. builder.andWhere(`code like '22%'`);
  244. const r1 = await builder.getOne();
  245. const r2 = await this.regionModel.findOne({ where: { name: Like(`%${i.area2}%`), code: Like('22%'), level: Equal('area') } });
  246. if (r1) {
  247. i.area.push(r1.name);
  248. delete i.area1;
  249. } else {
  250. const area = specialArea1Deal[i.area1];
  251. if (area) {
  252. i.area.push(area);
  253. delete i.area1;
  254. }
  255. }
  256. if (r2) {
  257. i.area.push(r2.name);
  258. delete i.area2;
  259. } else {
  260. // 需要特殊处理的
  261. const area = specialArea2Deal[i.area2];
  262. if (area) {
  263. i.area.push(area);
  264. }
  265. // 还有一种情况就是省市都写的一个.就不需要第二个了,所以最后一定删除
  266. delete i.area2;
  267. }
  268. }
  269. // #endregion
  270. }
  271. // return allData.filter(f => f.area1 || f.area2);
  272. await this.demandModel.insert(allData);
  273. }
  274. projectMeta() {
  275. return {
  276. 3: 'name',
  277. 4: 'brief',
  278. 5: 'main',
  279. 6: 'progress',
  280. 7: 'track_unit',
  281. 8: 'source',
  282. };
  283. }
  284. projectIndustryMeta() {
  285. return [
  286. { size: 33, value: '汽车电子及新型汽车零部件' },
  287. { size: 30, value: '光电子及智能传感器' },
  288. { size: 24, value: '精密仪器及先进装备' },
  289. { size: 60, value: '生物医药及先进医疗器械' },
  290. { size: 4, value: '车规级芯片及功率半导体器件' },
  291. { size: 13, value: '人工智能及智能机器人' },
  292. { size: 24, value: '生物基及高性能新材料' },
  293. { size: 25, value: '新能源及动力电池' },
  294. { size: 10, value: '碳纤维及复合材料' },
  295. { size: 5, value: '遥感卫星及航空航天' },
  296. { size: 10, value: '精细化工及天然气化工' },
  297. { size: 20, value: '农产品加工及绿色食品' },
  298. { size: 5, value: '孵化平台' },
  299. { size: 9, value: '产业技术创新平台' },
  300. ];
  301. }
  302. async importProject() {
  303. const p = path.resolve(__dirname, '../../../importData/20240624', '项目库.xlsx');
  304. const wb = new Excel.Workbook();
  305. await wb.xlsx.readFile(p);
  306. const sheet = wb.getWorksheet('统计表');
  307. if (!sheet) return;
  308. const meta = this.projectMeta();
  309. let allData = [];
  310. const notDealRows = [1, 2, 3, 4, 5];
  311. const industryMeta = this.projectIndustryMeta();
  312. sheet.eachRow((row, ri) => {
  313. if (notDealRows.includes(ri)) {
  314. // 不处理
  315. } else {
  316. const obj = {};
  317. row.eachCell((cell, ci) => {
  318. const val = cell.value;
  319. const key = meta[ci];
  320. if (key) {
  321. obj[key] = val;
  322. }
  323. });
  324. const res = industryMeta.find(f => f.value === get(obj, 'name'));
  325. if (!res) {
  326. for (const key in obj) {
  327. if (!isString(obj[key])) {
  328. const rtobj = get(obj[key], 'richText');
  329. let text = '';
  330. if (rtobj) {
  331. for (const i of rtobj) {
  332. text = `${text}${i.text}`;
  333. }
  334. }
  335. obj[key] = text;
  336. }
  337. }
  338. allData.push(obj);
  339. }
  340. }
  341. });
  342. // 分组,然后给加上产业字段
  343. const newData = [];
  344. for (const meta of industryMeta) {
  345. const { size, value } = meta;
  346. const nds = take(allData, size);
  347. for (const i of nds) {
  348. i.industry = value;
  349. }
  350. newData.push(...nds);
  351. // 删除提取出来的数据
  352. allData = differenceWith(allData, nds, isEqual);
  353. }
  354. await this.projectModel.insert(newData);
  355. // return newData;
  356. }
  357. }