| 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);
- }
- }
|