浏览代码

申报单位管理

warrior 8 月之前
父节点
当前提交
62ec9ad4d7

+ 5 - 5
projects/textbook/src/app/comp-manage/comp-manage.component.ts

@@ -50,11 +50,11 @@ export class CompManageComponent implements OnInit {
             path:"/nav-admin/manage/user",
             id:'2-1',
           },
-          // {
-          //   name:'组织管理',
-          //   path:"/nav-admin/manage/role",
-          //   id:'2-3',
-          // },
+          {
+            name:'组织管理',
+            path:"/nav-admin/manage/role",
+            id:'2-3',
+          },
         ]
       },
       // {

+ 14 - 0
projects/textbook/src/index.html

@@ -16,6 +16,20 @@
   *{
     font-family: PingFang SC;
   }
+  *::-webkit-scrollbar {
+    width: 5px;
+    height: 5px;
+  }
+  *::-webkit-scrollbar-thumb { 
+    border-radius: 10px;
+    -webkit-box-shadow: inset 0 0 5px #b62749;
+    background: #b62749;
+  }
+  *::-webkit-scrollbar-track {
+    -webkit-box-shadow: inset 0 0 5px #f4cbcd;
+    border-radius: 10px;
+    background: #f5f5f5;
+  }
 </style>
 <body class="mat-typography">
   <app-root></app-root>

+ 3 - 3
projects/textbook/src/modules/nav-admin/components/profile/profile.component.html

