review-details.component.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. import { Component, Input, OnInit } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { NzSpaceModule } from 'ng-zorro-antd/space';
  4. import { CommonCompModule } from '../../../../services/common.modules';
  5. import { ActivatedRoute, Router } from '@angular/router';
  6. import { NzMessageModule } from 'ng-zorro-antd/message';
  7. import { NzMessageService } from 'ng-zorro-antd/message';
  8. import Parse from 'parse';
  9. import { textbookServer } from '../../../../services/textbook';
  10. import { NzModalService } from 'ng-zorro-antd/modal';
  11. import { MatDialog } from '@angular/material/dialog';
  12. import { NzEmptyModule } from 'ng-zorro-antd/empty';
  13. import { DatePipe } from '@angular/common';
  14. import { NzPopoverModule } from 'ng-zorro-antd/popover';
  15. @Component({
  16. selector: 'app-review-details',
  17. templateUrl: './review-details.component.html',
  18. styleUrls: ['./review-details.component.scss'],
  19. imports: [
  20. CommonModule,
  21. NzSpaceModule,
  22. CommonCompModule,
  23. NzMessageModule,
  24. NzEmptyModule,
  25. NzPopoverModule,
  26. ],
  27. providers: [DatePipe],
  28. standalone: true,
  29. })
  30. export class ReviewDetailsComponent implements OnInit {
  31. reviewList: Array<Parse.Object> = [];
  32. count: number = 0;
  33. @Input('limit') limit: number = 10;
  34. pageIndex: number = 1;
  35. loading: boolean = false;
  36. @Input('maxWidth') maxWidth: any; //最大宽度
  37. @Input('eduProcess') eduProcess?: Parse.Object; //流程id,verify存在时需要
  38. @Input('listOfFilter') listOfFilter: Array<any> = []; //评审组
  39. @Input('filterObj') filterObj: any = {
  40. showGroup: false,
  41. contained: [],
  42. bookMap: {}, //教材对应评审组结构{booid:评审组名称}
  43. };
  44. searchValue: string = '';
  45. listOfColumns: any = {
  46. lang: {
  47. // listOfFilter: [{ value: '中文', text: '中文' }],
  48. onChange: (data: Array<string>) => {
  49. console.log(data);
  50. if (data?.length < 1) {
  51. this.filterObj.contained = Object.keys(this.filterObj.bookMap);
  52. } else {
  53. this.filterObj.contained = [];
  54. for (const key in this.filterObj.bookMap) {
  55. const item = this.filterObj.bookMap[key];
  56. if (data.includes(item.id)) {
  57. this.filterObj.contained.push(key);
  58. }
  59. }
  60. }
  61. this.getTextbook(this.searchValue);
  62. },
  63. },
  64. };
  65. showLoading: boolean = false; //全局
  66. time: any;
  67. /* 格式化拓展表字段 */
  68. fromatFiled(list: Array<Parse.Object>, filed: string): string {
  69. let arr: Array<string | null> = [];
  70. let isDate = false;
  71. list.forEach((item: Parse.Object) => {
  72. // arr.add(item.get(filed))
  73. if (
  74. isDate ||
  75. Object.prototype.toString.call(item.get(filed)).indexOf('Date') != -1
  76. ) {
  77. arr.push(this.datePipe.transform(item.get(filed), 'yyyy-MM'));
  78. isDate = true;
  79. } else {
  80. arr.push(item.get(filed));
  81. }
  82. });
  83. let j = Array.from(arr).join(',');
  84. if (!isDate) {
  85. j = Array.from(new Set(arr)).join(' ');
  86. }
  87. return j || '-';
  88. }
  89. constructor(
  90. private activeRoute: ActivatedRoute,
  91. public tbookSer: textbookServer,
  92. private router: Router,
  93. private msg: NzMessageService,
  94. public dialog: MatDialog,
  95. private route: Router,
  96. private datePipe: DatePipe,
  97. private modal: NzModalService
  98. ) {}
  99. ngOnInit() {
  100. this.getTextbook();
  101. }
  102. async getTextbook(val?: string, exported?: boolean): Promise<any[] | void> {
  103. if (this.loading) return;
  104. if (!exported) this.loading = true;
  105. try {
  106. let queryParams: any = {
  107. where: {
  108. $or: [
  109. {
  110. eduTextbook: {
  111. $inQuery: {
  112. where: {
  113. $or: [
  114. {
  115. title: { $regex: `.*${val || ''}.*` },
  116. },
  117. {
  118. childrens: {
  119. $inQuery: {
  120. where: {
  121. $or: [
  122. {
  123. ISBN: { $regex: `.*${val || ''}.*` },
  124. },
  125. {
  126. author: { $regex: `.*${val || ''}.*` },
  127. },
  128. ],
  129. },
  130. className: 'EduTextbookVolume',
  131. },
  132. },
  133. },
  134. ],
  135. },
  136. className: 'EduTextbook',
  137. },
  138. },
  139. },
  140. {
  141. profile: {
  142. $inQuery: {
  143. where: {
  144. $or: [
  145. {
  146. user: {
  147. $inQuery: {
  148. where: {
  149. $or: [
  150. {
  151. name: { $regex: `.*${val || ''}.*` },
  152. },
  153. ],
  154. },
  155. className: '_User',
  156. },
  157. },
  158. },
  159. ],
  160. },
  161. className: 'Profile',
  162. },
  163. },
  164. },
  165. ],
  166. eduTextbook: { $in: this.filterObj.contained },
  167. },
  168. };
  169. let query = Parse.Query.fromJSON('EduReview', queryParams);
  170. this.eduProcess?.id && query.equalTo('eduProcess', this.eduProcess.id);
  171. query.descending('updatedAt');
  172. query.notEqualTo('isDeleted', true);
  173. query.exists('score');
  174. query.equalTo('verify',true)
  175. query.include(
  176. 'eduTextbook',
  177. 'eduTextbook.childrens',
  178. 'profile',
  179. 'profile.user'
  180. );
  181. this.count = await query.count();
  182. query.limit(this.limit);
  183. query.skip(this.limit * (this.pageIndex - 1));
  184. if (exported) {
  185. query.limit(1000);
  186. let r = await query.find();
  187. this.loading = false;
  188. return r;
  189. }
  190. this.reviewList = await query.find();
  191. console.log(this.reviewList);
  192. this.loading = false;
  193. } catch (err) {
  194. console.warn(err);
  195. this.msg.error('获取超时');
  196. }
  197. this.loading = false;
  198. }
  199. onSearch(e: string) {
  200. this.pageIndex = 1;
  201. console.log(e);
  202. if (this.time) clearTimeout(this.time);
  203. this.time = setTimeout(() => {
  204. this.getTextbook(e);
  205. }, 500);
  206. }
  207. //分页切换
  208. pageIndexChange(e: any) {
  209. console.log(e);
  210. this.pageIndex = e;
  211. this.getTextbook(this.searchValue);
  212. }
  213. //切换分页条数
  214. onPageSizeChange(): void {
  215. console.log(this.limit);
  216. // this.onAllChecked(false)
  217. this.pageIndex = 1;
  218. this.getTextbook(this.searchValue);
  219. }
  220. toUrl(url: string, param?: Object) {
  221. console.log(url);
  222. if (param) {
  223. this.route.navigate([url, param]);
  224. return;
  225. }
  226. this.route.navigate([url]);
  227. }
  228. //导出表格
  229. async export() {
  230. if (this.showLoading) return;
  231. this.showLoading = true;
  232. try {
  233. let table;
  234. let data: any = await this.getTextbook('', true);
  235. if (this.filterObj.showGroup) {
  236. table = this.getActivityTable(data);
  237. } else {
  238. table = this.getTable(data);
  239. }
  240. let title = '评审明细表';
  241. this.excel(table, `${title}.xls`);
  242. this.showLoading = false;
  243. } catch (err) {
  244. console.log(err);
  245. this.showLoading = false;
  246. this.msg.error('导出超时');
  247. }
  248. }
  249. //合并后(活动详情)
  250. getActivityTable(data: Array<Parse.Object>): string {
  251. let groupMap: any = {};
  252. data.forEach((item: Parse.Object) => {
  253. let obj = {
  254. name: item?.get('profile')?.get('user')?.get('name'),
  255. score: item?.get('score'),
  256. };
  257. if (!groupMap[item?.get('eduTextbook')?.id]) {
  258. groupMap[item?.get('eduTextbook')?.id] = {
  259. eduTextbook: item?.get('eduTextbook'),
  260. groupList: [obj],
  261. };
  262. } else {
  263. groupMap[item?.get('eduTextbook')?.id]['groupList'].push(obj);
  264. }
  265. });
  266. console.log(groupMap);
  267. let table = `<table border="1px" cellspacing="0" cellpadding="0">
  268. <thead>
  269. <tr>
  270. <th>序号</th>
  271. <th>教材申报编号</th>
  272. <th>申报教材名称</th>
  273. <th>所属学科专业类</th>
  274. <th>第一主编/作者</th>
  275. <th>出版单位</th>
  276. <th>所属评审组</th>
  277. `;
  278. let l = 0;
  279. let dataLsit: any = Object.values(groupMap);
  280. dataLsit.forEach((val: any) => {
  281. if (val?.groupList.length > l) l = val?.groupList.length;
  282. });
  283. for (let index = 0; index < l; index++) {
  284. table += `<th>评审专家${index + 1}</th>`;
  285. }
  286. table += `
  287. <th>平均分值(若为空请点击计算后再导出)</th>
  288. </tr>
  289. </thead>
  290. <tbody>`;
  291. let _body = '';
  292. for (var row = 0; row < dataLsit.length; row++) {
  293. _body += '<tr>';
  294. _body += '<td>';
  295. _body += `${row + 1}`;
  296. _body += '</td>';
  297. _body += '<td>';
  298. _body += `&nbsp;${dataLsit[row]?.eduTextbook?.get('code') || ''}`;
  299. _body += '</td>';
  300. _body += '<td>';
  301. _body += `&nbsp;${dataLsit[row]?.eduTextbook?.get('title') || ''}`;
  302. _body += '</td>';
  303. _body += '<td>';
  304. _body += `&nbsp;${
  305. (dataLsit[row]?.eduTextbook?.get('majorPoniter')?.code || '') +
  306. '/' +
  307. dataLsit[row]?.eduTextbook?.get('majorPoniter')?.name || ''
  308. }`;
  309. _body += '</td>';
  310. _body += '<td>';
  311. _body += `&nbsp;${this.fromatFiled(
  312. dataLsit[row]?.eduTextbook?.get('childrens'),
  313. 'author'
  314. )}`;
  315. _body += '</td>';
  316. _body += '<td>';
  317. _body += `${this.fromatFiled(
  318. dataLsit[row]?.eduTextbook?.get('childrens'),
  319. 'editionUnit'
  320. )}`;
  321. _body += '</td>';
  322. _body += '<td>';
  323. _body += `${this.filterObj.bookMap[dataLsit[row]?.eduTextbook?.id].name}`;
  324. _body += '</td>';
  325. for (let i = 0; i < l; i++) {
  326. const element = dataLsit[row]['groupList'][i];
  327. _body += '<td>';
  328. _body += `${element?.name ?? ''} ${element?.score??''}`;
  329. _body += '</td>';
  330. }
  331. // _body += '<td>';
  332. // _body += ` &nbsp;${
  333. // this.filterObj.bookMap[dataLsit[row]?.eduTextbook?.id].name || '-'
  334. // }`;
  335. // _body += '</td>';
  336. // _body += '<td>';
  337. // _body += `${
  338. // dataLsit[row]?.get('profile')?.get('user')?.get('name') || '-'
  339. // }`;
  340. // _body += '</td>';
  341. // _body += '<td>';
  342. // _body += `&nbsp;${this.datePipe.transform(
  343. // dataLsit[row]?.updatedAt,
  344. // 'yyyy-MM-dd HH:mm:ss'
  345. // )}`;
  346. // _body += '</td>';
  347. _body += '<td>';
  348. _body += `${dataLsit[row]?.eduTextbook?.get('score') ?? '-'}`;
  349. _body += '</td>';
  350. _body += '</tr>';
  351. }
  352. table += _body;
  353. table += '</tbody>';
  354. table += '</table>';
  355. return table;
  356. }
  357. //非合并(评审组详情)
  358. getTable(data: Array<Parse.Object>): string {
  359. let table = `<table border="1px" cellspacing="0" cellpadding="0">
  360. <thead>
  361. <tr>
  362. <th>序号</th>
  363. <th>教材申报编号</th>
  364. <th>申报教材名称</th>
  365. <th>所属学科专业类</th>
  366. <th>第一主编/作者</th>
  367. <th>出版单位</th>
  368. <th>评审专家</th>
  369. <th>提交时间</th>
  370. <th>分值</th>
  371. </tr>
  372. </thead>
  373. <tbody>
  374. `;
  375. let _body = '';
  376. for (var row = 0; row < data.length; row++) {
  377. _body += '<tr>';
  378. _body += '<td>';
  379. _body += `${row + 1}`;
  380. _body += '</td>';
  381. _body += '<td>';
  382. _body += `&nbsp;${data[row]?.get('eduTextbook')?.get('code') || ''}`;
  383. _body += '</td>';
  384. _body += '<td>';
  385. _body += `&nbsp;${data[row]?.get('eduTextbook')?.get('title') || ''}`;
  386. _body += '</td>';
  387. _body += '<td>';
  388. _body += `&nbsp;${
  389. (data[row]?.get('eduTextbook')?.get('majorPoniter')?.code || '') +
  390. '/' +
  391. data[row]?.get('eduTextbook')?.get('majorPoniter')?.name || ''
  392. }`;
  393. _body += '</td>';
  394. _body += '<td>';
  395. _body += `&nbsp;${this.fromatFiled(
  396. data[row]?.get('eduTextbook')?.get('childrens'),
  397. 'author'
  398. )}`;
  399. _body += '</td>';
  400. _body += '<td>';
  401. _body += `${this.fromatFiled(
  402. data[row]?.get('eduTextbook')?.get('childrens'),
  403. 'editionUnit'
  404. )}`;
  405. _body += '</td>';
  406. // if (this.filterObj.showGroup) {
  407. // _body += '<td>';
  408. // _body += ` &nbsp;${
  409. // this.filterObj.bookMap[data[row]?.get('eduTextbook')?.id].name ||
  410. // '-'
  411. // }`;
  412. // _body += '</td>';
  413. // }
  414. _body += '<td>';
  415. _body += `${data[row]?.get('profile')?.get('user')?.get('name') || '-'}`;
  416. _body += '</td>';
  417. _body += '<td>';
  418. _body += `&nbsp;${this.datePipe.transform(
  419. data[row]?.updatedAt,
  420. 'yyyy-MM-dd HH:mm:ss'
  421. )}`;
  422. _body += '</td>';
  423. _body += '<td>';
  424. _body += `${data[row]?.get('score') ?? '-'}`;
  425. _body += '</td>';
  426. _body += '</tr>';
  427. }
  428. table += _body;
  429. table += '</tbody>';
  430. table += '</table>';
  431. return table;
  432. }
  433. excel(data: any, filename: string) {
  434. let html =
  435. "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>";
  436. html +=
  437. '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">';
  438. html += '<meta http-equiv="content-type" content="application/vnd.ms-excel';
  439. html += '; charset=UTF-8">';
  440. html += '<head>';
  441. html += '</head>';
  442. html += '<body>';
  443. html += data;
  444. html += '</body>';
  445. html += '</html>';
  446. let uri =
  447. 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(html);
  448. let link = document.createElement('a');
  449. link.href = uri;
  450. link.download = `${filename}`;
  451. document.body.appendChild(link);
  452. link.click();
  453. document.body.removeChild(link);
  454. }
  455. }