|
@@ -6,6 +6,26 @@ import { FormsModule } from '@angular/forms';
|
|
|
import { MatChipsModule } from '@angular/material/chips';
|
|
|
import { MatIconModule } from '@angular/material/icon';
|
|
|
|
|
|
+// 设计师状态枚举
|
|
|
+export enum DesignerStatus {
|
|
|
+ IDLE = 'idle', // 空闲
|
|
|
+ BUSY = 'busy', // 忙碌
|
|
|
+ VACATION = 'vacation', // 休假
|
|
|
+ TRAINING = 'training' // 培训中
|
|
|
+}
|
|
|
+
|
|
|
+// 设计师状态接口
|
|
|
+export interface DesignerStatusInfo {
|
|
|
+ id: string;
|
|
|
+ name: string;
|
|
|
+ status: DesignerStatus;
|
|
|
+ currentProjects: number;
|
|
|
+ maxCapacity: number;
|
|
|
+ availableFrom?: string; // 预计空闲时间
|
|
|
+ skills: string[];
|
|
|
+ avatar?: string;
|
|
|
+}
|
|
|
+
|
|
|
// 定义客户信息接口
|
|
|
interface Customer {
|
|
|
id: string;
|
|
@@ -60,6 +80,77 @@ export class ConsultationOrderPanelComponent implements OnInit, OnChanges {
|
|
|
showTeamAssignmentModal = false;
|
|
|
selectedDesigner: Designer | null = null;
|
|
|
|
|
|
+ // Mock设计师状态数据
|
|
|
+ mockDesignerStatuses: DesignerStatusInfo[] = [
|
|
|
+ {
|
|
|
+ id: '1',
|
|
|
+ name: '张设计师',
|
|
|
+ status: DesignerStatus.IDLE,
|
|
|
+ currentProjects: 1,
|
|
|
+ maxCapacity: 5,
|
|
|
+ skills: ['现代简约', '北欧风格', '工业风'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '2',
|
|
|
+ name: '李设计师',
|
|
|
+ status: DesignerStatus.BUSY,
|
|
|
+ currentProjects: 4,
|
|
|
+ maxCapacity: 5,
|
|
|
+ availableFrom: '2024-01-25',
|
|
|
+ skills: ['欧式古典', '美式乡村', '中式传统'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '3',
|
|
|
+ name: '王设计师',
|
|
|
+ status: DesignerStatus.BUSY,
|
|
|
+ currentProjects: 5,
|
|
|
+ maxCapacity: 5,
|
|
|
+ availableFrom: '2024-02-01',
|
|
|
+ skills: ['极简主义', '日式禅风', '斯堪的纳维亚'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '4',
|
|
|
+ name: '陈设计师',
|
|
|
+ status: DesignerStatus.IDLE,
|
|
|
+ currentProjects: 2,
|
|
|
+ maxCapacity: 5,
|
|
|
+ skills: ['新中式', '轻奢风格', '混搭风格'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '5',
|
|
|
+ name: '赵设计师',
|
|
|
+ status: DesignerStatus.VACATION,
|
|
|
+ currentProjects: 0,
|
|
|
+ maxCapacity: 5,
|
|
|
+ availableFrom: '2024-02-10',
|
|
|
+ skills: ['现代简约', '北欧风格'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '6',
|
|
|
+ name: '钱设计师',
|
|
|
+ status: DesignerStatus.IDLE,
|
|
|
+ currentProjects: 0,
|
|
|
+ maxCapacity: 5,
|
|
|
+ skills: ['现代简约', '工业风'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '7',
|
|
|
+ name: '孙设计师',
|
|
|
+ status: DesignerStatus.TRAINING,
|
|
|
+ currentProjects: 1,
|
|
|
+ maxCapacity: 5,
|
|
|
+ availableFrom: '2024-01-20',
|
|
|
+ skills: ['新中式', '轻奢风格'],
|
|
|
+ avatar: '/assets/images/default-avatar.svg'
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
// 新增:自动分配用的设计师池(与弹窗组件保持一致的数据结构)
|
|
|
private allDesigners: Designer[] = [
|
|
|
{
|
|
@@ -378,6 +469,51 @@ export class ConsultationOrderPanelComponent implements OnInit, OnChanges {
|
|
|
return this.isFormValid();
|
|
|
}
|
|
|
|
|
|
+ // 设计师选择处理
|
|
|
+ onDesignerSelected(event: Event): void {
|
|
|
+ const selectElement = event.target as HTMLSelectElement;
|
|
|
+ const designerId = selectElement.value;
|
|
|
+
|
|
|
+ if (designerId) {
|
|
|
+ const selectedDesigner = this.mockDesignerStatuses.find(d => d.id === designerId);
|
|
|
+ if (selectedDesigner) {
|
|
|
+ // 检查设计师状态
|
|
|
+ if (selectedDesigner.status === DesignerStatus.IDLE &&
|
|
|
+ selectedDesigner.currentProjects < selectedDesigner.maxCapacity) {
|
|
|
+ // 设计师空闲,可以自动选择
|
|
|
+ this.selectedDesigner = {
|
|
|
+ id: selectedDesigner.id,
|
|
|
+ name: selectedDesigner.name,
|
|
|
+ role: '室内设计师',
|
|
|
+ avatar: selectedDesigner.avatar || '/assets/images/default-avatar.svg',
|
|
|
+ skills: selectedDesigner.skills,
|
|
|
+ workload: { level: 'low', percentage: 0, text: '空闲' },
|
|
|
+ recentTasks: []
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ // 设计师忙碌,需要手动分配
|
|
|
+ this.selectedDesigner = null;
|
|
|
+ // 显示分配弹窗
|
|
|
+ this.showTeamAssignmentModal = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.selectedDesigner = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新阶段状态
|
|
|
+ this.checkStageCompletion();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查设计师是否可用
|
|
|
+ isDesignerAvailable(designerId: string): boolean {
|
|
|
+ const designer = this.mockDesignerStatuses.find(d => d.id === designerId);
|
|
|
+ return designer ?
|
|
|
+ designer.status === DesignerStatus.IDLE &&
|
|
|
+ designer.currentProjects < designer.maxCapacity :
|
|
|
+ false;
|
|
|
+ }
|
|
|
+
|
|
|
// 创建订单方法(支持自动分配空闲设计师)
|
|
|
createOrder() {
|
|
|
// 表单未通过校验则不允许创建
|
|
@@ -385,6 +521,17 @@ export class ConsultationOrderPanelComponent implements OnInit, OnChanges {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 检查是否选择了设计师
|
|
|
+ const selectedDesignerId = this.requirementForm.get('preferredDesigner')?.value;
|
|
|
+ if (selectedDesignerId) {
|
|
|
+ // 检查设计师是否可用
|
|
|
+ if (!this.isDesignerAvailable(selectedDesignerId)) {
|
|
|
+ // 设计师不可用,阻止创建并弹出分配弹窗
|
|
|
+ this.showTeamAssignmentModal = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 若尚未选择设计师,尝试自动分配空闲设计师
|
|
|
if (!this.selectedDesigner) {
|
|
|
const assigned = this.autoAssignDesignerIfAvailable();
|
|
@@ -436,6 +583,11 @@ export class ConsultationOrderPanelComponent implements OnInit, OnChanges {
|
|
|
this.createOrder();
|
|
|
}
|
|
|
|
|
|
+ // 打开团队分配弹窗
|
|
|
+ openTeamAssignmentModal() {
|
|
|
+ this.showTeamAssignmentModal = true;
|
|
|
+ }
|
|
|
+
|
|
|
// 关闭团队分配弹窗
|
|
|
closeTeamAssignmentModal() {
|
|
|
this.showTeamAssignmentModal = false;
|