| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 | import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';import { CommonModule } from '@angular/common';import { FormsModule } from '@angular/forms';import { DesignerTeamAssignmentModalComponent } from '../../../pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component';import type { DesignerAssignmentResult } from '../../../pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component';interface ApprovalData {  projectId: string;  projectName: string;  quotationTotal: number;  assignedTeams: TeamInfo[];  projectInfo: {    title: string;    projectType: string;    demoday: Date;    deadline?: Date;  };  submitter: {    id: string;    name: string;    role: string;  };  submitTime: Date;}interface TeamInfo {  id: string;  name: string;  spaces: string[];}@Component({  selector: 'app-order-approval-panel',  standalone: true,  imports: [CommonModule, FormsModule, DesignerTeamAssignmentModalComponent],  templateUrl: './order-approval-panel.component.html',  styleUrls: ['./order-approval-panel.component.scss']})export class OrderApprovalPanelComponent implements OnInit {  @Input() project: any;  // Parse Project 对象  @Input() currentUser: any;  // 当前组长用户  @Output() approvalCompleted = new EventEmitter<{    action: 'approved' | 'rejected';    reason?: string;    comment?: string;  }>();  approvalData: ApprovalData | null = null;  showRejectModal = false;  rejectReason = '';  approvalComment = '';  isSubmitting = false;  // 驳回原因快捷选项  rejectReasons = [    '报价不合理,需要调整',    '设计师分配不当',    '项目信息不完整',    '需要补充项目资料',    '其他原因(请在下方说明)'  ];  selectedRejectReason = '';  // 编辑设计师分配相关  isEditingTeams = false;  editedTeams: TeamInfo[] = [];  availableDesigners: any[] = [];    // 设计师分配弹窗  showDesignerModal = false;  ngOnInit() {    this.loadApprovalData();  }  /**   * 加载审批数据   */  private loadApprovalData() {    if (!this.project) return;    const data = this.project.get('data') || {};    const approvalHistory = data.approvalHistory || [];    const latestRecord = approvalHistory[approvalHistory.length - 1];    this.approvalData = {      projectId: this.project.id,      projectName: this.project.get('title'),      quotationTotal: latestRecord?.quotationTotal || 0,      assignedTeams: latestRecord?.teams || [],      projectInfo: {        title: this.project.get('title'),        projectType: this.project.get('projectType'),        demoday: this.project.get('demoday'),        deadline: this.project.get('deadline')      },      submitter: latestRecord?.submitter || { id: '', name: '未知', role: '未知' },      submitTime: latestRecord?.submitTime || new Date()    };  }  /**   * 通过审批   */  async approveOrder() {    if (this.isSubmitting) return;        const confirmed = confirm('确认通过此订单审批吗?');    if (!confirmed) return;    this.isSubmitting = true;    try {      this.approvalCompleted.emit({        action: 'approved',        comment: this.approvalComment || undefined      });    } finally {      this.isSubmitting = false;    }  }  /**   * 打开驳回弹窗   */  openRejectModal() {    this.showRejectModal = true;    this.rejectReason = '';    this.selectedRejectReason = '';    this.approvalComment = '';  }  /**   * 关闭驳回弹窗   */  closeRejectModal() {    this.showRejectModal = false;  }  /**   * 选择驳回原因   */  selectRejectReason(reason: string) {    this.selectedRejectReason = reason;    if (reason !== '其他原因(请在下方说明)') {      this.rejectReason = reason;    } else {      this.rejectReason = '';    }  }  /**   * 提交驳回   */  async submitRejection() {    const finalReason = this.selectedRejectReason === '其他原因(请在下方说明)'       ? this.rejectReason       : this.selectedRejectReason;    if (!finalReason || !finalReason.trim()) {      alert('请填写驳回原因');      return;    }    if (this.isSubmitting) return;    this.isSubmitting = true;    try {      this.approvalCompleted.emit({        action: 'rejected',        reason: finalReason,        comment: this.approvalComment || undefined      });      this.closeRejectModal();    } finally {      this.isSubmitting = false;    }  }  /**   * 格式化金额   */  formatCurrency(amount: number): string {    return `¥${amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;  }  /**   * 开启编辑设计师分配模式   */  startEditTeams() {    this.isEditingTeams = true;    // 深拷贝当前团队数据,避免直接修改原数据    this.editedTeams = JSON.parse(JSON.stringify(this.approvalData?.assignedTeams || []));    // 加载可用设计师列表(这里需要从数据库加载)    this.loadAvailableDesigners();  }  /**   * 取消编辑设计师分配   */  cancelEditTeams() {    this.isEditingTeams = false;    this.editedTeams = [];  }  /**   * 保存设计师分配修改   */  saveTeamsEdit() {    if (!this.approvalData) return;        // 更新审批数据中的团队信息    this.approvalData.assignedTeams = JSON.parse(JSON.stringify(this.editedTeams));        // 更新项目数据    const data = this.project.get('data') || {};    const approvalHistory = data.approvalHistory || [];    const latestRecord = approvalHistory[approvalHistory.length - 1];    if (latestRecord) {      latestRecord.teams = this.editedTeams;      this.project.set('data', data);    }        this.isEditingTeams = false;    alert('设计师分配已更新');  }  /**   * 加载可用设计师列表   */  private async loadAvailableDesigners() {    // TODO: 从数据库加载设计师列表    // 这里暂时使用模拟数据    this.availableDesigners = [      { id: '1', name: '张三', avatar: '' },      { id: '2', name: '李四', avatar: '' },      { id: '3', name: '王五', avatar: '' }    ];  }  /**   * 移除团队成员   */  removeTeam(index: number) {    this.editedTeams.splice(index, 1);  }  /**   * 添加团队成员(打开设计师选择弹窗)   */  addTeamMember() {    this.showDesignerModal = true;  }  /**   * 关闭设计师选择弹窗   */  closeDesignerModal() {    this.showDesignerModal = false;  }  /**   * 处理设计师选择结果   */  handleDesignerAssignment(result: DesignerAssignmentResult) {    console.log('设计师分配结果:', result);        // 将选择的设计师添加到编辑列表中    if (result.selectedDesigners && result.selectedDesigners.length > 0) {      result.selectedDesigners.forEach(designer => {        // 查找该设计师的空间分配        const spaceAssignment = result.spaceAssignments?.find(          sa => sa.designerId === designer.id        );                // 获取空间名称列表(直接使用spaceIds,它们通常已经是名称或可读ID)        let spaces: string[] = [];        if (spaceAssignment && spaceAssignment.spaceIds && spaceAssignment.spaceIds.length > 0) {          spaces = spaceAssignment.spaceIds;        }                // 检查是否已存在该设计师(避免重复添加)        const existingIndex = this.editedTeams.findIndex(t => t.id === designer.id);        if (existingIndex >= 0) {          // 更新现有设计师的空间          this.editedTeams[existingIndex].spaces = spaces;          alert(`已更新 ${designer.name} 的空间分配`);        } else {          // 添加新设计师          this.editedTeams.push({            id: designer.id,            name: designer.name,            spaces: spaces          });          alert(`已添加设计师:${designer.name}${spaces.length > 0 ? '\n负责空间:' + spaces.join(', ') : ''}`);        }      });    }        this.closeDesignerModal();  }  /**   * 编辑团队空间   */  editTeamSpaces(team: TeamInfo) {    const currentSpaces = team.spaces.join(', ');    const spacesInput = prompt('请输入负责的空间(用逗号分隔):', currentSpaces);    if (spacesInput !== null) {      team.spaces = spacesInput.split(',').map(s => s.trim()).filter(s => s);    }  }}
 |