@@ -30,13 +30,13 @@
     @for (data of profiles; track data.id) {
     <tr>
       <td nzLeft>
-        {{ data?.get("name") }}
+        {{ data?.get('user').get("name") }}
       </td>
       <td>
-        {{ data?.get("mobile") }}
+        {{ data?.get('user').get("phone") }}
       </td>
       <td>
-        {{ data?.get("email") }}
+        {{ data?.get('user').get("phone") || data?.get("email") }}
       </td>
       <td>
         {{ data?.createdAt | date : "yyyy-MM-dd" }}

+ 1 - 0
projects/textbook/src/modules/nav-admin/components/profile/profile.component.ts

@@ -57,6 +57,7 @@ export class ProfileComponent  implements OnInit {
     this.identity && query.equalTo('identity',this.identity)
     this.province && query.equalTo('province',this.province)
     this.disabled && query.containedIn('objectId',this.idList)
+    query.include('user')
     this.profiles = await query.find()
   }
   onChange(id:string){

+ 181 - 8
projects/textbook/src/modules/nav-admin/page-role/page-role.component.html

@@ -1,8 +1,181 @@
-<comp-table-list
-  #list
-  [schema]="Department"
-  *ngIf="className && fieldsArray"
-  [className]="className"
-  [fieldsArray]="fieldsArray"
-  [queryParams]="queryParams"
-></comp-table-list>
+<nz-page-header>
+  <nz-page-header-title
+    >申报单位管理
+    <br />
+    <div class="subtitle">
+      使用组织机构树管理使用“十四五”高等教育国家规划教材申报系统的所有单位,单位与申报工作流程相关联。
+    </div>
+  </nz-page-header-title>
+  <nz-page-header-extra>
+    <nz-space>
+      <button
+        style="background: #3e49b3; border: 1px #3e49b3"
+        *nzSpaceItem
+        nz-button
+        nzType="primary"
+        (click)="onAdd()"
+      >
+        添加账号
+      </button>
+    </nz-space>
+  </nz-page-header-extra>
+</nz-page-header>
+<div class="edit-content">
+  <div class="tool">
+    <div class="tool-left">
+      <div class="search">
+        <nz-input-group style="width: 210px" [nzPrefix]="prefixTemplateUser">
+          <input
+            type="text"
+            nz-input
+            placeholder="搜索"
+            [(ngModel)]="searchValue"
+          />
+        </nz-input-group>
+        <ng-template #prefixTemplateUser
+          ><span nz-icon nzType="search"></span
+        ></ng-template>
+        <button
+          nz-button
+          nzType="default"
+          nz-dropdown
+          [nzDropdownMenu]="menutep"
+          [nzPlacement]="'bottomLeft'"
+          style="margin-left: 10px"
+        >
+          <span nz-icon nzType="plus" nzTheme="outline"></span>新建
+        </button>
+        <nz-dropdown-menu #menutep="nzDropdownMenu">
+          <ul nz-menu>
+            <li nz-menu-item>
+              <button nz-button nzType="link" style="color: #231c1f">
+                <span nz-icon nzType="plus" nzTheme="outline"></span>添加部门
+              </button>
+            </li>
+            <li nz-menu-item>
+              <button nz-button nzType="link" style="color: #231c1f">
+                <span nz-icon nzType="merge" nzTheme="outline"></span>
+                新建组织
+              </button>
+            </li>
+          </ul>
+        </nz-dropdown-menu>
+      </div>
+      <div class="">{{ currentDepart ? currentDepart.title : "" }}</div>
+      <div class="tag">
+        <span nz-icon nzType="team" nzTheme="outline"></span>
+        {{ profiles.length }}人
+      </div>
+      <label nz-checkbox [(ngModel)]="checkedShowFilter"
+        >仅显示部门直属成员</label
+      >
+    </div>
+    <div class="tool-right">
+      <a nz-button nzType="link" (click)="onAdd()">
+        <span nz-icon nzType="plus" nzTheme="outline"></span>添加账号
+      </a>
+    </div>
+  </div>
+  <div class="layout" #maxWidth>
+    <div class="sider" #sider>
+      <nz-tree
+        [nzData]="nodes"
+        nzAsyncData
+        [nzSearchValue]="searchValue"
+        (nzClick)="nzEvent($event)"
+        (nzExpandChange)="nzEvent($event)"
+        (nzSearchValueChange)="onSearch($event)"
+        [nzTreeTemplate]="nzTreeTemplate"
+      ></nz-tree>
+      <ng-template #nzTreeTemplate let-node let-origin="origin">
+        <span
+          class="custom-node"
+          (contextmenu)="contextMenu($event, menu, node)"
+        >
+          <span class="folder-name">{{ node.title }}</span>
+        </span>
+      </ng-template>
+      <!-- 节点右键菜单 -->
+      <nz-dropdown-menu #menu="nzDropdownMenu">
+        <ul nz-menu>
+          <li nz-menu-item (click)="goEditOKRTree()">添加下级部门</li>
+          <li nz-menu-item (click)="goEditOKRTree()">编辑部门</li>
+          <li nz-menu-item (click)="goEditOKRTree()">删除部门</li>
+        </ul>
+      </nz-dropdown-menu>
+    </div>
+    <div class="breadcrumb">
+      <!-- <comp-table-list
+        #list
+        [schema]="Department"
+        *ngIf="className && fieldsArray"
+        [className]="className"
+        [fieldsArray]="fieldsArray"
+        [queryParams]="queryParams"
+      ></comp-table-list> -->
+      <nz-table
+        #tableData
+        [nzData]="profiles"
+        [nzTotal]="profiles.length"
+        [nzPageSize]="10"
+        style="margin: 10px 0"
+        [nzLoading]="loading"
+        nzSize="middle"
+        [nzNoResult]="emptyResult"
+      >
+        <thead>
+          <tr>
+            <th
+              nzWidth="120px"
+              nzLeft
+              [nzChecked]="checkedAll"
+              [nzIndeterminate]="indeterminate"
+              nzLabel="Select all"
+              (nzCheckedChange)="onAllChecked($event)"
+            ></th>
+            <th nzWidth="120px" nzLeft>用户</th>
+            <th nzWidth="120px">手机号</th>
+            <th nzWidth="120px">邮箱</th>
+            <th nzWidth="120px">人员类型</th>
+            <th nzWidth="120px">所属部门</th>
+            <th nzWidth="120px" nzRight>操作</th>
+          </tr>
+        </thead>
+        <tbody>
+          @for (data of profiles; track data.objectId) {
+          <tr>
+            <td
+              nzLeft
+              [nzChecked]="data.checked"
+              (nzCheckedChange)="onItemChecked(data.objectId, $event)"
+            ></td>
+            <td nzLeft>
+              {{ data?.user.name }}
+            </td>
+            <td>
+              {{ data?.user.phone }}
+            </td>
+            <td>
+              {{ data?.user.email || data?.email }}
+            </td>
+            <td>
+              {{ data?.identity }}
+            </td>
+            <td>
+              {{ data?.user.departmentName }}
+            </td>
+            <td nzRight>
+              <button nz-button nzType="default">
+                <span nz-icon nzType="stop" nzTheme="outline"></span>移除部门
+              </button>
+            </td>
+          </tr>
+          }
+        </tbody>
+      </nz-table>
+      <ng-template #emptyResult>
+        <nz-empty nzNotFoundImage="/img/group-empty.png"></nz-empty>
+      </ng-template>
+    </div>
+  </div>
+</div>

+ 90 - 0
projects/textbook/src/modules/nav-admin/page-role/page-role.component.scss

@@ -0,0 +1,90 @@
+.subtitle{
+  margin-right: 12px;
+  color: #00000073;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.5715;
+  // overflow: hidden;
+  // white-space: nowrap;
+  // text-overflow: ellipsis;
+}
+.edit-content{
+  margin: 0 0 20px;
+  padding: 0 24px;
+  height: calc(100vh - 192px);
+  min-width: 1100px;
+  .tool{
+    display: flex;
+    justify-content: space-between;
+    .tool-left{
+      display: flex;
+      align-items: center;
+      .search{
+        display: flex;
+        width: 300px;
+        margin-right: 20px;
+      }
+      .tag{
+        background: #f7f7f7;
+        display: flex;
+        align-items: center;
+        color: #6f6f6f;
+        line-height: 26px;
+        padding: 0 8px;
+        margin: 0 10px;
+      }
+    }
+  }
+  .layout{
+    display: flex;
+    width: 100%;
+    .sider{
+      width: 300px;
+      margin: 10px 0;
+      height: calc(100vh - 192px);
+      overflow-y: scroll;
+      flex-shrink: 0;
+      .custom-node{
+        display: flex;
+      }
+      .folder-desc{
+        display: none;
+        margin-left: 10px;
+        background-color: white;
+        color: #ba1a1a;
+        border: none;
+      }
+      .custom-node:hover .folder-desc{
+        display: block;
+      }
+      .custom-name:hover .folder-desc{
+        display: block;
+      }
+    }
+    .breadcrumb{
+      flex: 1;
+    }
+  }
+}
+::ng-deep .ant-page-header-heading-title{
+  white-space: normal;
+}
+::ng-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{
+  color: #c6233f;
+}
+::ng-deep .ant-tabs-ink-bar{
+  background: #c6233f;
+}
+::ng-deep .ant-tabs-tab:hover{
+  color: #e97488;
+}
+::ng-deep .ant-tabs-tab-btn:active{
+  color: #e97488;
+}
+::ng-deep .ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected{
+  background-color: #ba1a1a;
+  color: white;
+}
+::ng-deep .ant-tree .ant-tree-node-content-wrapper:hover{
+  background-color: #eae6e6;
+}

+ 157 - 25
projects/textbook/src/modules/nav-admin/page-role/page-role.component.ts

@@ -3,52 +3,184 @@ import { ActivatedRoute, 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 * 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 {
+  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';
+interface nodes {
+  title: string;
+  key: string;
+  isLeaf?: boolean;
+  isParent?: boolean;
+  children?: Array<any>;
+}
 @Component({
   selector: 'app-page-role',
   templateUrl: './page-role.component.html',
   styleUrls: ['./page-role.component.scss'],
-  imports: [CommonModule,RouterOutlet,CompTableListComponent],
+  imports: [
+    CommonModule,
+    CommonCompModule,
+    RouterOutlet,
+    CompTableListComponent,
+    NzSpaceModule,
+    NzPageHeaderModule,
+    NzBreadCrumbModule,
+    NzTreeModule,
+    NzCheckboxModule,
+    NzEmptyModule,
+  ],
   standalone: true,
 })
-export class PageRoleComponent  implements OnInit {
-  @ViewChild(CompTableListComponent) list:CompTableListComponent|undefined
+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<any>|undefined
+  Department = Department;
+  user: Parse.User | undefined;
+  className: string | undefined;
+  queryParams: any | undefined;
+  fieldsArray: Array<any> | undefined;
+  searchValue: string = ''; //搜索内容
+  nodes: Array<nodes | any> = [];
+  currentDepart: nodes | any = null;
+
+  profiles: Array<any> = [];
+  checkedShowFilter: boolean = false;
+
+  checkedAll: boolean = false; //全选
+  indeterminate = false;
+  loading = false;
 
   constructor(
     private route: ActivatedRoute,
     private activeRoute: ActivatedRoute,
-    // private translate:TranslateService,
+    private nzContextMenuService: NzContextMenuService,
   ) {
     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},
-    }}
+    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 isDeleted = params.get('isDeleted')
-      if(isDeleted){
-        this.queryParams.where['isDeleted'] = {$eq:true}
-      }else{
-        this.queryParams.where['isDeleted'] = {$ne:true}
-      }
-      this.list?.ngOnInit()
+      // let isDeleted = params.get('isDeleted');
+      // if (isDeleted) {
+      //   this.queryParams.where['isDeleted'] = { $eq: true };
+      // } else {
+      //   this.queryParams.where['isDeleted'] = { $ne: true };
+      // }
+      // this.list?.ngOnInit();
+      this.nodes = await this.getDepart();
     });
   }
