process-list.component.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. import { Component, OnInit, ViewChild } from '@angular/core';
  2. import { ActivatedRoute, RouterOutlet, Router } from '@angular/router';
  3. // import { CompTableListComponent } from '../../../../app/comp-table/comp-table-list/comp-table-list.component';
  4. import _Role from '../../../../schemas/_Role';
  5. // import { TranslateService } from '@ngx-translate/core';
  6. import * as Parse from 'parse';
  7. import { CommonModule } from '@angular/common';
  8. import { Department } from '../../../../schemas/Department';
  9. import { NzSpaceModule } from 'ng-zorro-antd/space';
  10. import { NzPageHeaderModule } from 'ng-zorro-antd/page-header';
  11. import { NzBreadCrumbModule } from 'ng-zorro-antd/breadcrumb';
  12. import { CommonCompModule } from '../../../../services/common.modules';
  13. import { NzModalModule } from 'ng-zorro-antd/modal';
  14. import {
  15. NzFormatEmitEvent,
  16. NzTreeModule,
  17. NzTreeNode,
  18. } from 'ng-zorro-antd/tree';
  19. import {
  20. NzContextMenuService,
  21. NzDropdownMenuComponent,
  22. } from 'ng-zorro-antd/dropdown';
  23. import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
  24. import { NzEmptyModule } from 'ng-zorro-antd/empty';
  25. import { NzRadioModule } from 'ng-zorro-antd/radio';
  26. import { NzMessageService } from 'ng-zorro-antd/message';
  27. import { NzModalService } from 'ng-zorro-antd/modal';
  28. import { NzPopoverModule } from 'ng-zorro-antd/popover';
  29. import { setHours } from 'date-fns';
  30. import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
  31. interface nodes {
  32. title: string;
  33. key: string;
  34. isLeaf?: boolean;
  35. isParent?: boolean;
  36. children?: Array<any>;
  37. }
  38. interface depart {
  39. name: string;
  40. id?: string;
  41. code?: string;
  42. desc?: string;
  43. parent?: object | any;
  44. branch: string;
  45. }
  46. @Component({
  47. selector: 'app-process-list',
  48. templateUrl: './process-list.component.html',
  49. styleUrls: ['./process-list.component.scss'],
  50. imports: [
  51. CommonModule,
  52. CommonCompModule,
  53. RouterOutlet,
  54. // CompTableListComponent,
  55. NzSpaceModule,
  56. NzPageHeaderModule,
  57. NzBreadCrumbModule,
  58. NzTreeModule,
  59. NzCheckboxModule,
  60. NzEmptyModule,
  61. NzModalModule,
  62. NzRadioModule,
  63. NzPopoverModule,
  64. NzDatePickerModule
  65. ],
  66. standalone: true,
  67. })
  68. export class ProcessListComponent implements OnInit {
  69. // @ViewChild(CompTableListComponent) list: CompTableListComponent | undefined;
  70. timeDefaultValue = setHours(new Date(), 0);
  71. // _Role = _Role
  72. Department = Department;
  73. user: Parse.User | undefined;
  74. className: string | undefined;
  75. queryParams: any | undefined;
  76. fieldsArray: Array<any> | undefined;
  77. searchValue: string = ''; //搜索内容
  78. searchValuePro: string = ''; //搜索流程内容
  79. nodes: Array<nodes | any> = [];
  80. currentDepart: nodes | any = null;
  81. eduProcessList: Array<Parse.Object> = [];
  82. statusMap: any = {};
  83. eduProcessLength: number = 0;
  84. pageSize: number = 10;
  85. pageIndex: number = 1;
  86. checkedShowFilter: boolean = false;
  87. checkedAll: boolean = false; //全选
  88. indeterminate = false;
  89. loading = false;
  90. isVisible: boolean = false;
  91. activatedNode: NzTreeNode | any; //当前选择节点
  92. editType: string = 'add'; //弹窗类型
  93. activeDepart?: Parse.Object; //当前编辑部门
  94. editObject: depart = {
  95. name: '',
  96. code: '',
  97. desc: '',
  98. parent: {},
  99. branch: '',
  100. };
  101. parentMap: Array<any> = [];
  102. parentList: Array<any> = [];
  103. setOfCheckedId = new Set<string>();
  104. formatStatus = (e: any) => {
  105. if (e.get('status') == '100') {
  106. return {
  107. title: '已暂停',
  108. color: 'lime',
  109. strat: true,
  110. stop: true,
  111. end: false,
  112. del: false,
  113. };
  114. }
  115. if (
  116. e?.get('deadline') &&
  117. new Date() > new Date(e?.get('deadline')) &&
  118. e?.get('status') == '400'
  119. ) {
  120. return {
  121. title: '已结束',
  122. color: 'gold',
  123. strat: false,
  124. stop: false,
  125. end: false,
  126. del: true,
  127. collect:true
  128. };
  129. }
  130. if(e?.get('collectStartData') && new Date() < new Date(e?.get('collectStartData'))){
  131. return {
  132. title: '待收集',
  133. color: 'default',
  134. strat: false,
  135. stop: false,
  136. end: false,
  137. del: false,
  138. collect:true
  139. };
  140. }
  141. if(e?.get('collectStartData') && new Date() > new Date(e?.get('collectStartData'))
  142. && new Date() < e?.get('collectEndData')){
  143. return {
  144. title: '收集中',
  145. color: 'orange',
  146. strat: false,
  147. stop: false,
  148. end: false,
  149. del: false,
  150. collect:true
  151. };
  152. }
  153. if (e?.get('status') == '400') {
  154. return {
  155. title: '已完成',
  156. color: 'green',
  157. strat: false,
  158. stop: false,
  159. end: true,
  160. del: false,
  161. collect:true
  162. };
  163. }
  164. if (!e?.get('startDate') || new Date() < new Date(e.get('startDate'))) {
  165. return {
  166. title: '未开始',
  167. color: 'grey',
  168. strat: true,
  169. stop: false,
  170. end: false,
  171. del: true,
  172. };
  173. }
  174. if (e?.get('deadline') && new Date() > new Date(e?.get('deadline'))) {
  175. return {
  176. title: '已逾期',
  177. color: 'red',
  178. strat: true,
  179. stop: false,
  180. end: false,
  181. del: true,
  182. };
  183. }
  184. if (
  185. e.get('status') == '200' &&
  186. e?.get('startDate') &&
  187. new Date() >= new Date(e?.get('startDate'))
  188. ) {
  189. return {
  190. title: '遴选中',
  191. color: 'blue',
  192. strat: false,
  193. stop: true,
  194. end: true,
  195. del: false,
  196. };
  197. }
  198. if (e.get('status') == '300') {
  199. return {
  200. title: '已公示',
  201. color: 'red',
  202. strat: false,
  203. stop: true,
  204. end: true,
  205. del: false,
  206. };
  207. }
  208. if (e.get('status') == '201') {
  209. return {
  210. title: '评审中',
  211. color: 'cyan',
  212. strat: false,
  213. stop: true,
  214. end: true,
  215. del: false,
  216. };
  217. }
  218. return;
  219. };
  220. /* 新建组织 */
  221. branchObj: any = {
  222. name: '',
  223. code: '',
  224. desc: '',
  225. };
  226. showModal:boolean = false
  227. eduProcess?:Parse.Object //当前编辑流程
  228. textBookList:Array<Parse.Object> = [] //流程教材列表(推荐)
  229. collectStartData:any
  230. collectEndData:any
  231. constructor(
  232. private route: Router,
  233. private activeRoute: ActivatedRoute,
  234. private nzContextMenuService: NzContextMenuService,
  235. private message: NzMessageService,
  236. private modal: NzModalService
  237. ) {
  238. this.user = Parse.User.current();
  239. this.className = this.Department.className;
  240. this.fieldsArray = this.Department.fieldsArray;
  241. this.queryParams = {
  242. where: {
  243. isDeleted: { $ne: true },
  244. },
  245. };
  246. }
  247. ngOnInit(): void {
  248. this.activeRoute.paramMap.subscribe(async (params) => {
  249. this.nodes = await this.getDepart();
  250. });
  251. }
  252. async getDepart(
  253. parent?: string,
  254. searchValue?: string
  255. ): Promise<Array<nodes>> {
  256. let nodes: any = [];
  257. let query = new Parse.Query('Department');
  258. query.equalTo('parent', parent ? parent : undefined);
  259. searchValue && query.contains('name', searchValue);
  260. query.notEqualTo('isDeleted', true);
  261. query.select('code', 'name', 'branch', 'parent', 'type');
  262. query.descending('createdAt');
  263. query.limit(2000);
  264. let res = await query.find();
  265. res.forEach((item) => {
  266. nodes.push({
  267. title: item.get('name'),
  268. key: item.id,
  269. children: [],
  270. // isParent: item.get('type') =='单位' ? true : false, //是否是最下级
  271. isLeaf: true,
  272. });
  273. });
  274. return nodes;
  275. }
  276. async onSearch(e: string) {
  277. this.nodes = await this.getDepart('', e);
  278. }
  279. onSearchPro(e: string) {
  280. this.pageIndex = 1;
  281. this.getEduProcess();
  282. }
  283. changeDepart(e: any) {
  284. this.currentDepart = e;
  285. this.setOfCheckedId = new Set<string>();
  286. this.checkedAll = false;
  287. this.pageIndex = 1;
  288. this.getEduProcess();
  289. }
  290. async getEduProcess() {
  291. this.eduProcessList = [];
  292. this.loading = true;
  293. let query1 = Parse.Query.fromJSON('EduProcess', {
  294. where: {
  295. $or: [
  296. {
  297. name: { $regex: `.*${this.searchValuePro}.*` },
  298. },
  299. ],
  300. },
  301. });
  302. let query2 = Parse.Query.fromJSON('EduProcess', {
  303. where: {
  304. $or: [
  305. {
  306. code: { $regex: `.*${this.searchValuePro}.*` },
  307. },
  308. ],
  309. },
  310. });
  311. let query = Parse.Query.or(query1, query2);
  312. query.include('profileSubmitted', 'profileSubmitted.user');
  313. query.notEqualTo('isDeleted', true);
  314. this.currentDepart?.key && query.equalTo('branch', this.currentDepart.key);
  315. this.eduProcessLength = await query.count();
  316. query.skip(this.pageSize * (this.pageIndex - 1));
  317. query.limit(this.pageSize);
  318. query.descending('createdAt');
  319. let r = await query.find();
  320. // let list: any[] = [];
  321. r.forEach((item) => {
  322. // let _item = item.toJSON();
  323. // _item['checked'] = false;
  324. // _item['state'] = this.formatStatus(_item);
  325. this.statusMap[item.id] = this.formatStatus(item);
  326. });
  327. this.eduProcessList = r;
  328. this.loading = false;
  329. }
  330. //分页切换
  331. pageIndexChange(e: any) {
  332. console.log(e);
  333. this.pageIndex = e;
  334. this.getEduProcess();
  335. }
  336. onAllChecked(checked: boolean): void {
  337. console.log(checked);
  338. this.eduProcessList.forEach((item) => {
  339. if (checked) {
  340. this.setOfCheckedId.add(item.id);
  341. } else {
  342. this.setOfCheckedId.delete(item.id);
  343. }
  344. });
  345. if (!checked) {
  346. this.setOfCheckedId = new Set<string>();
  347. }
  348. this.checkedAll = checked;
  349. }
  350. onItemChecked(id: string, e: boolean) {
  351. if (e) {
  352. this.setOfCheckedId.add(id);
  353. } else {
  354. this.setOfCheckedId.delete(id);
  355. }
  356. this.checkedAll = this.eduProcessList.every((item) =>
  357. this.setOfCheckedId.has(item.id)
  358. );
  359. }
  360. //新建打开弹窗
  361. async showModalDepart(type: string) {
  362. this.parentList = this.nodes;
  363. if (type == 'edit') {
  364. let query = new Parse.Query('Department');
  365. let r = await query.get(this.activatedNode?.key);
  366. this.activeDepart = r;
  367. this.parentMap = this.formatNode(this.activatedNode);
  368. if (this.activatedNode?.parentNode?.origin.key) {
  369. this.parentList = await this.getDepart(
  370. this.activatedNode.parentNode.origin.key
  371. );
  372. }
  373. }
  374. this.editType = type;
  375. this.isVisible = true;
  376. }
  377. //格式化链
  378. formatNode(node: NzTreeNode): Array<any> {
  379. let arr = [];
  380. if (node.parentNode?.origin.title) {
  381. arr.push({
  382. title: node.parentNode?.origin.title,
  383. key: node.parentNode?.origin.key,
  384. });
  385. arr.unshift(...this.formatNode(node.parentNode));
  386. }
  387. return arr;
  388. }
  389. async onPre(data?: any, index?: number) {
  390. if (!data) {
  391. this.parentList = await this.getDepart();
  392. this.parentMap = [];
  393. return;
  394. }
  395. if (index == this.parentMap.length - 1) return;
  396. this.parentMap.splice(index || 0 + 1);
  397. this.parentList = await this.getDepart(data?.key);
  398. }
  399. //选择所属类别下级列表
  400. async onCheckedDepart(e: any, checked?: boolean) {
  401. console.log(e);
  402. if (checked) {
  403. this.editObject = {
  404. name: e.title,
  405. code: '',
  406. desc: '',
  407. parent: e,
  408. branch: '',
  409. };
  410. return;
  411. }
  412. this.parentMap.push({
  413. title: e.title,
  414. key: e.key,
  415. });
  416. this.parentList = await this.getDepart(e?.key);
  417. }
  418. /* 组织 */
  419. showModalOrganize() {
  420. // this.message.warning('权限灰度中');
  421. this.branchObj = {
  422. name: '',
  423. code: '',
  424. desc: '',
  425. };
  426. this.isVisible = true;
  427. }
  428. async handleOk(): Promise<void> {
  429. if (!this.branchObj?.name) {
  430. this.message.warning('组织名称不能为空');
  431. }
  432. let obj = Parse.Object.extend('Department');
  433. let depart = new obj();
  434. depart.set('name', this.branchObj?.name);
  435. depart.set('desc', this.branchObj?.desc);
  436. depart.set('code', this.branchObj?.code);
  437. await depart.save();
  438. this.isVisible = false;
  439. this.message.success('新建成功');
  440. this.nodes = await this.getDepart();
  441. }
  442. handleCancel(): void {
  443. console.log('Button cancel clicked!');
  444. this.isVisible = false;
  445. this.activatedNode = undefined;
  446. this.parentMap = [];
  447. this.showModal = false
  448. this.collectStartData = undefined
  449. this.collectEndData = undefined
  450. this.eduProcess = undefined
  451. this.textBookList = []
  452. }
  453. statusSelected(type: string) {
  454. let map: any = {
  455. strat: '开始',
  456. stop: '暂停',
  457. end: '结束',
  458. del: '删除',
  459. };
  460. this.modal.confirm({
  461. nzTitle: `批量${map[type]}`,
  462. nzContent:
  463. type == 'del'
  464. ? `删除后数据不可恢复,请谨慎操作`
  465. : `确认批量${map[type]}吗`,
  466. nzOkText: '确认',
  467. nzOkType: 'primary',
  468. nzOkDanger: map[type] ? true : false,
  469. nzOnOk: async () => {
  470. let selectedList = this.eduProcessList.filter((item: any) =>
  471. this.setOfCheckedId.has(item?.id)
  472. );
  473. let deletePromiseList = selectedList.map((item: any) => {
  474. return new Promise((resolve) => {
  475. resolve(this.onStatusChange(item, type));
  476. });
  477. });
  478. try {
  479. await Promise.all(deletePromiseList);
  480. this.getEduProcess();
  481. } catch (err) {}
  482. },
  483. nzCancelText: '取消',
  484. nzOnCancel: () => console.log('Cancel'),
  485. });
  486. }
  487. toUrl(url: string, params?: object) {
  488. if (params) {
  489. this.route.navigate([url, params]);
  490. } else {
  491. this.route.navigate([url]);
  492. }
  493. }
  494. //暂停流程
  495. async onStatusChange(
  496. data: Parse.Object,
  497. type: string,
  498. end?: boolean,
  499. ): Promise<void> {
  500. console.log(data, type);
  501. switch (type) {
  502. case 'strat':
  503. if (data?.get('status') == '100') {
  504. data?.set('status', '200');
  505. }
  506. if (!data?.get('startDate') || data?.get('startDate') > new Date()) {
  507. data?.set('startDate', new Date());
  508. }
  509. if (!data?.get('deadline') || data?.get('deadline') < new Date()) {
  510. data?.set(
  511. 'deadline',
  512. new Date(new Date().getTime() + 60 * 1000 * 60 * 24 * 7)
  513. );
  514. console.warn('结束时间延长一周之后');
  515. }
  516. break;
  517. case 'stop':
  518. data?.set('status', '100');
  519. break;
  520. case 'end':
  521. data?.set('status', '400');
  522. data?.set('deadline', new Date());
  523. break;
  524. case 'del':
  525. data?.set('isDeleted', true);
  526. break;
  527. }
  528. await data.save();
  529. if (end) {
  530. this.getEduProcess();
  531. }
  532. }
  533. //打开编辑收集文件弹窗
  534. openEditCollect(data:Parse.Object){
  535. this.eduProcess = data
  536. this.collectStartData = this.eduProcess?.get('collectStartData')
  537. this.collectEndData = this.eduProcess?.get('collectEndData')
  538. this.showModal = true
  539. }
  540. //保存收集文件设置
  541. async editCollect(){
  542. if(!this.collectStartData || !this.collectEndData || this.collectStartData > this.collectEndData){
  543. this.message.warning('请设置正确的开始和截止时间')
  544. return
  545. }
  546. this.eduProcess?.set('collectStartData',this.collectStartData)
  547. this.eduProcess?.set('collectEndData',this.collectEndData)
  548. await this.eduProcess?.save()
  549. this.message.success('设置成功')
  550. this.getEduProcess()
  551. this.showModal = false
  552. }
  553. }