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