+  async getDepart(
+    parent?: string,
+    searchValue?: string
+  ): Promise<Array<nodes>> {
+    let nodes: any = [];
+    let query = new Parse.Query('Department');
+    query.equalTo('parent', parent ? parent : undefined);
+    searchValue && query.contains('name', searchValue);
+    query.notEqualTo('isDeleted', true);
+    query.select('code', 'name', 'branch', 'parent');
+    query.descending('createdAt');
+    query.limit(2000);
+    let res = await query.find();
+    res.forEach((item) => {
+      nodes.push({
+        title: item.get('name'),
+        key: item.id,
+        children: [],
+        isParent: parent ? true : false, //是否为下级单位
+        isLeaf: false,
+      });
+    });
+    return nodes;
+  }
+  onAdd() {}
+  activatedNode?: NzTreeNode;
+  //展开/合并
+  async nzEvent(event: NzFormatEmitEvent): Promise<void> {
+    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.currentDepart = node.origin;
+        this.getProfile();
+      }
+    }
+  }
+  async getProfile() {
+    this.profiles = []
+    this.loading = true;
+    let query = new Parse.Query('Profile');
+    query.include('user');
+    query.notEqualTo('identity', '国家级管理员')
+    let r = await query.find();
+    let profiles: any[] = []
+    r.forEach(item=>{
+      let _item = item.toJSON()
+      _item['checked'] = false
+      profiles.push(_item);
+    })
+    this.profiles = profiles
+    this.loading = false;
+  }
+  //搜索触发
+  onSearch(event: NzFormatEmitEvent) {
+    console.log(event);
+  }
+  contextMenu($event: MouseEvent, menu: NzDropdownMenuComponent, node?:any): void {
+    console.log(node);
+    this.nzContextMenuService.create($event, menu);
+  }
+  goEditOKRTree(){
+
+  }
 
+  onAllChecked(checked: boolean): void {
+    console.log(checked);
+    this.profiles = this.profiles.map((item) => {
+      item.checked = checked;
+      return item;
+    });
+    this.checkedAll = checked
+  }
+  onItemChecked(id: string, e: boolean) {
+    let checkedAll = true
+    this.profiles = this.profiles.map((item) => {
+      if(id == item.objectId) item.checked = e;
+      if(!item.checked) checkedAll = false
+      return item;
+    });
+    this.checkedAll = checkedAll
+  }
 }