| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 | 
							- import { Component, OnInit, signal } from '@angular/core';
 
- import { CommonModule } from '@angular/common';
 
- import { FormsModule } from '@angular/forms';
 
- import { DepartmentService } from '../services/department.service';
 
- import { EmployeeService } from '../services/employee.service';
 
- import { FmodeObject } from 'fmode-ng/core';
 
- interface Department {
 
-   id: string;
 
-   name: string;
 
-   leader: FmodeObject;
 
-   leaderName: string;
 
-   leaderId?: string;
 
-   type: string;
 
-   memberCount: number;
 
-   createdAt?: Date;
 
- }
 
- interface Employee {
 
-   id: string;
 
-   name: string;
 
-   roleName: string;
 
- }
 
- @Component({
 
-   selector: 'app-departments',
 
-   standalone: true,
 
-   imports: [CommonModule, FormsModule],
 
-   templateUrl: './departments.html',
 
-   styleUrls: ['./departments.scss']
 
- })
 
- export class Departments implements OnInit {
 
-   // 数据
 
-   departments = signal<Department[]>([]);
 
-   employees = signal<Employee[]>([]); // 可选择的组长列表
 
-   loading = signal(false);
 
-   // 筛选
 
-   keyword = signal('');
 
-   // 侧边面板
 
-   showPanel = false;
 
-   panelMode: 'add' | 'detail' | 'edit' = 'add';
 
-   currentDepartment: Department | null = null;
 
-   formModel: Partial<Department> = {};
 
-   // 统计
 
-   total = signal(0);
 
-   constructor(
 
-     private departmentService: DepartmentService,
 
-     private employeeService: EmployeeService
 
-   ) {}
 
-   ngOnInit(): void {
 
-     this.loadDepartments();
 
-     this.loadLeaders();
 
-   }
 
-   async loadDepartments(): Promise<void> {
 
-     this.loading.set(true);
 
-     try {
 
-       const depts = await this.departmentService.findDepartments({
 
-         type: 'project'
 
-       });
 
-       const deptList: Department[] = await Promise.all(
 
-         depts.map(async d => {
 
-           const json = this.departmentService.toJSON(d);
 
-           const memberCount = await this.departmentService.countDepartmentMembers(json.objectId);
 
-           return {
 
-             id: json.objectId,
 
-             name: json.name || '未命名项目组',
 
-             leader: d?.get("leader"),
 
-             leaderName: d?.get("leader")?.get("name") || '未分配',
 
-             leaderId: d?.get("leader").id,
 
-             type: json.type || 'project',
 
-             memberCount,
 
-             createdAt: json.createdAt?.iso || json.createdAt
 
-           };
 
-         })
 
-       );
 
-       this.departments.set(deptList);
 
-       this.total.set(deptList.length);
 
-     } catch (error) {
 
-       console.error('加载项目组失败:', error);
 
-     } finally {
 
-       this.loading.set(false);
 
-     }
 
-   }
 
-   async loadLeaders(): Promise<void> {
 
-     try {
 
-       // 加载所有可以担任组长的员工(组长角色)
 
-       const leaders = await this.employeeService.findEmployees({
 
-         roleName: '组长'
 
-       });
 
-       this.employees.set(
 
-         leaders.map(l => {
 
-           const json = this.employeeService.toJSON(l);
 
-           return {
 
-             id: json.objectId,
 
-             name: json.name,
 
-             roleName: json.roleName
 
-           };
 
-         })
 
-       );
 
-     } catch (error) {
 
-       console.error('加载组长列表失败:', error);
 
-     }
 
-   }
 
-   get filtered() {
 
-     const kw = this.keyword().trim().toLowerCase();
 
-     if (!kw) return this.departments();
 
-     return this.departments().filter(
 
-       d =>
 
-         d.name.toLowerCase().includes(kw) ||
 
-         d.leaderName.toLowerCase().includes(kw)
 
-     );
 
-   }
 
-   resetFilters() {
 
-     this.keyword.set('');
 
-   }
 
-   // 新建项目组
 
-   addDepartment() {
 
-     this.formModel = {
 
-       name: '',
 
-       leaderId: undefined,
 
-       type: 'project'
 
-     };
 
-     this.currentDepartment = null;
 
-     this.panelMode = 'add';
 
-     this.showPanel = true;
 
-   }
 
-   // 查看详情
 
-   viewDepartment(dept: Department) {
 
-     this.currentDepartment = dept;
 
-     this.panelMode = 'detail';
 
-     this.showPanel = true;
 
-   }
 
-   // 编辑
 
-   editDepartment(dept: Department) {
 
-     this.currentDepartment = dept;
 
-     this.formModel = { ...dept };
 
-     this.panelMode = 'edit';
 
-     this.showPanel = true;
 
-   }
 
-   // 关闭面板
 
-   closePanel() {
 
-     this.showPanel = false;
 
-     this.panelMode = 'add';
 
-     this.currentDepartment = null;
 
-     this.formModel = {};
 
-   }
 
-   // 保存新增
 
-   async saveDepartment() {
 
-     const name = (this.formModel.name || '').trim();
 
-     if (!name) {
 
-      window?.fmode?.alert('请输入项目组名称');
 
-       return;
 
-     }
 
-     if (!this.formModel.leaderId) {
 
-      window?.fmode?.alert('请选择组长');
 
-       return;
 
-     }
 
-     try {
 
-       await this.departmentService.createDepartment({
 
-         name,
 
-         leaderId: this.formModel.leaderId,
 
-         type: 'project'
 
-       });
 
-       await this.loadDepartments();
 
-       this.closePanel();
 
-     } catch (error) {
 
-       console.error('创建项目组失败:', error);
 
-      window?.fmode?.alert('创建项目组失败,请重试');
 
-     }
 
-   }
 
-   // 提交编辑
 
-   async updateDepartment() {
 
-     if (!this.currentDepartment) return;
 
-     const name = (this.formModel.name || '').trim();
 
-     if (!name) {
 
-      window?.fmode?.alert('请输入项目组名称');
 
-       return;
 
-     }
 
-     if (!this.formModel.leaderId) {
 
-      window?.fmode?.alert('请选择组长');
 
-       return;
 
-     }
 
-     try {
 
-       await this.departmentService.updateDepartment(this.currentDepartment.id, {
 
-         name,
 
-         leaderId: this.formModel.leaderId
 
-       });
 
-       await this.loadDepartments();
 
-       this.closePanel();
 
-     } catch (error) {
 
-       console.error('更新项目组失败:', error);
 
-      window?.fmode?.alert('更新项目组失败,请重试');
 
-     }
 
-   }
 
-   // 删除
 
-   async deleteDepartment(dept: Department) {
 
-     if (!await window?.fmode?.confirm(`确定要删除项目组 "${dept.name}" 吗?`)) {
 
-       return;
 
-     }
 
-     try {
 
-       await this.departmentService.deleteDepartment(dept.id);
 
-       await this.loadDepartments();
 
-     } catch (error) {
 
-       console.error('删除项目组失败:', error);
 
-      window?.fmode?.alert('删除项目组失败,请重试');
 
-     }
 
-   }
 
-   // 导出
 
-   exportDepartments() {
 
-     const header = ['项目组名称', '组长', '成员数', '创建时间'];
 
-     const rows = this.filtered.map(d => [
 
-       d.name,
 
-       d.leaderName,
 
-       String(d.memberCount),
 
-       d.createdAt instanceof Date
 
-         ? d.createdAt.toISOString().slice(0, 10)
 
-         : String(d.createdAt || '')
 
-     ]);
 
-     this.downloadCSV('项目组列表.csv', [header, ...rows]);
 
-   }
 
-   private downloadCSV(filename: string, rows: (string | number)[][]) {
 
-     const escape = (val: string | number) => {
 
-       const s = String(val ?? '');
 
-       if (/[",\n]/.test(s)) return '"' + s.replace(/"/g, '""') + '"';
 
-       return s;
 
-     };
 
-     const csv = rows.map(r => r.map(escape).join(',')).join('\n');
 
-     const blob = new Blob(['\ufeff', csv], {
 
-       type: 'text/csv;charset=utf-8;'
 
-     });
 
-     const url = URL.createObjectURL(blob);
 
-     const a = document.createElement('a');
 
-     a.href = url;
 
-     a.download = filename;
 
-     a.click();
 
-     URL.revokeObjectURL(url);
 
-   }
 
- }
 
 
  |