page-role.component.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. constructor(
  108. public tbookSer: textbookServer,
  109. private route: Router,
  110. private modal: NzModalService,
  111. private activeRoute: ActivatedRoute,
  112. private nzContextMenuService: NzContextMenuService,
  113. private message: NzMessageService
  114. ) {
  115. this.user = Parse.User.current();
  116. this.className = this.Department.className;
  117. this.fieldsArray = this.Department.fieldsArray;
  118. this.queryParams = {
  119. where: {
  120. // user:this.user?.toPointer(),
  121. isDeleted: { $ne: true },
  122. },
  123. };
  124. }
  125. ngOnInit(): void {
  126. this.activeRoute.paramMap.subscribe(async (params) => {
  127. // let isDeleted = params.get('isDeleted');
  128. // if (isDeleted) {
  129. // this.queryParams.where['isDeleted'] = { $eq: true };
  130. // } else {
  131. // this.queryParams.where['isDeleted'] = { $ne: true };
  132. // }
  133. // this.list?.ngOnInit();
  134. if (!this.tbookSer.profile.user.department?.objectId) {
  135. this.message.warning('权限不足');
  136. history.back();
  137. return;
  138. }
  139. let query = new Parse.Query('Department')
  140. query.equalTo('objectId', this.tbookSer.profile.user.department?.objectId)
  141. query.select('hasChildren','branch')
  142. let r = await query.first()
  143. this.nodes = [
  144. {
  145. title: this.tbookSer.profile.user.department.name,
  146. key: this.tbookSer.profile.user.department?.objectId,
  147. children: [
  148. ...(await this.getDepart(
  149. this.tbookSer.profile.user.department?.objectId
  150. )),
  151. ],
  152. isParent: !r?.get('hasChildren'),
  153. isLeaf: !r?.get('hasChildren'),
  154. branch:r?.get('branch')
  155. },
  156. ];
  157. });
  158. }
  159. async getDepart(
  160. parent?: string,
  161. searchValue?: string,
  162. filter?: boolean
  163. ): Promise<Array<nodes>> {
  164. let nodes: any = [];
  165. let query = new Parse.Query('Department');
  166. if (!filter) {
  167. query.equalTo('parent', parent ? parent : undefined);
  168. }
  169. searchValue && query.contains('name', searchValue);
  170. query.notEqualTo('isDeleted', true);
  171. query.select('code', 'name', 'branch', 'parent', 'type','hasChildren');
  172. query.descending('createdAt');
  173. query.equalTo('branch',this.tbookSer.profile.companyType)
  174. console.log(searchValue);
  175. if(searchValue && searchValue != undefined){
  176. query.equalTo('parent',this.tbookSer.profile.user.department?.objectId)
  177. }
  178. query.limit(100);
  179. if (this.activeDepart) query.notEqualTo('objectId', this.activeDepart?.id);
  180. let res = await query.find();
  181. res.forEach((item) => {
  182. nodes.push({
  183. title: item.get('name'),
  184. key: item.id,
  185. children: [],
  186. branch: item.get('branch'),
  187. isLeaf: !item.get('hasChildren') ? true : false, //是否是最下级
  188. });
  189. });
  190. return nodes;
  191. }
  192. //搜索
  193. async onSearchNodes(e: string, modal?: boolean) {
  194. if (modal) {
  195. this.parentList = await this.getDepart('', e, true);
  196. return;
  197. }
  198. this.nodes = await this.getDepart('', e, e ? true : false);
  199. }
  200. //添加成员
  201. addMember() {
  202. this.parentList = this.nodes;
  203. this.account = {
  204. name: '',
  205. phone: '',
  206. email: '',
  207. password: '',
  208. identity: '',
  209. department: {},
  210. companyType: '',
  211. };
  212. this.accountIsVisible = true;
  213. }
  214. //展开/合并
  215. async nzEvent(event: NzFormatEmitEvent): Promise<void> {
  216. console.log(event);
  217. let node: any = event.node;
  218. if (event.eventName === 'expand') {
  219. // if (node.origin.isParent) {
  220. // node.addChildren([]);
  221. // return;
  222. // }
  223. if (node?._children.length <= 0) {
  224. let data = await this.getDepart(node.key);
  225. node.addChildren(data);
  226. }
  227. console.log(this.nodes);
  228. } else {
  229. // if (node.origin.isParent) {
  230. this.currentDepart = node.origin;
  231. this.getProfile();
  232. // }
  233. }
  234. }
  235. async getProfile() {
  236. this.profiles = [];
  237. this.loading = true;
  238. let queryParams = {
  239. where: {
  240. $or: [
  241. {
  242. user: {
  243. $inQuery: {
  244. where: {
  245. $or: [
  246. {
  247. department: { $eq: this.currentDepart.key },
  248. },
  249. ],
  250. },
  251. className: '_User',
  252. },
  253. },
  254. },
  255. ],
  256. },
  257. };
  258. let query = Parse.Query.fromJSON('Profile', queryParams);
  259. query.include('user');
  260. query.notEqualTo('identity', '国家级管理员');
  261. let r = await query.find();
  262. let profiles: any[] = [];
  263. r.forEach((item) => {
  264. let _item = item.toJSON();
  265. _item['checked'] = false;
  266. profiles.push(_item);
  267. });
  268. this.profiles = profiles;
  269. this.loading = false;
  270. }
  271. //搜索触发
  272. onSearch(event: NzFormatEmitEvent) {
  273. console.log(event);
  274. }
  275. contextMenu(
  276. $event: MouseEvent,
  277. menu: NzDropdownMenuComponent,
  278. node?: any
  279. ): void {
  280. console.log(node);
  281. this.activatedNode = node;
  282. this.nzContextMenuService.create($event, menu);
  283. }
  284. //删除部门
  285. onDelDepart() {
  286. this.message.warning('权限灰度中');
  287. }
  288. onAllChecked(checked: boolean): void {
  289. console.log(checked);
  290. this.profiles = this.profiles.map((item) => {
  291. item.checked = checked;
  292. return item;
  293. });
  294. this.checkedAll = checked;
  295. }
  296. onItemChecked(id: string, e: boolean) {
  297. let checkedAll = true;
  298. this.profiles = this.profiles.map((item) => {
  299. if (id == item.objectId) item.checked = e;
  300. if (!item.checked) checkedAll = false;
  301. return item;
  302. });
  303. this.checkedAll = checkedAll;
  304. }
  305. //新建打开弹窗
  306. async showModalDepart(type: string) {
  307. this.parentList = this.nodes;
  308. this.editObject = {
  309. name: '',
  310. code: '',
  311. desc: '',
  312. parent: '',
  313. branch: '',
  314. };
  315. if (type == 'edit') {
  316. let query = new Parse.Query('Department');
  317. let r = await query.get(this.activatedNode?.key);
  318. this.activeDepart = r;
  319. this.editObject = {
  320. name: this.activeDepart.get('name'),
  321. code: this.activeDepart.get('code'),
  322. desc: this.activeDepart.get('desc'),
  323. parent: {
  324. title: this.activeDepart.get('parent')?.get('name'),
  325. id: this.activeDepart.get('parent')?.id,
  326. },
  327. branch: this.activeDepart.get('branch'),
  328. };
  329. this.parentMap = await this.formatNode(
  330. this.activeDepart.get('parent')?.id
  331. );
  332. if (this.activatedNode?.parentNode?.origin?.parentNode?.origin.key) {
  333. this.parentList = await this.getDepart(
  334. this.activatedNode?.parentNode?.origin?.parentNode?.origin.key
  335. );
  336. }
  337. } else if (type == 'add' && this.activatedNode) {
  338. console.log(this.activatedNode);
  339. this.editObject.parent = {
  340. title: this.activatedNode.origin.title,
  341. id: this.activatedNode.origin.key,
  342. };
  343. this.editObject.branch =
  344. this.activatedNode.origin.branch || this.activatedNode.origin.title;
  345. this.parentMap = await this.formatNode(this.activatedNode.origin.key);
  346. if (this.activatedNode?.parentNode?.origin.key) {
  347. this.parentList = await this.getDepart(
  348. this.activatedNode.parentNode.origin.key
  349. );
  350. }
  351. }
  352. console.log(this.parentMap);
  353. this.editType = type;
  354. this.isVisible = true;
  355. }
  356. //格式化链
  357. async formatNode(id: string): Promise<Array<any>> {
  358. let query = new Parse.Query('Department');
  359. query.select('name', 'parent','hasChildren');
  360. let r = await query.get(id);
  361. let arr = [
  362. {
  363. title: r.get('name'),
  364. key: r.id,
  365. hasChildren: r.get('hasChildren'), //是否是最下级
  366. },
  367. ];
  368. if (r?.get('parent')) {
  369. arr.unshift(...(await this.formatNode(r?.get('parent').id)));
  370. }
  371. return arr;
  372. }
  373. async onPre(data?: any, index?: number) {
  374. if (!data?.key || !data.hasChildren) {
  375. // this.parentList = await this.getDepart();
  376. // this.parentMap = []
  377. return;
  378. }
  379. // if(index == this.parentMap.length-1) return
  380. if (index !== 0 && !index) this.parentMap.splice(index || 0 + 1);
  381. this.parentList = await this.getDepart(data?.key);
  382. }
  383. //选择所属类别下级列表
  384. async onCheckedDepart(type: string, e: any, checked?: boolean) {
  385. this.radio = e.key;
  386. console.log(e);
  387. this.parentMap = await this.formatNode(e.key);
  388. if (checked) {
  389. // this.editObject.name = e.title
  390. if (type == 'account') {
  391. this.account.department = { title: e.title, id: e.key };
  392. this.account.companyType = e.branch || e.title;
  393. } else {
  394. this.editObject.parent = {
  395. title: e.title,
  396. id: e.key,
  397. };
  398. this.editObject.branch = e.branch || e.title;
  399. }
  400. return;
  401. }
  402. if (e.isLeaf) {
  403. return;
  404. }
  405. // this.parentMap.push({
  406. // title: e.title,
  407. // key: e.key,
  408. // });
  409. this.parentList = await this.getDepart(e?.key);
  410. }
  411. async handleOk(): Promise<void> {
  412. if (!this.editObject?.name || !this.editObject.parent?.id) {
  413. this.message.error('请填写完整信息');
  414. return;
  415. }
  416. if (this.activeDepart?.id && this.editType == 'edit') {
  417. this.activeDepart.set('name', this.editObject?.name);
  418. this.activeDepart.set('code', this.editObject?.code);
  419. this.activeDepart.set('desc', this.editObject.desc);
  420. this.activeDepart.set('parent', {
  421. __type: 'Pointer',
  422. className: 'Department',
  423. objectId: this.editObject.parent?.id,
  424. });
  425. this.activeDepart.set('branch', this.editObject.branch);
  426. } else {
  427. let obj = Parse.Object.extend('Department');
  428. this.activeDepart = new obj();
  429. this.activeDepart?.set('name', this.editObject?.name);
  430. this.activeDepart?.set('code', this.editObject?.code);
  431. this.activeDepart?.set('desc', this.editObject.desc);
  432. this.activeDepart?.set('parent', {
  433. __type: 'Pointer',
  434. className: 'Department',
  435. objectId: this.editObject.parent?.id,
  436. });
  437. this.activeDepart?.set('branch', this.editObject.branch);
  438. }
  439. await this.activeDepart?.save();
  440. await this.updateChildren()
  441. this.isVisible = false;
  442. this.message.success(this.editType == 'edit' ? '保存' : '添加' + '成功');
  443. this.activeDepart = undefined;
  444. this.ngOnInit()
  445. }
  446. //更新上级children字段
  447. async updateChildren(){
  448. let query = new Parse.Query('Department')
  449. query.equalTo('objectId', this.editObject.parent?.id)
  450. let r = await query.first()
  451. if(r?.id && !r.get('hasChildren')){
  452. r?.set('hasChildren', true)
  453. await r.save()
  454. }
  455. return
  456. }
  457. handleCancel(): void {
  458. console.log('Button cancel clicked!');
  459. this.isVisible = false;
  460. this.activatedNode = undefined;
  461. this.parentMap = [];
  462. this.accountIsVisible = false;
  463. this.account = null;
  464. }
  465. /* 组织 */
  466. showModalOrganize() {
  467. this.message.warning('权限灰度中');
  468. }
  469. goDateil(id: string) {
  470. this.route.navigate(['/nav-admin/manage/user/edit', { id: id }]);
  471. }
  472. randomPassword() {
  473. let sCode =
  474. 'A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m';
  475. let aCode = sCode.split(',');
  476. let aLength = aCode.length; //获取到数组的长度
  477. let str = [];
  478. for (let i = 0; i <= 16; i++) {
  479. let j = Math.floor(Math.random() * aLength); //获取到随机的索引值
  480. let txt = aCode[j]; //得到随机的一个内容
  481. str.push(txt);
  482. }
  483. this.account.password = str.join('');
  484. console.log(this.account.password);
  485. }
  486. /* 添加账号 */
  487. async accountComplete() {
  488. if (
  489. !this.account?.name.trim() ||
  490. !this.account.department?.id ||
  491. !this.account.password.trim()
  492. ) {
  493. this.message.warning('请填写必填项');
  494. return;
  495. }
  496. if (!this.account.identity) {
  497. this.message.error('请选择人员类型');
  498. return;
  499. }
  500. let a = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
  501. if (this.account.phone && !String(this.account.phone).match(a)) {
  502. this.message.error('请填写正确手机号');
  503. return;
  504. }
  505. try {
  506. let obj = Parse.Object.extend('_User');
  507. let user = new obj();
  508. user?.set('username', this.account?.email);
  509. user?.set('name', this.account?.name);
  510. user?.set('phone', this.account?.phone);
  511. user?.set('email', this.account?.email);
  512. user?.set('password', this.account.password);
  513. user?.set('accountState', '已认证');
  514. user?.set('department', {
  515. __type: 'Pointer',
  516. className: 'Department',
  517. objectId: this.account.department?.id,
  518. });
  519. let u = await user.save();
  520. let p = Parse.Object.extend('Profile');
  521. let profile = new p();
  522. profile?.set('user', u?.toPointer());
  523. profile?.set('companyType', this.account.companyType);
  524. profile?.set('email', this.account.email);
  525. profile?.set('identity', this.account.identity);
  526. let res = await profile?.save();
  527. this.accountIsVisible = false;
  528. this.account = null;
  529. this.modal.success({
  530. nzTitle: '添加成功',
  531. nzContent: '',
  532. nzOnOk: () => {
  533. this.currentDepart && this.getProfile();
  534. },
  535. });
  536. } catch (err: any) {
  537. console.warn('添加用户错误', err);
  538. this.message.error(err?.Error || '错误:请检查用户邮箱是否已存在');
  539. return;
  540. }
  541. }
  542. setOfCheckedId = new Set<string>();
  543. //移除部门
  544. async removeBranch(data: Parse.Object) {
  545. if (data?.get('user')?.id) {
  546. data?.get('user')?.set('department', null);
  547. await data?.get('user')?.save();
  548. this.message.error('移除成功');
  549. this.getProfile();
  550. }
  551. }
  552. removeBranchAll() {
  553. this.modal.confirm({
  554. nzTitle: '批量移除',
  555. nzContent: `请谨慎操作`,
  556. nzOkText: '确认',
  557. nzOkType: 'primary',
  558. nzOkDanger: true,
  559. nzOnOk: async () => {
  560. let selectedList = this.profiles.filter((item: any) =>
  561. this.setOfCheckedId.has(item?.id)
  562. );
  563. let romovePromiseList = selectedList.map((item: any) => {
  564. return new Promise(async (resolve) => {
  565. item?.get('user')?.set('department', null);
  566. await item?.get('user')?.save();
  567. resolve(true);
  568. });
  569. });
  570. try {
  571. await Promise.all(romovePromiseList);
  572. this.message.error('移除成功');
  573. this.getProfile();
  574. this.resetChange();
  575. } catch (err) {}
  576. },
  577. nzCancelText: '取消',
  578. nzOnCancel: () => console.log('Cancel'),
  579. });
  580. }
  581. resetChange() {
  582. this.setOfCheckedId = new Set<string>();
  583. this.checkedAll = false;
  584. }
  585. }