import { Component, OnInit, ViewChild } from '@angular/core'; import { ActivatedRoute, Route, Router, RouterOutlet } from '@angular/router'; import { CompTableListComponent } from '../../../app/comp-table/comp-table-list/comp-table-list.component'; import _Role from '../../../schemas/_Role'; // import { TranslateService } from '@ngx-translate/core'; import * as Parse from 'parse'; import { CommonModule } from '@angular/common'; import { Department } from '../../../schemas/Department'; import { NzSpaceModule } from 'ng-zorro-antd/space'; import { NzPageHeaderModule } from 'ng-zorro-antd/page-header'; import { NzBreadCrumbModule } from 'ng-zorro-antd/breadcrumb'; import { CommonCompModule } from '../../../services/common.modules'; import { NzModalModule, NzModalService } from 'ng-zorro-antd/modal'; import { NzFormatEmitEvent, NzTreeModule, NzTreeNode, } from 'ng-zorro-antd/tree'; import { NzContextMenuService, NzDropdownMenuComponent, } from 'ng-zorro-antd/dropdown'; import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; import { NzEmptyModule } from 'ng-zorro-antd/empty'; import { NzRadioModule } from 'ng-zorro-antd/radio'; import { NzMessageService } from 'ng-zorro-antd/message'; import { NzSelectModule } from 'ng-zorro-antd/select'; import { textbookServer } from '../../../services/textbook'; import { NzSpinModule } from 'ng-zorro-antd/spin'; interface nodes { title: string; key: string; isLeaf?: boolean; branch?: string; children?: Array; } interface depart { name: string; id?: string; code?: string; desc?: string; parent?: object | any; branch: string; } @Component({ selector: 'app-page-role', templateUrl: './page-role.component.html', styleUrls: ['./page-role.component.scss'], imports: [ CommonModule, CommonCompModule, RouterOutlet, CompTableListComponent, NzSpaceModule, NzPageHeaderModule, NzBreadCrumbModule, NzTreeModule, NzCheckboxModule, NzEmptyModule, NzModalModule, NzRadioModule, NzSelectModule, NzSpinModule, ], standalone: true, }) export class PageRoleComponent implements OnInit { @ViewChild(CompTableListComponent) list: CompTableListComponent | undefined; // _Role = _Role Department = Department; user: Parse.User | undefined; className: string | undefined; queryParams: any | undefined; fieldsArray: Array | undefined; searchValue: string = ''; //搜索内容 searchValueNode: string = ''; nodes: Array = []; currentDepart: nodes | any = null; profiles: Array = []; checkedShowFilter: boolean = false; checkedAll: boolean = false; //全选 indeterminate = false; loading = false; pageSize: number = 10; pageIndex: number = 1; profileLength: number = 0; isVisible: boolean = false; activatedNode: NzTreeNode | any; //当前选择节点 editType: string = 'add'; //弹窗类型 activeDepart?: Parse.Object; //当前编辑部门 editObject: depart = { name: '', code: '', desc: '', parent: {}, branch: '', }; parentMap: Array = []; parentList: Array = []; radio: string = ''; /* 添加账号 */ accountIsVisible: boolean = false; account: any = { name: '', phone: '', email: '', password: '', identity: '', department: {}, companyType: '', }; userType: Array = ['工作联系人', '评审专家', '高校联系人', '教师']; parents: Array = []; //所有一级列表 nzExpandedKeys: any = []; //默认展开节点数 modalValue: string = ''; childrenList: Array = []; profileVisible: boolean = false; //用户部门变更 profileAccount: Parse.Object | undefined; //变更部门用户 profileEdit: any = { //变更部门用户json department: {}, companyType: '', identity: '', }; constructor( private route: Router, private activeRoute: ActivatedRoute, private nzContextMenuService: NzContextMenuService, public tbookSer: textbookServer, private modal: NzModalService, private message: NzMessageService ) { this.user = Parse.User.current(); this.className = this.Department.className; this.fieldsArray = this.Department.fieldsArray; this.queryParams = { where: { // user:this.user?.toPointer(), isDeleted: { $ne: true }, }, }; } ngOnInit(): void { this.activeRoute.paramMap.subscribe(async (params) => { let nodes: Array = await this.getDepart(); this.parents = [...nodes]; Promise.all( nodes.map(async (item, index) => { nodes[index].children = await this.getDepart(item.key); // nodes[index]['isExpanded'] = true this.nzExpandedKeys.push(nodes[index]?.key); }) ).then(() => { this.nodes = nodes; }); }); } async getDepart( parent?: string, searchValue?: string, filter?: boolean ): Promise> { let nodes: any = []; let query = new Parse.Query('Department'); if (!filter) { query.equalTo('parent', parent ? parent : undefined); } searchValue && query.contains('name', searchValue); query.notEqualTo('isDeleted', true); query.select('code', 'name', 'branch', 'parent', 'type', 'hasChildren'); query.descending('createdAt'); query.limit(2000); if (this.activeDepart) query.notEqualTo('objectId', this.activeDepart?.id); let res = await query.find(); res.forEach((item) => { nodes.push({ title: item.get('name'), key: item.id, children: [], branch: item.get('branch'), parent: item.get('parent')?.id, //上级 isLeaf: !item.get('hasChildren'), //是否是最下级 type: item.get('type'), }); }); return nodes; } //搜索 async onSearchNodes(e: string, modal?: boolean) { if (modal) { this.parentList = await this.getDepart('', e, true); return; } this.nodes = await this.getDepart('', e, e ? true : false); } //搜索失去焦点 onblur(type: string) { console.log(type); if (type == 'account' || type == 'profileEdit') { this.modalValue = this.account.department?.title; this.modalValue = this.account.profileEdit?.title; } else if (type == 'editObject') { this.modalValue = this.editObject.parent?.title; } } reset(type: string) { this.modalValue = ''; this.parentList = this.nodes; this.parentMap = []; if (type == 'account' || type == 'profileEdit') { this.account.department = {}; this.account.identity = ''; this.account.profileEdit = {}; this.account.profileEdit = ''; } else if (type == 'editObject') { this.editObject.parent = {}; } } //展开/合并 async nzEvent(event: NzFormatEmitEvent): Promise { console.log(event); let node: any = event.node; if (event.eventName === 'expand') { // if (node.origin.isParent) { // node.addChildren([]); // return; // } if (node?._children.length <= 0) { let data = await this.getDepart(node.key); node.addChildren(data); } console.log(this.nodes); } else { // if (node.origin.isParent) { this.loading = true; this.pageIndex = 1; this.currentDepart = node.origin; this.childrenList = await this.tbookSer.getChild(this.currentDepart.key); this.getProfile(); // } } } async getProfile() { this.profiles = []; this.loading = true; let childrens = [this.currentDepart.key]; if (!this.checkedShowFilter) { childrens = this.childrenList; } let queryParams = { where: { $or: [ { user: { $inQuery: { where: { $or: [ { department: { $in: childrens }, }, ], }, className: '_User', }, }, }, ], }, }; let query = Parse.Query.fromJSON('Profile', queryParams); query.include('user'); query.notEqualTo('identity', '国家级管理员'); query.notEqualTo('isDeleted', true); this.profileLength = await query.count(); query.limit(this.pageSize); query.skip((this.pageIndex - 1) * this.pageSize); let r = await query.find(); this.profiles = r; this.loading = false; this.resetChange(); } //分页切换 pageIndexChange(e: any) { console.log(e); this.pageIndex = e; this.getProfile(); } onChecked() { this.pageIndex = 1; this.getProfile(); } //搜索触发 onSearch(event: NzFormatEmitEvent) { this.pageIndex = 1; console.log(event); } contextMenu( $event: MouseEvent, menu: NzDropdownMenuComponent, node?: any ): void { console.log(node); this.activatedNode = node; this.nzContextMenuService.create($event, menu); } //删除部门 async onDelDepart() { this.modal.confirm({ nzTitle: '删除', nzContent: '删除后数据不可恢复,请谨慎操作', nzOkText: '确认', nzOkType: 'primary', nzOkDanger: true, nzOnOk: async () => { new Promise(async (resolve, reject) => { if (this.activatedNode) { let query = new Parse.Query('Department'); let r = await query.get(this.activatedNode?.key); if (r?.id) { r.set('isDeleted', true); await r.save(); } this.message.success('删除成功'); this.nodes = await this.getDepart(); resolve(true); } }).catch(() => console.log('Oops errors!')); }, nzCancelText: '取消', nzOnCancel: () => console.log('Cancel'), }); } onAllChecked(checked: boolean): void { this.profiles.forEach((item) => { if (checked) { this.setOfCheckedId.add(item.id); } else { this.setOfCheckedId.delete(item.id); } }); this.checkedAll = checked; } onItemChecked(id: string, e: boolean) { if (e) { this.setOfCheckedId.add(id); } else { this.setOfCheckedId.delete(id); } this.checkedAll = this.profiles.every((item) => this.setOfCheckedId.has(item.id) ); } //添加成员 addMember() { this.radio = ''; this.modalValue = ''; this.parentList = this.nodes; this.account = { name: '', phone: '', email: '', password: '', identity: '', department: {}, companyType: '', }; this.accountIsVisible = true; } //新建打开弹窗 async showModalDepart(type: string) { this.parentList = this.nodes; this.editObject = { name: '', code: '', desc: '', parent: '', branch: '', }; this.radio = ''; this.modalValue = ''; if (type == 'edit') { let query = new Parse.Query('Department'); query.include('parent', 'parent.parent'); let r = await query.get(this.activatedNode?.key); this.activeDepart = r; this.editObject = { name: this.activeDepart.get('name'), code: this.activeDepart.get('code'), desc: this.activeDepart.get('desc'), parent: { title: this.activeDepart.get('parent')?.get('name'), id: this.activeDepart.get('parent')?.id, }, branch: this.activeDepart.get('branch'), }; this.modalValue = this.activeDepart.get('parent')?.get('name'); this.parentMap = await this.tbookSer.formatNode( this.activeDepart.get('parent')?.id ); if (r?.get('parent')?.get('parent')?.id) { this.parentList = await this.getDepart( r.get('parent')?.get('parent').id ); } else { this.parentList = this.parents; } this.radio = this.activeDepart.get('parent')?.id; } else if (type == 'add' && this.activatedNode) { this.editObject.parent = { title: this.activatedNode.origin.title, id: this.activatedNode.origin.key, }; this.radio = this.activatedNode.origin.key; this.modalValue = this.activatedNode.origin.title; this.editObject.branch = this.activatedNode.origin.branch || this.activatedNode.origin.title; this.parentMap = await this.tbookSer.formatNode( this.activatedNode.origin.key ); if (this.activatedNode?.origin.branch) { this.parentList = await this.getDepart( this.activatedNode?.origin.branch ); } } console.log(this.parentMap); this.editType = type; this.isVisible = true; } async onPre(data?: any, index?: number) { if (!data) { this.parentList = await this.getDepart(); this.parentMap = []; return; } if (index == this.parentMap.length - 1) return; this.parentMap.splice((index || 0) + 1); this.parentList = await this.getDepart(data?.key); this.radio = ''; } //选择所属类别下级列表 async onCheckedDepart(type: string, e: any, checked?: boolean) { console.log(e); this.radio = e.key; if (type == 'account' || type == 'profileEdit') { this.account.identity = ''; this.profileEdit.identity = ''; } this.parentMap = await this.tbookSer.formatNode(e.key); if (checked || e.isLeaf) { this.pushValue(type, e); return; } if (e.isLeaf) { return; } this.parentList = await this.getDepart(e?.key); } //赋值 pushValue(type: string, e: any) { this.modalValue = e.title; this.radio = e.key; if (type == 'account' && e.parent) { this.account.department = { title: e.title, id: e.key }; this.account.companyType = e.branch || e.title; this.userType = this.parents.some((item) => e.parent == item.key) ? !e.type ? ['工作联系人'] : ['评审专家', '工作联系人', '教师'] : e.type == '单位' ? ['评审专家', '高校联系人', '教师'] : ['评审专家', '教师']; } else if (type == 'profileEdit' && e.parent) { this.profileEdit.department = { title: e.title, id: e.key }; this.profileEdit.companyType = e.branch || e.title; this.userType = this.parents.some((item) => e.parent == item.key) ? !e.type ? ['工作联系人'] : ['评审专家', '工作联系人', '教师'] : e.type == '单位' ? ['评审专家', '高校联系人', '教师'] : ['评审专家', '教师']; } else { this.editObject.parent = { title: e.title, id: e.key, }; this.editObject.branch = e.branch || e.title; } } //保存编辑&新增部门 async handleOk(): Promise { if (!this.editObject?.name || !this.editObject.parent?.id) { this.message.error('请填写完整信息'); return; } if (this.activeDepart?.id && this.editType == 'edit') { this.activeDepart.set('name', this.editObject?.name); this.activeDepart.set('code', this.editObject?.code); this.activeDepart.set('desc', this.editObject.desc); this.activeDepart.set('parent', { __type: 'Pointer', className: 'Department', objectId: this.editObject.parent?.id, }); this.activeDepart.set('branch', this.editObject.branch); } else { let obj = Parse.Object.extend('Department'); this.activeDepart = new obj(); this.activeDepart?.set('name', this.editObject?.name); this.activeDepart?.set('code', this.editObject?.code); this.activeDepart?.set('desc', this.editObject.desc); this.activeDepart?.set('parent', { __type: 'Pointer', className: 'Department', objectId: this.editObject.parent?.id, }); this.activeDepart?.set('branch', this.editObject.branch); } let type; let filters = ['出版单位', '教育部直属高校']; if (filters.includes(this.editObject.parent?.title)) { type = '单位'; } this.activeDepart?.set('type', type); await this.activeDepart?.save(); if (!type && this.activeDepart?.id) { //判断添加的是部门还是单位 let leng = await this.tbookSer.formatNode(this.activeDepart.id); if (leng.length > 2) { console.log(leng.length); if (filters.includes(leng[0].title)) { this.activeDepart?.set('type', '部门'); } else { this.activeDepart?.set('type', leng.length > 3 ? '部门' : '单位'); } leng.slice(); await this.activeDepart?.save(); } } await this.updateChildren(); this.isVisible = false; this.message.success(this.editType == 'edit' ? '保存' : '添加' + '成功'); this.activeDepart = undefined; this.nodes = await this.getDepart(); } //更新上级children字段 async updateChildren() { let query = new Parse.Query('Department'); query.equalTo('objectId', this.editObject.parent?.id); query.select('hasChildren'); let r = await query.first(); if (r?.id && !r.get('hasChildren')) { r?.set('hasChildren', true); await r.save(); } return; } //变更用户部门 async showProfile(data: Parse.Object) { let id = data?.get('user')?.get('department')?.id || data?.get('user')?.get('department')?.objectId let query = new Parse.Query('Department'); query.include('parent', 'parent.parent'); let r = await query.get(id); this.parentMap = await this.tbookSer.formatNode(id); if (r?.get('parent')?.id) { this.parentList = await this.getDepart(r.get('parent').id); } else { this.parentList = this.parents; } this.radio = id; this.profileAccount = data; this.profileEdit = { //变更部门用户json department: { key: r?.id, title: r?.get('title'), }, companyType: data?.get('companyType'), identity: data?.get('identity'), }; let parms = { title: r?.get('name'), key: r?.id, type: r?.get('type'), parent: r?.get('parent')?.id, branch: r?.get('branch'), }; console.log(parms); this.pushValue('profileEdit', parms); this.modalValue = r?.get('name'); this.profileVisible = true; } handleCancel(): void { console.log('Button cancel clicked!'); this.isVisible = false; this.activatedNode = undefined; this.parentMap = []; this.accountIsVisible = false; this.account = { name: '', phone: '', email: '', password: '', identity: '', department: {}, companyType: '', }; this.profileVisible = false; this.profileAccount = undefined; this.profileEdit = { //变更部门用户json department: {}, companyType: '', identity: '', }; } /* 组织 */ showModalOrganize() { this.message.warning('权限灰度中'); } goDateil(id: string) { this.route.navigate(['/nav-admin/manage/user/edit', { id: id }]); } randomPassword() { this.account.password = this.tbookSer.randomPassword(); console.log(this.account.password); } /* 添加账号 */ isLoadingOne: boolean = false; async accountComplete() { if (this.isLoadingOne) return; this.isLoadingOne = true; this.account.email = this.account?.email.trim(); this.account.phone = this.account?.phone.trim(); this.account.name = this.account?.name.trim(); this.account.password = this.account?.password.trim(); if (!(await this.authVrifly())) { this.isLoadingOne = false; return; } try { let obj = Parse.Object.extend('_User'); let user = new obj(); user?.set('username', this.account?.email || this.account?.phone); user?.set('name', this.account?.name); user?.set('phone', this.account?.phone); this.account?.email && user?.set('email', this.account?.email); user?.set('password', this.account.password); user?.set('accountState', '已认证'); user?.set('department', { __type: 'Pointer', className: 'Department', objectId: this.account.department?.id, }); let u = await user.save(); let p = Parse.Object.extend('Profile'); let profile = new p(); profile?.set('user', u?.toPointer()); profile?.set('companyType', this.account.companyType); profile?.set('email', this.account.email); profile?.set('identity', this.account.identity); let res = await profile?.save(); this.isLoadingOne = false; this.accountIsVisible = false; this.account = null; Parse.Cloud.run('aliSmsSend', { mobileList: [this.account?.phone], templateCode: 'SMS_469060724', params: {}, signName: '普通高等教育教材网', }); this.modal.success({ nzTitle: '添加成功', nzContent: '', nzOnOk: () => { this.currentDepart && this.getProfile(); }, }); } catch (err: any) { console.warn('添加用户错误', err); this.isLoadingOne = false; this.message.error( err?.Error || '错误:请检查用户邮箱或手机号是否已存在' ); return; } } //保存更新部门 async updateProfile() { if (this.isLoadingOne) return; this.isLoadingOne = true; if ( !this.profileEdit?.department.id || !this.profileEdit?.department?.title || !this.profileEdit?.identity || !this.profileEdit.companyType ) { this.message.warning('填写信息不完整'); this.isLoadingOne = false; return; } try { //如果更换用户之前是工作联系人,卸载对应流程工作联系人 if(this.profileAccount?.id && this.profileAccount?.get('identity') == '工作联系人'){ await this.tbookSer.updateProfileSubmitted(this.profileAccount?.id,'del') } this.profileAccount?.set('identity', this.profileEdit?.identity); this.profileAccount?.set('companyType', this.profileEdit?.companyType); await this.profileAccount?.save(); this.profileAccount?.get('user')?.set('department', { __type: 'Pointer', className: 'Department', objectId: this.profileEdit?.department.id, }); await this.profileAccount?.get('user')?.save(); if(this.profileEdit?.identity == '工作联系人' && this.profileAccount?.id){ let auth = await this.tbookSer.updateProfileSubmitted(this.profileAccount?.id,'save',this.profileEdit?.department.id,this.message) if(!auth){ this.isLoadingOne = false; return } } this.pageIndex = 1; this.getProfile(); this.isLoadingOne = false; this.handleCancel() } catch (err) { console.log(err); this.message.error('修改出错,请稍后重试'); this.isLoadingOne = false; } } async authVrifly(): Promise { this.account.email = this.account?.email.trim(); this.account.phone = this.account?.phone.trim(); this.account.name = this.account?.name.trim(); this.account.password = this.account?.password.trim(); if ( !this.account?.name || !this.account.department?.id || !this.account.password || !this.account.phone || !this.account?.email ) { this.message.warning('请填写必填项'); return; } if (!this.account.identity) { this.message.error('请选择人员类型'); return; } let a = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/; if (this.account.phone && !String(this.account.phone).match(a)) { this.message.error('请填写正确手机号'); return; } let m = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if (!String(this.account.email).match(m)) { this.message.error('邮箱格式有误'); return; } // if(!this.account?.email && !this.account?.phone){ // this.message.error("邮箱或手机号必须填写一项"); // return; // } console.log(this.account.password); if ( !(this.account.password.length >= 6 && this.account.password.length <= 18) ) { this.message.error( '密码格式错误,请填写6-18位非空字符串(数字、大小写字母或英文符号)' ); return; } if (!(await this.tbookSer.userFind(this.account.phone))) { this.message.error('手机号已存在'); return; } return true; } setOfCheckedId = new Set(); //移除部门 // async removeBranch(data: Parse.Object) { // if (data?.get('user')?.id) { // data?.get('user')?.set('department', null); // await data?.get('user')?.save(); // this.message.success('移除成功'); // this.getProfile(); // } // } // removeBranchAll() { // this.modal.confirm({ // nzTitle: '批量移除', // nzContent: `请谨慎操作`, // nzOkText: '确认', // nzOkType: 'primary', // nzOkDanger: true, // nzOnOk: async () => { // let selectedList = this.profiles.filter((item: any) => // this.setOfCheckedId.has(item?.id) // ); // let romovePromiseList = selectedList.map((item: any) => { // return new Promise(async (resolve) => { // item?.get('user')?.set('department', null); // await item?.get('user')?.save(); // resolve(true); // }); // }); // try { // await Promise.all(romovePromiseList); // this.message.error('移除成功'); // this.getProfile(); // this.resetChange(); // } catch (err) {} // }, // nzCancelText: '取消', // nzOnCancel: () => console.log('Cancel'), // }); // } //删除用户 async deleteSelected(data?: Parse.Object) { let filters = []; if (data?.id) { filters = [data?.id]; } else { filters = Array.from(this.setOfCheckedId); } console.log(filters); let v = await this.tbookSer.getEduProcessProf(filters); this.modal.confirm({ nzTitle: `确认${data?.id ? '删除该用户' : '批量删除'}吗?`, nzContent: `${ v ? '该用户已经被设置为【'+ v + '】的工作联系人,删除后,你需要重新设置该流程的工作联系人' : '该用户已经提交至申报流程中的教材不会被删除' }`, nzOkText: '确认', nzOkType: 'primary', nzOkDanger: true, nzOnOk: async () => { let selectedList = this.profiles.filter((item: any) => this.setOfCheckedId.has(item?.id) ); let deletePromiseList = selectedList.map((item: any) => { return new Promise(async (resolve) => { await item.get('user')?.destroy(); await item.destroy(); resolve(true); }); }); try { await Promise.all(deletePromiseList); this.getProfile(); this.resetChange(); } catch (err) {} }, nzCancelText: '取消', nzOnCancel: () => console.log('Cancel'), }); } resetChange() { this.setOfCheckedId = new Set(); this.checkedAll = false; } }