page-role.component.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. import { Component, OnInit, ViewChild } from '@angular/core';
  2. import { ActivatedRoute, Route, Router, RouterOutlet } 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, NzModalService } 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 { textbookServer } from '../../../services/textbook';
  28. import { NzSelectModule } from 'ng-zorro-antd/select';
  29. interface nodes {
  30. title: string;
  31. key: string;
  32. isLeaf?: boolean;
  33. isParent?: boolean;
  34. children?: Array<any>;
  35. }
  36. interface depart {
  37. name: string;
  38. id?: string;
  39. code?: string;
  40. desc?: string;
  41. parent?: object | any;
  42. branch: string;
  43. }
  44. @Component({
  45. selector: 'app-page-role',
  46. templateUrl: './page-role.component.html',
  47. styleUrls: ['./page-role.component.scss'],
  48. imports: [
  49. CommonModule,
  50. CommonCompModule,
  51. RouterOutlet,
  52. CompTableListComponent,
  53. NzSpaceModule,
  54. NzPageHeaderModule,
  55. NzBreadCrumbModule,
  56. NzTreeModule,
  57. NzCheckboxModule,
  58. NzEmptyModule,
  59. NzModalModule,
  60. NzRadioModule,
  61. NzSelectModule,
  62. ],
  63. standalone: true,
  64. })
  65. export class PageRoleComponent implements OnInit {
  66. @ViewChild(CompTableListComponent) list: CompTableListComponent | undefined;
  67. // _Role = _Role
  68. Department = Department;
  69. user?: Parse.User;
  70. className: string | undefined;
  71. queryParams: any | undefined;
  72. fieldsArray: Array<any> | undefined;
  73. searchValue: string = ''; //搜索内容
  74. nodes: Array<nodes | any> = [];
  75. currentDepart: nodes | any = null;
  76. profiles: Array<any> = [];
  77. checkedShowFilter: boolean = false;
  78. checkedAll: boolean = false; //全选
  79. indeterminate = false;
  80. loading = false;
  81. isVisible: boolean = false;
  82. activatedNode: NzTreeNode | any; //当前选择节点
  83. editType: string = 'add'; //弹窗类型
  84. activeDepart?: Parse.Object; //当前编辑部门
  85. editObject: depart = {
  86. name: '',
  87. code: '',
  88. desc: '',
  89. parent: {},
  90. branch: '',
  91. };
  92. parentMap: Array<any> = [];
  93. parentList: Array<any> = [];
  94. radio: string = '';
  95. /* 添加账号 */
  96. accountIsVisible: boolean = false;
  97. account: any = {
  98. name: '',
  99. phone: '',
  100. email: '',
  101. password: '',
  102. identity: '',
  103. department: {},
  104. companyType: '',
  105. };
  106. userType: Array<string> = ['个人'];
  107. parents: Array<any> = []; //所有一级列表
  108. constructor(
  109. public tbookSer: textbookServer,
  110. private route: Router,
  111. private modal: NzModalService,
  112. private activeRoute: ActivatedRoute,
  113. private nzContextMenuService: NzContextMenuService,
  114. private message: NzMessageService
  115. ) {
  116. this.user = Parse.User.current();
  117. // this.className = this.Department.className;
  118. // this.fieldsArray = this.Department.fieldsArray;
  119. // this.queryParams = {
  120. // where: {
  121. // // user:this.user?.toPointer(),
  122. // isDeleted: { $ne: true },
  123. // },
  124. // };
  125. }
  126. ngOnInit(): void {
  127. this.activeRoute.paramMap.subscribe(async (params) => {
  128. this.refresh();
  129. });
  130. }
  131. async refresh() {
  132. if (!this.tbookSer.profile.user.department?.objectId) {
  133. this.message.warning('权限不足');
  134. history.back();
  135. return;
  136. }
  137. let query = new Parse.Query('Department');
  138. query.equalTo('objectId', this.tbookSer.profile.user.department?.objectId);
  139. query.select('code', 'name', 'branch', 'parent', 'type', 'hasChildren');
  140. let r = await query.first();
  141. this.nodes = [
  142. {
  143. title: this.tbookSer.profile.user.department.name,
  144. key: this.tbookSer.profile.user.department?.objectId,
  145. children: [
  146. ...(await this.getDepart(
  147. this.tbookSer.profile.user.department?.objectId
  148. )),
  149. ],
  150. isParent: !r?.get('hasChildren'),
  151. isLeaf: !r?.get('hasChildren'),
  152. branch: r?.get('branch'),
  153. parent: r?.get('parent')?.id, //上级
  154. type: r?.get('branch'),
  155. },
  156. ];
  157. let query2 = new Parse.Query('Department');
  158. query2.select('name');
  159. query2.equalTo('parent', null);
  160. this.parents = await query2.find();
  161. }
  162. async getDepart(
  163. parent?: string,
  164. searchValue?: string,
  165. filter?: boolean
  166. ): Promise<Array<nodes>> {
  167. let nodes: any = [];
  168. let query = new Parse.Query('Department');
  169. if (!filter) {
  170. query.equalTo('parent', parent ? parent : undefined);
  171. }
  172. searchValue && query.contains('name', searchValue);
  173. query.notEqualTo('isDeleted', true);
  174. query.select('code', 'name', 'branch', 'parent', 'type', 'hasChildren');
  175. query.descending('createdAt');
  176. query.equalTo('branch', this.tbookSer.profile.companyType);
  177. console.log(searchValue);
  178. if (searchValue && searchValue != undefined) {
  179. query.equalTo('parent', this.tbookSer.profile.user.department?.objectId);
  180. }
  181. query.limit(100);
  182. if (this.activeDepart) query.notEqualTo('objectId', this.activeDepart?.id);
  183. let res = await query.find();
  184. res.forEach((item) => {
  185. nodes.push({
  186. title: item.get('name'),
  187. key: item.id,
  188. children: [],
  189. branch: item.get('branch'),
  190. parent: item.get('parent')?.id, //上级
  191. isLeaf: !item.get('hasChildren') ? true : false, //是否是最下级
  192. type: item.get('type'),
  193. });
  194. });
  195. return nodes;
  196. }
  197. //搜索
  198. async onSearchNodes(e: string, modal?: boolean) {
  199. if (modal) {
  200. this.parentList = await this.getDepart('', e, true);
  201. return;
  202. }
  203. this.nodes = await this.getDepart('', e, e ? true : false);
  204. }
  205. //添加成员
  206. addMember() {
  207. this.radio = ''
  208. this.parentList = this.nodes;
  209. this.account = {
  210. name: '',
  211. phone: '',
  212. email: '',
  213. password: '',
  214. identity: '',
  215. department: {},
  216. companyType: '',
  217. };
  218. this.accountIsVisible = true;
  219. }
  220. //展开/合并
  221. async nzEvent(event: NzFormatEmitEvent): Promise<void> {
  222. console.log(event);
  223. let node: any = event.node;
  224. if (event.eventName === 'expand') {
  225. // if (node.origin.isParent) {
  226. // node.addChildren([]);
  227. // return;
  228. // }
  229. if (node?._children.length <= 0) {
  230. let data = await this.getDepart(node.key);
  231. node.addChildren(data);
  232. }
  233. } else {
  234. // if (node.origin.isParent) {
  235. this.currentDepart = node.origin;
  236. this.getProfile();
  237. // }
  238. }
  239. }
  240. async getProfile() {
  241. this.profiles = [];
  242. this.loading = true;
  243. let queryParams = {
  244. where: {
  245. $or: [
  246. {
  247. user: {
  248. $inQuery: {
  249. where: {
  250. $or: [
  251. {
  252. department: { $eq: this.currentDepart.key },
  253. },
  254. ],
  255. },
  256. className: '_User',
  257. },
  258. },
  259. },
  260. ],
  261. },
  262. };
  263. let query = Parse.Query.fromJSON('Profile', queryParams);
  264. query.include('user');
  265. query.notEqualTo('identity', '国家级管理员');
  266. let r = await query.find();
  267. let profiles: any[] = [];
  268. r.forEach((item) => {
  269. let _item = item.toJSON();
  270. _item['checked'] = false;
  271. profiles.push(_item);
  272. });
  273. this.profiles = profiles;
  274. this.loading = false;
  275. }
  276. //搜索触发
  277. onSearch(event: NzFormatEmitEvent) {
  278. console.log(event);
  279. }
  280. contextMenu(
  281. $event: MouseEvent,
  282. menu: NzDropdownMenuComponent,
  283. node?: any
  284. ): void {
  285. console.log(node);
  286. this.activatedNode = node;
  287. this.nzContextMenuService.create($event, menu);
  288. }
  289. //删除部门
  290. onDelDepart() {
  291. this.message.warning('权限灰度中');
  292. }
  293. onAllChecked(checked: boolean): void {
  294. console.log(checked);
  295. this.profiles = this.profiles.map((item) => {
  296. item.checked = checked;
  297. return item;
  298. });
  299. this.checkedAll = checked;
  300. }
  301. onItemChecked(id: string, e: boolean) {
  302. let checkedAll = true;
  303. this.profiles = this.profiles.map((item) => {
  304. if (id == item.objectId) item.checked = e;
  305. if (!item.checked) checkedAll = false;
  306. return item;
  307. });
  308. this.checkedAll = checkedAll;
  309. }
  310. //新建打开弹窗
  311. async showModalDepart(type: string) {
  312. this.radio = ''
  313. this.parentList = this.nodes;
  314. this.editObject = {
  315. name: '',
  316. code: '',
  317. desc: '',
  318. parent: '',
  319. branch: '',
  320. };
  321. if (type == 'edit') {
  322. let query = new Parse.Query('Department');
  323. let r = await query.get(this.activatedNode?.key);
  324. this.activeDepart = r;
  325. this.editObject = {
  326. name: this.activeDepart.get('name'),
  327. code: this.activeDepart.get('code'),
  328. desc: this.activeDepart.get('desc'),
  329. parent: {
  330. title: this.activeDepart.get('parent')?.get('name'),
  331. id: this.activeDepart.get('parent')?.id,
  332. },
  333. branch: this.activeDepart.get('branch'),
  334. };
  335. this.parentMap = await this.formatNode(
  336. this.activeDepart.get('parent')?.id
  337. );
  338. if (this.activatedNode?.parentNode?.origin?.parentNode?.origin.key) {
  339. this.parentList = await this.getDepart(
  340. this.activatedNode?.parentNode?.origin?.parentNode?.origin.key
  341. );
  342. }
  343. } else if (type == 'add' && this.activatedNode) {
  344. console.log(this.activatedNode);
  345. this.editObject.parent = {
  346. title: this.activatedNode.origin.title,
  347. id: this.activatedNode.origin.key,
  348. };
  349. this.editObject.branch =
  350. this.activatedNode.origin.branch || this.activatedNode.origin.title;
  351. this.parentMap = await this.formatNode(this.activatedNode.origin.key);
  352. if (this.activatedNode?.parentNode?.origin.key) {
  353. this.parentList = await this.getDepart(
  354. this.activatedNode.parentNode.origin.key
  355. );
  356. }
  357. }
  358. console.log(this.parentMap);
  359. this.editType = type;
  360. this.isVisible = true;
  361. }
  362. //格式化链
  363. async formatNode(id: string): Promise<Array<any>> {
  364. let query = new Parse.Query('Department');
  365. query.select('name', 'parent', 'hasChildren');
  366. let r = await query.get(id);
  367. let arr = [
  368. {
  369. title: r.get('name'),
  370. key: r.id,
  371. hasChildren: r.get('hasChildren'), //是否是最下级
  372. },
  373. ];
  374. if (r?.get('parent')) {
  375. arr.unshift(...(await this.formatNode(r?.get('parent').id)));
  376. }
  377. return arr;
  378. }
  379. async onPre(data?: any, index?: number) {
  380. console.log(data);
  381. if (!data?.key || !data.hasChildren) {
  382. // this.parentList = await this.getDepart();
  383. // this.parentMap = []
  384. return;
  385. }
  386. // if(index == this.parentMap.length-1) return
  387. this.parentMap.splice((index || 0) + 1);
  388. this.parentList = await this.getDepart(data?.key);
  389. }
  390. //选择所属类别下级列表
  391. async onCheckedDepart(type: string, e: any, checked?: boolean) {
  392. this.radio = e.key;
  393. console.log(e);
  394. if (type == 'account') this.account.identity = '';
  395. this.parentMap = await this.formatNode(e.key);
  396. let index = this.parentMap.findIndex(
  397. (item) => this.tbookSer.profile.user.department?.objectId == item.key
  398. );
  399. if (index != -1) {
  400. this.parentMap.forEach((item, i) => {
  401. if (i >= index) {
  402. this.parentMap[i].verify = true;
  403. }
  404. });
  405. }
  406. if (checked) {
  407. // this.editObject.name = e.title
  408. if (type == 'account') {
  409. this.account.department = { title: e.title, id: e.key };
  410. this.account.companyType = e.branch || e.title;
  411. this.userType = this.parents.some((item) => e.parent == item.id)
  412. ? ['评审专家', '个人']
  413. : e.type
  414. ? ['评审专家', '高校联系人', '个人']
  415. : ['评审专家', '个人'];
  416. } else {
  417. this.editObject.parent = {
  418. title: e.title,
  419. id: e.key,
  420. };
  421. this.editObject.branch = e.branch || e.title;
  422. }
  423. return;
  424. }
  425. if (e.isLeaf) {
  426. return;
  427. }
  428. this.parentList = await this.getDepart(e?.key);
  429. }
  430. async handleOk(): Promise<void> {
  431. if (!this.editObject?.name || !this.editObject.parent?.id) {
  432. this.message.error('请填写完整信息');
  433. return;
  434. }
  435. if (this.activeDepart?.id && this.editType == 'edit') {
  436. this.activeDepart.set('name', this.editObject?.name);
  437. this.activeDepart.set('code', this.editObject?.code);
  438. this.activeDepart.set('desc', this.editObject.desc);
  439. this.activeDepart.set('parent', {
  440. __type: 'Pointer',
  441. className: 'Department',
  442. objectId: this.editObject.parent?.id,
  443. });
  444. this.activeDepart.set('branch', this.editObject.branch);
  445. } else {
  446. let obj = Parse.Object.extend('Department');
  447. this.activeDepart = new obj();
  448. this.activeDepart?.set('name', this.editObject?.name);
  449. this.activeDepart?.set('code', this.editObject?.code);
  450. this.activeDepart?.set('desc', this.editObject.desc);
  451. this.activeDepart?.set('parent', {
  452. __type: 'Pointer',
  453. className: 'Department',
  454. objectId: this.editObject.parent?.id,
  455. });
  456. this.activeDepart?.set('branch', this.editObject.branch);
  457. }
  458. await this.activeDepart?.save();
  459. if(this.activeDepart?.id){
  460. //判断添加的是部门还是单位
  461. let filters = ['出版单位','教育部直属高校']
  462. let leng = await this.formatNode(this.activeDepart.id)
  463. if(leng.length > 2){
  464. console.log(leng.length);
  465. if(filters.includes(leng[0].title)){
  466. this.activeDepart?.set('type', '部门');
  467. }else{
  468. this.activeDepart?.set('type',leng.length > 3 ? '部门' : '单位');
  469. }
  470. leng.slice()
  471. await this.activeDepart?.save();
  472. }
  473. }
  474. await this.updateChildren();
  475. this.isVisible = false;
  476. this.message.success(this.editType == 'edit' ? '保存' : '添加' + '成功');
  477. this.activeDepart = undefined;
  478. this.ngOnInit();
  479. }
  480. //更新上级children字段
  481. async updateChildren() {
  482. let query = new Parse.Query('Department');
  483. query.equalTo('objectId', this.editObject.parent?.id);
  484. query.select('hasChildren')
  485. let r = await query.first();
  486. if (r?.id && !r.get('hasChildren')) {
  487. r?.set('hasChildren', true);
  488. await r.save();
  489. }
  490. return;
  491. }
  492. handleCancel(): void {
  493. console.log('Button cancel clicked!');
  494. this.isVisible = false;
  495. this.activatedNode = undefined;
  496. this.parentMap = [];
  497. this.accountIsVisible = false;
  498. this.account = null;
  499. }
  500. /* 组织 */
  501. showModalOrganize() {
  502. this.message.warning('权限灰度中');
  503. }
  504. goDateil(id: string) {
  505. this.route.navigate(['/nav-admin/manage/user/edit', { id: id }]);
  506. }
  507. randomPassword() {
  508. this.account.password = this.tbookSer.randomPassword();
  509. }
  510. /* 添加账号 */
  511. async accountComplete() {
  512. if (
  513. !this.account?.name.trim() ||
  514. !this.account.department?.id ||
  515. !this.account.password.trim()
  516. ) {
  517. this.message.warning('请填写必填项');
  518. return;
  519. }
  520. if (!this.account.identity) {
  521. this.message.error('请选择人员类型');
  522. return;
  523. }
  524. let a = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
  525. if (this.account.phone && !String(this.account.phone).match(a)) {
  526. this.message.error('请填写正确手机号');
  527. return;
  528. }
  529. this.account.email = this.account?.email.trim();
  530. this.account.phone = this.account?.phone.trim();
  531. if (!this.account?.email && !this.account?.phone) {
  532. this.message.error('邮箱或手机号必须填写一项');
  533. return;
  534. }
  535. try {
  536. let obj = Parse.Object.extend('_User');
  537. let user = new obj();
  538. user?.set('username', this.account?.email || this.account?.phone);
  539. user?.set('name', this.account?.name);
  540. user?.set('phone', this.account?.phone);
  541. this.account?.email && user?.set('email', this.account?.email);
  542. user?.set('password', this.account.password);
  543. user?.set('accountState', '已认证');
  544. user?.set('department', {
  545. __type: 'Pointer',
  546. className: 'Department',
  547. objectId: this.account.department?.id,
  548. });
  549. let u = await user.save();
  550. let p = Parse.Object.extend('Profile');
  551. let profile = new p();
  552. profile?.set('user', u?.toPointer());
  553. profile?.set('companyType', this.account.companyType);
  554. profile?.set('email', this.account.email);
  555. profile?.set('identity', this.account.identity);
  556. let res = await profile?.save();
  557. this.accountIsVisible = false;
  558. this.account = null;
  559. this.modal.success({
  560. nzTitle: '添加成功',
  561. nzContent: '',
  562. nzOnOk: () => {
  563. this.currentDepart && this.getProfile();
  564. },
  565. });
  566. } catch (err: any) {
  567. console.warn('添加用户错误', err);
  568. this.message.error(err?.Error || '错误:请检查用户邮箱是否已存在');
  569. return;
  570. }
  571. }
  572. setOfCheckedId = new Set<string>();
  573. //移除部门
  574. async removeBranch(data: Parse.Object) {
  575. if (data?.get('user')?.id) {
  576. data?.get('user')?.set('department', null);
  577. await data?.get('user')?.save();
  578. this.message.error('移除成功');
  579. this.getProfile();
  580. }
  581. }
  582. removeBranchAll() {
  583. this.modal.confirm({
  584. nzTitle: '批量移除',
  585. nzContent: `请谨慎操作`,
  586. nzOkText: '确认',
  587. nzOkType: 'primary',
  588. nzOkDanger: true,
  589. nzOnOk: async () => {
  590. let selectedList = this.profiles.filter((item: any) =>
  591. this.setOfCheckedId.has(item?.id)
  592. );
  593. let romovePromiseList = selectedList.map((item: any) => {
  594. return new Promise(async (resolve) => {
  595. item?.get('user')?.set('department', null);
  596. await item?.get('user')?.save();
  597. resolve(true);
  598. });
  599. });
  600. try {
  601. await Promise.all(romovePromiseList);
  602. this.message.error('移除成功');
  603. this.getProfile();
  604. this.resetChange();
  605. } catch (err) {}
  606. },
  607. nzCancelText: '取消',
  608. nzOnCancel: () => console.log('Cancel'),
  609. });
  610. }
  611. resetChange() {
  612. this.setOfCheckedId = new Set<string>();
  613. this.checkedAll = false;
  614. }
  615. }