123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- import { Component, EventEmitter, OnInit, Output, Input, OnChanges, SimpleChanges } from '@angular/core';
- import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
- import { CommonModule } from '@angular/common';
- import { TeamAssignmentModalComponent, Designer } from '../team-assignment-modal/team-assignment-modal.component';
- import { FormsModule } from '@angular/forms';
- import { MatChipsModule } from '@angular/material/chips';
- import { MatIconModule } from '@angular/material/icon';
- // 定义客户信息接口
- interface Customer {
- id: string;
- name: string;
- phone: string;
- wechat?: string;
- avatar?: string;
- customerType?: string;
- source?: string;
- remark?: string;
- demandType?: string;
- preferenceTags?: string[];
- followUpStatus?: string;
- }
- @Component({
- selector: 'app-consultation-order-panel',
- standalone: true,
- imports: [
- CommonModule,
- ReactiveFormsModule,
- FormsModule,
- MatChipsModule,
- MatIconModule,
- TeamAssignmentModalComponent
- ],
- templateUrl: './consultation-order-panel.component.html',
- styleUrls: ['./consultation-order-panel.component.scss']
- })
- export class ConsultationOrderPanelComponent implements OnInit, OnChanges {
- @Output() orderCreated = new EventEmitter<any>();
- @Output() projectCreated = new EventEmitter<any>(); // 新增项目创建成功事件
- @Input() syncData: any = null; // 接收同步的订单数据
- // 搜索客户关键词
- searchKeyword = '';
- // 搜索结果列表
- searchResults: Customer[] = [];
- // 选中的客户
- selectedCustomer: Customer | null = null;
- // 表单提交状态
- isSubmitting = false;
- // 项目需求卡片展开状态 - 默认展开以便用户填写必填字段
- isRequirementCardExpanded = true;
- // 需求表单
- requirementForm: FormGroup;
- // 客户表单
- customerForm: FormGroup;
-
- // 团队分配弹窗相关
- showTeamAssignmentModal = false;
- selectedDesigner: Designer | null = null;
- // 新增:自动分配用的设计师池(与弹窗组件保持一致的数据结构)
- private allDesigners: Designer[] = [
- {
- id: '1',
- name: '张设计师',
- role: '高级室内设计师',
- avatar: '/assets/images/default-avatar.svg',
- skills: ['现代简约', '北欧风格', '工业风'],
- workload: { level: 'low', percentage: 30, text: '轻度' },
- recentTasks: [
- { id: '1', name: '海景别墅设计', projectName: '海景别墅设计', stage: 'modeling', deadline: '2024-01-15' },
- { id: '2', name: '现代公寓改造', projectName: '现代公寓改造', stage: 'rendering', deadline: '2024-01-20' }
- ]
- },
- {
- id: '2',
- name: '李设计师',
- role: '资深设计总监',
- avatar: '/assets/images/default-avatar.svg',
- skills: ['欧式古典', '美式乡村', '中式传统'],
- workload: { level: 'medium', percentage: 65, text: '中度' },
- recentTasks: [
- { id: '3', name: '豪华会所设计', projectName: '豪华会所设计', stage: 'soft-decoration', deadline: '2024-01-18' },
- { id: '4', name: '商业空间规划', projectName: '商业空间规划', stage: 'post-production', deadline: '2024-01-25' },
- { id: '5', name: '私人定制住宅', projectName: '私人定制住宅', stage: 'modeling', deadline: '2024-02-01' }
- ]
- },
- {
- id: '3',
- name: '王设计师',
- role: '创意设计师',
- avatar: '/assets/images/default-avatar.svg',
- skills: ['极简主义', '日式禅风', '斯堪的纳维亚'],
- workload: { level: 'high', percentage: 85, text: '重度' },
- recentTasks: [
- { id: '6', name: '艺术画廊设计', projectName: '艺术画廊设计', stage: 'rendering', deadline: '2024-01-12' },
- { id: '7', name: '精品酒店套房', projectName: '精品酒店套房', stage: 'soft-decoration', deadline: '2024-01-16' },
- { id: '8', name: '创意办公空间', projectName: '创意办公空间', stage: 'post-production', deadline: '2024-01-22' },
- { id: '9', name: '高端住宅项目', projectName: '高端住宅项目', stage: 'modeling', deadline: '2024-01-28' }
- ]
- },
- {
- id: '4',
- name: '陈设计师',
- role: '室内设计师',
- avatar: '/assets/images/default-avatar.svg',
- skills: ['新中式', '轻奢风格', '混搭风格'],
- workload: { level: 'low', percentage: 20, text: '轻度' },
- recentTasks: [
- { id: '10', name: '温馨家庭住宅', projectName: '温馨家庭住宅', stage: 'modeling', deadline: '2024-01-30' }
- ]
- },
- // 新增:完全空闲的设计师用于自动分配展示
- {
- id: '5',
- name: '赵设计师',
- role: '室内设计师',
- avatar: '/assets/images/default-avatar.svg',
- skills: ['现代简约', '北欧风格'],
- workload: { level: 'low', percentage: 0, text: '空闲' },
- recentTasks: []
- }
- ];
- // 样式选项
- styleOptions = [
- '现代简约', '北欧风', '工业风', '新中式', '法式轻奢', '日式', '美式', '混搭'
- ];
- // 项目小组选项
- projectGroupOptions = [
- '设计一组', '设计二组', '设计三组', '高端定制组', '软装设计组'
- ];
- // 偏好标签选项
- preferenceTagOptions = [
- '柔和色系', '明亮色系', '深色系', '中性色系',
- '环保材料', '实木', '大理石', '瓷砖', '地板', '墙纸',
- '现代简约', '北欧风格', '中式风格', '美式风格', '工业风',
- '智能家电', '收纳空间', '开放式厨房', '大窗户'
- ];
- preferenceTags: string[] = [];
- // 新标签输入
- newTag = '';
- // 角色上下文
- roleContext: 'customer-service' | 'designer' | 'team-leader' = 'customer-service';
- constructor(private fb: FormBuilder) {
- // 初始化需求表单
- this.requirementForm = this.fb.group({
- downPayment: ['', [Validators.required, Validators.min(0)]],
- budget: ['', Validators.required],
- area: ['', [Validators.required, Validators.min(1)]],
- smallImageTime: [''],
- largeImageTime: [''],
- houseType: [''],
- floor: ['', Validators.min(1)],
- preferredDesigner: [''],
- specialRequirements: [''],
- referenceCases: [[]],
- priceDetails: [''],
- // 新增字段
- spaceRequirements: [''],
- designAngles: [''],
- specialAreaHandling: [''],
- materialRequirements: [''],
- lightingRequirements: ['']
- });
- // 初始化客户表单
- this.customerForm = this.fb.group({
- wechat: [''],
- customerType: ['新客户'],
- source: [''],
- remark: [''],
- demandType: [''],
- followUpStatus: ['']
- });
- }
- ngOnInit(): void {
- // 监听表单变化,实时更新阶段状态
- this.customerForm.valueChanges.subscribe(() => {
- this.checkStageCompletion();
- });
-
- this.requirementForm.valueChanges.subscribe(() => {
- this.checkStageCompletion();
- });
-
- // 初始检查阶段状态
- this.checkStageCompletion();
-
- // 如果有同步数据,立即填充表单
- if (this.syncData) {
- this.fillFormWithSyncData(this.syncData);
- }
- }
- ngOnChanges(changes: SimpleChanges): void {
- // 当syncData发生变化时,填充表单数据
- if (changes['syncData'] && changes['syncData'].currentValue) {
- this.fillFormWithSyncData(changes['syncData'].currentValue);
- }
- }
- // 使用同步数据填充表单
- private fillFormWithSyncData(data: any): void {
- if (data.customerInfo) {
- this.customerForm.patchValue(data.customerInfo);
- this.selectedCustomer = data.customerInfo;
- }
-
- if (data.requirementInfo) {
- this.requirementForm.patchValue(data.requirementInfo);
- }
-
- if (data.preferenceTags && Array.isArray(data.preferenceTags)) {
- this.preferenceTags = [...data.preferenceTags];
- }
-
- // 更新阶段完成状态
- this.checkStageCompletion();
- }
- // 搜索客户
- searchCustomer() {
- if (this.searchKeyword.length >= 2) {
- // 模拟搜索结果
- this.searchResults = [
- {
- id: '1',
- name: '张先生',
- phone: '138****5678',
- customerType: '老客户',
- source: '官网咨询',
- avatar: "data:image/svg+xml,%3Csvg width='64' height='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='%23E6E6E6'/%3E%3Ctext x='50%25' y='50%25' font-family='Arial' font-size='13.333333333333334' font-weight='bold' text-anchor='middle' fill='%23555555' dy='0.3em'%3EIMG%3C/text%3E%3C/svg%3E"
- },
- {
- id: '2',
- name: '李女士',
- phone: '139****1234',
- customerType: 'VIP客户',
- source: '推荐介绍',
- avatar: "data:image/svg+xml,%3Csvg width='65' height='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='%23DCDCDC'/%3E%3Ctext x='50%25' y='50%25' font-family='Arial' font-size='13.333333333333334' font-weight='bold' text-anchor='middle' fill='%23555555' dy='0.3em'%3EIMG%3C/text%3E%3C/svg%3E"
- }
- ];
- }
- }
- // 选择客户
- selectCustomer(customer: Customer) {
- this.selectedCustomer = customer;
- // 填充客户表单
- this.customerForm.patchValue({
- name: customer.name,
- phone: customer.phone,
- wechat: customer.wechat || '',
- customerType: customer.customerType || '新客户',
- source: customer.source || '',
- remark: customer.remark || ''
- });
-
- // 清空搜索结果
- this.searchResults = [];
- this.searchKeyword = '';
- }
- // 清除选中的客户
- clearSelectedCustomer() {
- this.selectedCustomer = null;
- this.customerForm.reset({
- customerType: '新客户'
- });
- }
- // 添加偏好标签
- addPreferenceTag(tag: string): void {
- if (tag && !this.preferenceTags.includes(tag)) {
- this.preferenceTags.push(tag);
- this.newTag = ''; // 清空输入框
- }
- }
- // 删除偏好标签
- removePreferenceTag(tag: string): void {
- const index = this.preferenceTags.indexOf(tag);
- if (index >= 0) {
- this.preferenceTags.splice(index, 1);
- }
- }
- // 流程状态管理
- stageCompletionStatus = {
- customerInfo: false,
- projectRequirements: false,
- teamAssignment: false,
- orderConfirmation: false
- };
- // 获取阶段状态文本
- getStageStatusText(stage: keyof typeof this.stageCompletionStatus): string {
- if (this.stageCompletionStatus[stage]) {
- return '已完成';
- } else {
- // 检查是否为未开始状态
- const stages = ['customerInfo', 'projectRequirements', 'teamAssignment', 'orderConfirmation'];
- const currentIndex = stages.indexOf(stage);
-
- // 检查前面的阶段是否都已完成
- let allPreviousCompleted = true;
- for (let i = 0; i < currentIndex; i++) {
- if (!this.stageCompletionStatus[stages[i] as keyof typeof this.stageCompletionStatus]) {
- allPreviousCompleted = false;
- break;
- }
- }
-
- return allPreviousCompleted ? '进行中' : '未进行';
- }
- }
- // 获取阶段状态类名
- getStageStatusClass(stage: keyof typeof this.stageCompletionStatus): string {
- if (this.stageCompletionStatus[stage]) {
- return 'stage-completed';
- } else {
- // 检查是否为未开始状态
- const stages = ['customerInfo', 'projectRequirements', 'teamAssignment', 'orderConfirmation'];
- const currentIndex = stages.indexOf(stage);
-
- // 检查前面的阶段是否都已完成
- let allPreviousCompleted = true;
- for (let i = 0; i < currentIndex; i++) {
- if (!this.stageCompletionStatus[stages[i] as keyof typeof this.stageCompletionStatus]) {
- allPreviousCompleted = false;
- break;
- }
- }
-
- return allPreviousCompleted ? 'stage-in-progress' : 'stage-pending';
- }
- }
- // 获取进度百分比
- getProgressPercentage(): number {
- const completedStages = Object.values(this.stageCompletionStatus).filter(status => status).length;
- return Math.round((completedStages / 4) * 100);
- }
- // 检查阶段完成状态
- private checkStageCompletion(): void {
- // 检查客户信息阶段 - 客户信息表单有效
- this.stageCompletionStatus.customerInfo = this.customerForm.valid;
-
- // 检查项目需求阶段 - 需求表单有效
- this.stageCompletionStatus.projectRequirements = this.requirementForm.valid;
-
- // 检查团队分配阶段 - 已选择设计师
- this.stageCompletionStatus.teamAssignment = !!this.selectedDesigner;
-
- // 检查订单确认阶段 - 所有前面阶段都完成
- this.stageCompletionStatus.orderConfirmation = this.stageCompletionStatus.customerInfo &&
- this.stageCompletionStatus.projectRequirements &&
- this.stageCompletionStatus.teamAssignment;
- }
- // 检查表单是否有效
- isFormValid(): boolean {
- return this.customerForm.valid && this.requirementForm.valid;
- }
- // 检查是否可以创建订单(放宽条件:仅需表单有效即可点击创建,设计师由系统自动分配或人工分配)
- canCreateOrder(): boolean {
- return this.isFormValid();
- }
- // 创建订单方法(支持自动分配空闲设计师)
- createOrder() {
- // 表单未通过校验则不允许创建
- if (!this.isFormValid()) {
- return;
- }
- // 若尚未选择设计师,尝试自动分配空闲设计师
- if (!this.selectedDesigner) {
- const assigned = this.autoAssignDesignerIfAvailable();
- if (!assigned) {
- // 无空闲设计师:阻止创建并弹出分配弹窗
- this.showTeamAssignmentModal = true;
- return;
- }
- }
- this.isSubmitting = true;
-
- // 构建完整的项目数据
- const formData = {
- customerInfo: this.customerForm.value,
- requirementInfo: this.requirementForm.value,
- preferenceTags: this.preferenceTags,
- roleContext: this.roleContext,
- createdAt: new Date()
- };
-
- const projectData = {
- customerInfo: this.customerForm.value,
- requirementInfo: this.requirementForm.value,
- preferenceTags: this.preferenceTags,
- assignedDesigner: this.selectedDesigner,
- createdAt: new Date()
- };
-
- // 先触发订单创建事件(用于数据同步)
- this.orderCreated.emit(formData);
-
- // 再触发项目创建成功事件(用于阶段推进)
- this.projectCreated.emit(projectData);
-
- // 重置表单
- this.customerForm.reset({
- customerType: '新客户'
- });
- this.requirementForm.reset();
- this.preferenceTags = [];
- this.selectedCustomer = null;
- this.selectedDesigner = null;
- this.isSubmitting = false;
- }
- // 提交表单 - 保留原有逻辑但简化
- submitForm() {
- this.createOrder();
- }
- // 关闭团队分配弹窗
- closeTeamAssignmentModal() {
- this.showTeamAssignmentModal = false;
- }
- // 确认团队分配 - 优化流程:同时触发订单创建和项目创建事件
- confirmTeamAssignment(designer: Designer) {
- this.selectedDesigner = designer;
- this.showTeamAssignmentModal = false;
- this.isSubmitting = false; // 重置提交状态
-
- // 更新阶段状态
- this.checkStageCompletion();
-
- // 构建完整的项目数据
- const formData = {
- customerInfo: this.customerForm.value,
- requirementInfo: this.requirementForm.value,
- preferenceTags: this.preferenceTags,
- roleContext: this.roleContext, // 添加角色上下文信息
- createdAt: new Date()
- };
-
- const projectData = {
- customerInfo: this.customerForm.value,
- requirementInfo: this.requirementForm.value,
- preferenceTags: this.preferenceTags,
- assignedDesigner: designer,
- createdAt: new Date()
- };
-
- // 先触发订单创建事件(用于数据同步)
- this.orderCreated.emit(formData);
-
- // 再触发项目创建成功事件(用于阶段推进)
- this.projectCreated.emit(projectData);
-
- // 重置表单
- this.customerForm.reset({
- customerType: '新客户'
- });
- this.requirementForm.reset();
- this.preferenceTags = [];
- this.selectedCustomer = null;
- }
- // 新增:查找空闲设计师(低负载且在项少于等于1)
- private findAvailableDesigners(): Designer[] {
- return this.allDesigners.filter(d => d.workload.level === 'low' && (d.recentTasks?.length || 0) === 0);
- }
- // 新增:自动随机分配空闲设计师
- private autoAssignDesignerIfAvailable(): boolean {
- const candidates = this.findAvailableDesigners();
- if (candidates.length === 0) {
- return false;
- }
- const randomIndex = Math.floor(Math.random() * candidates.length);
- this.selectedDesigner = candidates[randomIndex];
- // 更新阶段状态(选择了设计师)
- this.checkStageCompletion();
- return true;
- }
- }
|