import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { Project, Task, RenderProgress, ModelCheckItem, CustomerFeedback, DesignerChange, Settlement, SkillTag, PerformanceData, MatchingOrder, ProjectStage } from '../models/project.model'; // 材料统计数据接口 interface MaterialStatistics { monthlyAdded: number; totalCostSaved: number; personalDownloads: number; } // 材料项接口 interface MaterialItem { id: string; name: string; type: string; style: string; price: number; thumbnailUrl: string; downloadCount: number; tags: string[]; costSaved: number; isNew: boolean; uploadTime: Date; } // 材料列表响应接口 interface MaterialsResponse { materials: MaterialItem[]; total: number; } // 异常历史记录接口 interface ExceptionHistory { id: string; type: 'failed' | 'stuck' | 'quality' | 'other'; description: string; submitTime: Date; status: '待处理' | '处理中' | '已解决'; response?: string; } @Injectable({ providedIn: 'root' }) export class ProjectService { // 模拟数据 - 实际应用中应从API获取 private projects: Project[] = [ { id: 'proj-001', name: '现代风格客厅设计', customerName: '张三', customerTags: [ { source: '朋友圈', needType: '硬装', preference: '现代', colorAtmosphere: '简约明亮' } ], highPriorityNeeds: ['需家具购买建议'], status: '进行中', currentStage: '需求沟通', stage: '需求沟通', createdAt: new Date('2025-09-01'), deadline: new Date('2025-09-15'), assigneeId: 'designer1', assigneeName: '设计师A', skillsRequired: ['现代风格', '硬装'] }, { id: '2', name: '宋式风格卧室设计', customerName: '李四', customerTags: [ { source: '信息流', needType: '软装', preference: '宋式', colorAtmosphere: '典雅古朴' } ], highPriorityNeeds: [], status: '进行中', currentStage: '渲染', stage: '渲染', createdAt: new Date('2025-09-02'), deadline: new Date('2025-09-20'), assigneeId: 'designer1', assigneeName: '设计师A', skillsRequired: ['宋式风格', '软装'] }, { id: '3', name: '欧式风格厨房设计', customerName: '王五', customerTags: [ { source: '朋友圈', needType: '硬装', preference: '欧式', colorAtmosphere: '豪华温馨' } ], highPriorityNeeds: ['需快速交付'], status: '已完成', currentStage: '投诉处理', stage: '投诉处理', createdAt: new Date('2025-08-20'), deadline: new Date('2025-09-05'), assigneeId: 'designer1', assigneeName: '设计师A', skillsRequired: ['欧式风格', '硬装'] } ]; private tasks: Task[] = [ { id: 't1', projectId: '1', projectName: '现代风格客厅设计', title: '完成客厅建模', stage: '建模', deadline: new Date('2025-09-10'), isOverdue: false, isCompleted: false, priority: 'high', assignee: '设计师A', description: '根据客户需求完成客厅3D模型构建' }, { id: 't2', projectId: '2', projectName: '宋式风格卧室设计', title: '确认渲染结果', stage: '渲染', deadline: new Date('2025-09-12'), isOverdue: false, isCompleted: false, priority: 'medium', assignee: '设计师B', description: '审核渲染效果并与客户确认' }, { id: 't3', projectId: '1', projectName: '现代风格客厅设计', title: '处理客户反馈', stage: '渲染', deadline: new Date('2025-09-08'), isOverdue: true, isCompleted: false, priority: 'high', assignee: '客服', description: '整理客户反馈意见并传达给设计团队' } ]; private renderProgresses: RenderProgress[] = [ { id: 'rp1', projectId: '2', completionRate: 60, estimatedTimeRemaining: 1, status: '进行中', updatedAt: new Date() } ]; private modelCheckItems: ModelCheckItem[] = [ { id: 'm1', name: '尺寸准确性', isPassed: true }, { id: 'm2', name: '比例协调性', isPassed: true }, { id: 'm3', name: '户型匹配度', isPassed: false, notes: '需调整沙发位置' } ]; private feedbacks: CustomerFeedback[] = [ { id: 'f1', projectId: '1', content: '客厅设计不太满意,沙发的颜色和整体风格不太搭配', isSatisfied: false, problemLocation: '沙发区域', expectedEffect: '更宽敞舒适', referenceCase: '提供了参考图片', status: '待处理', createdAt: new Date('2025-09-07'), customerName: '张女士', rating: 2 }, { id: 'f2', projectId: '1', content: '整体设计很满意,特别是厨房的布局很合理,使用起来很方便', isSatisfied: true, problemLocation: '', expectedEffect: '', referenceCase: '', status: '已解决', createdAt: new Date('2025-09-05'), updatedAt: new Date('2025-09-06'), customerName: '张女士', rating: 5, response: '感谢您的认可,我们会继续努力为您提供更好的设计服务。' }, { id: 'f3', projectId: '1', content: '卧室的灯光设计有些暗,希望能增加一些辅助照明', isSatisfied: false, problemLocation: '主卧室', expectedEffect: '更明亮温馨', referenceCase: '希望参考北欧风格的照明设计', status: '处理中', createdAt: new Date('2025-09-06'), customerName: '张女士', rating: 3 }, { id: 'f4', projectId: '2', content: '餐厅的家具选择很棒,质感和颜色都很满意', isSatisfied: true, problemLocation: '', expectedEffect: '', referenceCase: '', status: '已解决', createdAt: new Date('2025-09-04'), updatedAt: new Date('2025-09-05'), customerName: '李先生', rating: 4, response: '谢谢您的好评,我们精心挑选的家具能得到您的认可很开心。' }, { id: 'f5', projectId: '2', content: '阳台的设计需要调整,现在的布局不太实用', isSatisfied: false, problemLocation: '阳台区域', expectedEffect: '更实用的储物和休闲空间', referenceCase: '希望有更多储物柜', status: '待处理', createdAt: new Date('2025-09-08'), customerName: '李先生', rating: 2 }, { id: 'f6', projectId: '3', content: '书房的设计非常棒,工作环境很舒适,书柜的设计也很实用', isSatisfied: true, problemLocation: '', expectedEffect: '', referenceCase: '', status: '已解决', createdAt: new Date('2025-09-03'), updatedAt: new Date('2025-09-04'), customerName: '王女士', rating: 5, response: '很高兴书房设计能满足您的工作需求,实用性一直是我们设计的重点。' }, { id: 'f7', projectId: '3', content: '客厅的材质选择有些问题,地板的纹理和墙面不太协调', isSatisfied: false, problemLocation: '客厅地面', expectedEffect: '更协调的材质搭配', referenceCase: '希望参考现代简约风格', status: '处理中', createdAt: new Date('2025-09-07'), customerName: '王女士', rating: 3 }, { id: 'f8', projectId: '1', content: '儿童房的设计很用心,孩子很喜欢,安全性也考虑得很周到', isSatisfied: true, problemLocation: '', expectedEffect: '', referenceCase: '', status: '已解决', createdAt: new Date('2025-09-02'), updatedAt: new Date('2025-09-03'), customerName: '张女士', rating: 5, response: '孩子的安全和喜好是我们设计儿童房的首要考虑,很开心能得到小朋友的认可。' }, { id: 'f9', projectId: '2', content: '厨房的收纳设计很实用,但是操作台的高度需要调整', isSatisfied: false, problemLocation: '厨房操作台', expectedEffect: '更符合人体工学的高度', referenceCase: '希望按照我的身高定制', status: '待处理', createdAt: new Date('2025-09-09'), customerName: '李先生', rating: 3 }, { id: 'f10', projectId: '3', content: '整体效果超出预期,设计师很专业,沟通也很顺畅', isSatisfied: true, problemLocation: '', expectedEffect: '', referenceCase: '', status: '已解决', createdAt: new Date('2025-09-01'), updatedAt: new Date('2025-09-02'), customerName: '王女士', rating: 5, response: '感谢您对我们团队的认可,专业和沟通是我们一直坚持的服务标准。' } ]; private settlements: Settlement[] = [ // 项目3的结算记录 { id: 's1', projectId: '3', projectName: '欧式风格厨房设计', stage: '建模', amount: 3000, percentage: 30, status: '已结算', createdAt: new Date('2025-08-25'), settledAt: new Date('2025-09-01') }, { id: 's2', projectId: '3', projectName: '欧式风格厨房设计', stage: '渲染', amount: 5000, percentage: 50, status: '已结算', createdAt: new Date('2025-08-28'), settledAt: new Date('2025-09-01') }, { id: 's3', projectId: '3', projectName: '欧式风格厨房设计', stage: '渲染', amount: 2000, percentage: 20, status: '已结算', createdAt: new Date('2025-09-02'), settledAt: new Date('2025-09-05') }, // 项目1的结算记录(当前项目) { id: 's4', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '建模', amount: 4500, percentage: 30, status: '已结算', createdAt: new Date('2025-09-01'), settledAt: new Date('2025-09-03') }, { id: 's5', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '软装', amount: 3500, percentage: 25, status: '已结算', createdAt: new Date('2025-09-05'), settledAt: new Date('2025-09-08') }, { id: 's6', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '渲染', amount: 4000, percentage: 30, status: '待结算', createdAt: new Date('2025-09-10') }, { id: 's7', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '渲染', amount: 2000, percentage: 15, status: '待结算', createdAt: new Date('2025-09-12') }, // 添加一些逾期的结算项 { id: 's8', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '尾款结算', amount: 6000, percentage: 40, status: '待结算', createdAt: new Date('2025-08-15') // 超过30天,算作逾期 }, { id: 's9', projectId: 'proj-001', projectName: '现代风格客厅设计', stage: '方案确认', amount: 1500, percentage: 10, status: '待结算', createdAt: new Date('2025-08-20') // 逾期项目 }, // 项目2的结算记录 { id: 's10', projectId: '2', projectName: '宋式风格卧室设计', stage: '建模', amount: 3200, percentage: 30, status: '已结算', createdAt: new Date('2025-09-03'), settledAt: new Date('2025-09-05') }, { id: 's11', projectId: '2', projectName: '宋式风格卧室设计', stage: '软装', amount: 2800, percentage: 25, status: '待结算', createdAt: new Date('2025-09-08') }, // 客服项目的尾款结算记录 { id: 's12', projectId: '1', // 对应客服项目PRJ-2024-001 projectName: '企业官网设计开发', stage: '尾款结算', amount: 50000, percentage: 100, status: '待结算', createdAt: new Date('2024-01-15'), dueDate: new Date('2024-02-15') }, { id: 's13', projectId: '2', // 对应客服项目PRJ-2024-002 projectName: '移动端APP开发', stage: '尾款结算', amount: 80000, percentage: 100, status: '逾期', createdAt: new Date('2024-01-10'), dueDate: new Date('2024-02-10') }, { id: 's14', projectId: '3', // 对应客服项目PRJ-2024-003 projectName: '电商平台升级', stage: '尾款结算', amount: 120000, percentage: 100, status: '已结算', createdAt: new Date('2024-01-08'), settledAt: new Date('2024-01-22'), dueDate: new Date('2024-02-08') }, // 添加更多不同项目的尾款结算记录 { id: 's15', projectId: '4', projectName: '品牌VI设计', stage: '尾款结算', amount: 35000, percentage: 100, status: '待结算', createdAt: new Date('2024-12-01'), dueDate: new Date('2024-12-31') }, { id: 's16', projectId: '5', projectName: '小程序开发', stage: '尾款结算', amount: 45000, percentage: 100, status: '逾期', createdAt: new Date('2024-11-15'), dueDate: new Date('2024-12-15') }, { id: 's17', projectId: '6', projectName: '网站重构项目', stage: '尾款结算', amount: 28000, percentage: 100, status: '已结算', createdAt: new Date('2024-12-10'), settledAt: new Date('2024-12-20'), dueDate: new Date('2025-01-10') }, { id: 's18', projectId: '7', projectName: '数据可视化系统', stage: '尾款结算', amount: 95000, percentage: 100, status: '待结算', createdAt: new Date('2024-12-20'), dueDate: new Date('2025-01-20') }, { id: 's19', projectId: '8', projectName: '智能家居控制系统', stage: '尾款结算', amount: 68000, percentage: 100, status: '逾期', createdAt: new Date('2024-10-30'), dueDate: new Date('2024-11-30') }, { id: 's20', projectId: '9', projectName: '在线教育平台', stage: '尾款结算', amount: 150000, percentage: 100, status: '已结算', createdAt: new Date('2024-11-25'), settledAt: new Date('2024-12-15'), dueDate: new Date('2024-12-25') } ]; private skillTags: SkillTag[] = [ { id: 'sk1', name: '现代风格', level: 5, count: 10 }, { id: 'sk2', name: '宋式风格', level: 3, count: 5 }, { id: 'sk3', name: '硬装', level: 5, count: 8 }, { id: 'sk4', name: '软装', level: 3, count: 4 } ]; private performanceData: PerformanceData[] = [ { month: '2025-08', projectCompletionRate: 90, customerSatisfaction: 95, deliveryOnTimeRate: 85 }, { month: '2025-09', projectCompletionRate: 85, customerSatisfaction: 90, deliveryOnTimeRate: 90 }, { month: '2025-10', projectCompletionRate: 95, customerSatisfaction: 92, deliveryOnTimeRate: 88 } ]; private matchingOrders: MatchingOrder[] = [ { id: 'mo1', projectName: '新中式风格书房设计', requiredSkills: ['宋式风格', '硬装'], matchRate: 90, customerLevel: '优质' }, { id: 'mo2', projectName: '北欧风格餐厅设计', requiredSkills: ['现代风格', '软装'], matchRate: 80, customerLevel: '普通' } ]; // 获取当前设计师的项目列表 getProjects(): Observable { return of(this.projects); } // 获取项目详情 getProjectById(id: string): Observable { return of(this.projects.find(project => project.id === id)); } // 获取待办任务 getTasks(mockSize?: number): Observable { if (typeof mockSize === 'number' && mockSize > 0) { const now = new Date(this.projects[0]?.deadline || new Date()); const year = now.getFullYear(); const month = now.getMonth(); const pool = ['设计师A','设计师B','设计师C','设计师D','设计师E']; const prios: Array<'high'|'medium'|'low'> = ['high','medium','low']; const gen: Task[] = []; const daysInMonth = new Date(year, month + 1, 0).getDate(); for (let i = 0; i < mockSize; i++) { const day = (i % daysInMonth) + 1; const deadline = new Date(year, month, day); gen.push({ id: `m${i}`, projectId: String((i % this.projects.length) + 1), projectName: this.projects[i % this.projects.length].name, title: `Mock任务${i}`, stage: '建模', deadline, isOverdue: deadline < new Date(), isCompleted: false, priority: prios[i % prios.length], assignee: pool[i % pool.length], description: '性能压测生成' }); } return of(gen); } return of(this.tasks); } // 标记任务完成 markTaskAsCompleted(taskId: string): Observable { const task = this.tasks.find(t => t.id === taskId); if (task) { task.isCompleted = true; task.completedDate = new Date(); } return of(task as Task); } // 获取渲染进度 getRenderProgress(projectId: string): Observable { return of(this.renderProgresses.find(rp => rp.projectId === projectId)); } // 获取模型检查清单 getModelCheckItems(): Observable { return of(this.modelCheckItems); } // 更新模型检查项 updateModelCheckItem(itemId: string, isPassed: boolean): Observable { const item = this.modelCheckItems.find(i => i.id === itemId); if (item) { item.isPassed = isPassed; } return of(item as ModelCheckItem); } // 获取客户反馈 getCustomerFeedbacks(): Observable { return of(this.feedbacks); } // 更新反馈状态 updateFeedbackStatus(feedbackId: string, status: '处理中' | '已解决'): Observable { const feedback = this.feedbacks.find(f => f.id === feedbackId); if (feedback) { feedback.status = status; feedback.updatedAt = new Date(); } return of(feedback as CustomerFeedback); } // 获取结算记录 getSettlements(): Observable { return of(this.settlements); } // 获取技能标签 getSkillTags(): Observable { return of(this.skillTags); } // 获取绩效数据 getPerformanceData(): Observable { return of(this.performanceData); } // 获取匹配订单 getMatchingOrders(): Observable { return of(this.matchingOrders); } // 生成需求确认清单 generateRequirementChecklist(projectId: string): Observable { return of([ '个性化需求已确认', '色彩氛围已确认', '硬装/软装范围已确认', '资料提交截止时间已确认' ]); } // 生成提醒话术 generateReminderMessage(type: 'overdue' | 'stagnation'): Observable { if (type === 'overdue') { return of('当前处于对图期,需1小时内回复,若您需时间梳理需求,可约定XX时间沟通'); } else { return of('接下来将推进新项目,若需修改请提前1天预约'); } } // 更新项目阶段 updateProjectStage(projectId: string, stage: ProjectStage): Observable { const project = this.projects.find(p => p.id === projectId); if (project) { project.currentStage = stage; // 如果是投诉处理阶段,则将项目状态设置为已完成 if (stage === '投诉处理') { project.status = '已完成'; } } return of(project); } // 获取材料统计数据 getMaterialStatistics(): Observable { return of({ monthlyAdded: 15, totalCostSaved: 2800, personalDownloads: 42 }); } // 获取异常历史记录 getExceptionHistories(projectId: string): Observable { return of([ { id: 'eh1', type: 'quality', description: '光线效果不符合预期', submitTime: new Date('2025-09-05'), status: '已解决', response: '已调整灯光参数' }, { id: 'eh2', type: 'stuck', description: '沙发尺寸需要调整', submitTime: new Date('2025-09-07'), status: '待处理' } ]); } // 更新收藏材料状态 updateFavoriteMaterial(materialId: string, isFavorite: boolean): Observable { // 模拟API调用 console.log(`${isFavorite ? '添加' : '取消'}材料收藏:`, materialId); return of(void 0); } // 获取收藏材料列表 getFavoriteMaterials(): Observable { // 模拟返回收藏的材料ID列表 return of(['mat1', 'mat3', 'mat5']); } // 获取材料列表 getMaterials( searchQuery: string = '', filterType: string = '', filterStyle: string = '', filterPrice: string = '', page: number = 1, pageSize: number = 10 ): Observable { // 模拟材料数据 const mockMaterials: MaterialItem[] = [ { id: 'mat1', name: '现代风格沙发', type: '家具', style: '现代', price: 2800, thumbnailUrl: 'https://picsum.photos/200/150', downloadCount: 120, tags: ['现代', '舒适', '客厅', '布艺'], costSaved: 500, isNew: false, uploadTime: new Date('2025-08-15') }, { id: 'mat2', name: '宋式风格茶几', type: '家具', style: '宋式', price: 1500, thumbnailUrl: 'https://picsum.photos/200/151', downloadCount: 85, tags: ['宋式', '古典', '实木', '客厅'], costSaved: 300, isNew: true, uploadTime: new Date('2025-09-07') }, { id: 'mat3', name: '欧式吊灯', type: '灯具', style: '欧式', price: 2200, thumbnailUrl: 'https://picsum.photos/200/152', downloadCount: 150, tags: ['欧式', '奢华', '客厅', '水晶'], costSaved: 450, isNew: false, uploadTime: new Date('2025-08-20') }, { id: 'mat4', name: '中式地毯', type: '纺织品', style: '中式', price: 1800, thumbnailUrl: 'https://picsum.photos/200/153', downloadCount: 95, tags: ['中式', '传统', '卧室', '羊毛'], costSaved: 350, isNew: false, uploadTime: new Date('2025-08-25') }, { id: 'mat5', name: '北欧风格窗帘', type: '纺织品', style: '北欧', price: 1200, thumbnailUrl: 'https://picsum.photos/200/154', downloadCount: 130, tags: ['北欧', '简约', '卧室', '亚麻'], costSaved: 250, isNew: true, uploadTime: new Date('2025-09-05') } ]; // 简单的搜索和过滤逻辑 let filtered = [...mockMaterials]; if (searchQuery) { filtered = filtered.filter(m => m.name.toLowerCase().includes(searchQuery.toLowerCase())); } if (filterType) { filtered = filtered.filter(m => m.type === filterType); } if (filterStyle) { filtered = filtered.filter(m => m.style === filterStyle); } // 分页 const startIndex = (page - 1) * pageSize; const paginated = filtered.slice(startIndex, startIndex + pageSize); return of({ materials: paginated, total: filtered.length }); } // 记录材料下载 recordMaterialDownload(materialId: string): Observable { // 模拟下载记录 console.log('记录材料下载:', materialId); return of(void 0); } // 创建项目 createProject(projectData: { customerId: string; customerName: string; requirement: any; referenceCases: any[]; tags: { demandType?: string; preferenceTags?: string[]; followUpStatus?: string; }; // 可选扩展字段:报价与指派信息 quotation?: any; assignment?: any; orderAmount?: number; }): Observable<{ success: boolean; projectId: string }> { // 模拟API调用 console.log('创建项目:', projectData); // 模拟返回创建的项目ID return of({ success: true, projectId: 'new-project-' + Date.now() }); } // 创建项目群 createProjectGroup(groupData: { customerId: string; customerName: string; tags?: { demandType?: string; preferenceTags?: string[]; followUpStatus?: string; }; }): Observable<{ success: boolean; groupId: string }> { // 模拟API调用 console.log('创建项目群:', groupData); // 模拟返回创建的群组ID return of({ success: true, groupId: 'new-group-' + Date.now() }); } }