# 项目多产品任务逻辑设计 (基于Project表统一管理) ## 1. 多产品场景概述 ### 1.1 业务背景 映三色设计师项目管理系统采用Project表统一管理空间设计产品。每个Project代表一个独立的空间设计产品,支持从单空间到复杂多空间项目的灵活管理。通过Product表的统一架构,实现设计产品化的项目管理模式。 ### 1.2 多产品分布特征 - **单产品设计项目**:占比约70%,主要针对单个空间产品设计(如客厅设计、卧室设计) - **双产品设计项目**:占比约20%,通常是客餐厅一体化、主卧+衣帽间等组合设计 - **多产品设计项目**:占比约10%,全屋设计、别墅等多空间综合项目设计 ### 1.3 现有系统架构 当前系统采用Project表的统一管理架构: - 每个Project代表一个独立的空间设计产品 - Project表通过productId字段关联具体产品 - 支持多Project的统一管理和协调 - 产品化设计流程和标准化交付 ## 2. 基于Project表的数据模型设计 ### 2.1 Project表统一管理 #### 2.1.1 Project 表作为产品设计管理核心 ```typescript interface Project { // 产品基础信息 id: string; name: string; // 产品名称:"李总主卧设计" type: string; // 产品类型:"bedroom", "living_room" 等 status: 'not_started' | 'in_progress' | 'awaiting_review' | 'completed'; priority: number; // 优先级 1-10 complexity: 'simple' | 'medium' | 'complex'; // 空间属性(产品设计维度) area?: number; // 空间面积 metadata?: { dimensions?: { // 空间尺寸 length: number; width: number; height: number; }; features?: string[]; // 空间特征:["朝南", "飘窗", "独立卫浴"] constraints?: string[]; // 约束条件:["承重墙不可动"] style?: string; // 设计风格 specialRequirements?: string[]; // 特殊要求 }; // 产品需求字段 requirements?: { colorRequirement: Object; // 色彩需求 spaceStructureRequirement: Object; // 空间结构需求 materialRequirement: Object; // 材质需求 lightingRequirement: Object; // 灯光需求 specificRequirements?: string[]; // 特定需求 }; // 产品报价字段 quotation?: { price: number; // 产品价格 currency: string; // "CNY" breakdown: { design: number; // 设计费 modeling: number; // 建模费 rendering: number; // 渲染费 softDecor: number; // 软装费 }; status: string; // "pending" | "approved" validUntil: Date; }; // 产品评价字段 reviews?: Array; // 关联信息 projectId: string; // 所属主项目ID designerId?: string; // 负责设计师ID estimatedBudget?: number; // 预估预算 estimatedDuration?: number; // 预估工期 order: number; // 排序顺序 // 时间信息 createdAt: Date; updatedAt: Date; } enum ProductType { LIVING_ROOM = 'living_room', // 客厅 BEDROOM = 'bedroom', // 卧室 KITCHEN = 'kitchen', // 厨房 BATHROOM = 'bathroom', // 卫生间 DINING_ROOM = 'dining_room', // 餐厅 STUDY = 'study', // 书房 BALCONY = 'balcony', // 阳台 CORRIDOR = 'corridor', // 走廊 STORAGE = 'storage', // 储物间 ENTRANCE = 'entrance', // 玄关 OTHER = 'other' // 其他 } ``` #### 2.1.2 产品进度管理 ```typescript interface ProductProgress { productId: string; // 关联产品ID stage: ProjectStage; // 当前阶段 progress: number; // 进度百分比 0-100 status: ProgressStatus; timeline: StageTimeline[]; // 各阶段时间线 blockers?: string[]; // 阻碍因素 estimatedCompletion?: Date; // 预计完成时间 actualCompletion?: Date; // 实际完成时间 } interface StageTimeline { stage: ProjectStage; startTime?: Date; endTime?: Date; duration?: number; // 持续时间(小时) status: 'not_started' | 'in_progress' | 'completed' | 'blocked'; assignee?: string; // 负责人ID deliverables?: string[]; // 交付物 quality?: { score: number; // 质量评分 issues: string[]; // 问题点 }; } enum ProgressStatus { NOT_STARTED = 'not_started', IN_PROGRESS = 'in_progress', AWAITING_REVIEW = 'awaiting_review', COMPLETED = 'completed', BLOCKED = 'blocked', DELAYED = 'delayed' } ``` #### 2.1.3 产品人员分配 ```typescript interface ProductAssignment { productId: string; // 产品ID stage: ProjectStage; // 阶段 assigneeId: string; // 负责人ID assigneeName: string; // 负责人姓名 role: AssignmentRole; // 分配角色 assignedAt: Date; // 分配时间 assignedBy: string; // 分配人ID status: 'active' | 'completed' | 'reassigned'; workload: number; // 工作量占比 0-1 notes?: string; // 分配备注 performance?: { efficiency: number; // 工作效率 quality: number; // 工作质量 collaboration: number; // 协作能力 }; } enum AssignmentRole { PRIMARY_DESIGNER = 'primary_designer', // 主设计师 MODELING_DESIGNER = 'modeling_designer', // 建模师 RENDERING_DESIGNER = 'rendering_designer',// 渲染师 SOFT_DECOR_DESIGNER = 'soft_decor_designer', // 软装师 QUALITY_REVIEWER = 'quality_reviewer' // 质量审核员 } ``` ### 2.2 各阶段数据结构适配 #### 2.2.1 订单分配阶段多产品适配 ```typescript // 扩展 主项目Project 数据结构 interface MultiProductProject { id: string; title: string; status: string; // 产品管理 products: Project[]; // 产品列表 // 全局报价信息 quotation: { totalAmount: number; // 总金额 currency: string; // 货币单位 // 按产品分项报价 productQuotations: ProductQuotation[]; // 按费用类型汇总 breakdown: { design: number; // 设计费 modeling: number; // 建模费 rendering: number; // 渲染费 softDecor: number; // 软装费 postProcess: number; // 后期费 }; // 折扣信息 discount?: { type: 'percentage' | 'fixed'; value: number; reason: string; }; }; // 项目协调信息 coordination: { dependencies: ProductDependency[]; // 产品依赖关系 batchOperations: BatchOperation[]; // 批量操作 qualityStandards: QualityStandard[]; // 质量标准 }; } interface ProductQuotation { productId: string; // 产品ID productName: string; // 产品名称 productType: ProductType; // 产品类型 amount: number; // 该产品金额 items: QuotationItem[]; // 报价项明细 priority: number; // 优先级 estimatedDays: number; // 预估工期 notes?: string; // 备注 } interface ProductDependency { fromProduct: string; // 源产品ID toProduct: string; // 目标产品ID type: 'style_reference' | 'color_flow' | 'material_matching' | 'size_reference' | 'functional_connection'; description: string; // 依赖描述 status: 'pending' | 'satisfied' | 'blocked'; priority: number; // 依赖优先级 } ``` #### 2.2.2 需求确认阶段多产品适配 ```typescript // 扩展 ProjectRequirement 数据结构 interface MultiProductRequirement { products: ProductRequirement[]; // 产品需求列表 globalRequirements: GlobalRequirements; // 全局需求 crossProductRequirements: CrossProductRequirement[]; // 跨产品需求 } interface ProductRequirement { productId: string; // 产品ID productName: string; // 产品名称 productType: ProductType; // 产品类型 // 四大核心需求数据 colorRequirement: ColorAtmosphereRequirement; spaceStructureRequirement: SpaceStructureRequirement; materialRequirement: MaterialRequirement; lightingRequirement: LightingRequirement; // 产品特定需求 specificRequirements: { functional?: string[]; // 功能需求:收纳、展示等 style?: string[]; // 风格偏好 constraints?: string[]; // 限制条件:承重、管道等 specialFeatures?: string[]; // 特殊功能:智能家居、无障碍设计等 }; // 参考资料管理 referenceImages?: string[]; // 参考图片 referenceFiles?: any[]; // 参考文件 priority: number; // 优先级 complexity: 'simple' | 'medium' | 'complex'; // 复杂度 } interface GlobalRequirements { overallStyle: string; // 整体风格 budget: { total: number; currency: string; breakdown?: Record; }; timeline: { preferredStartDate?: Date; deadline: Date; milestones?: Array<{ date: Date; description: string; }>; }; familyComposition: string; // 家庭构成 lifestyle: string[]; // 生活习惯 qualityStandards: string[]; // 质量标准 } interface CrossProductRequirement { type: 'style_consistency' | 'color_flow' | 'material_matching' | 'traffic_flow' | 'functional_connection'; description: string; // 跨产品需求描述 involvedProducts: string[]; // 涉及的产品ID列表 priority: number; // 优先级 impact: 'high' | 'medium' | 'low'; // 影响程度 } ``` #### 2.2.3 交付执行阶段多产品适配 ```typescript // 扩展现有的 deliveryProcesses 数据结构 interface MultiProductDeliveryProcess { processId: string; // 流程ID:modeling、softDecor、rendering、postProcess processName: string; // 流程名称 // 产品管理(增强版) products: DeliveryProduct[]; // 按产品组织的内容 content: Record; // 跨产品协调 crossProductCoordination: { dependencies: ProductDependency[]; // 产品依赖关系 batchOperations: BatchOperation[]; // 批量操作 qualityStandards: QualityStandard[]; // 质量标准 designReviews: DesignReview[]; // 设计评审 }; // 整体进度管理 overallProgress: { total: number; // 总体进度 byProduct: Record; // 各产品进度 byStage: Record; // 各阶段进度 estimatedCompletion: Date; riskIndicators: RiskIndicator[]; // 风险指标 }; } interface DeliveryProduct { productId: string; // 产品ID productName: string; // 产品名称 productType: ProductType; // 产品类型 priority: number; // 优先级 status: string; // 状态 // 交付内容 deliverables: { concepts: ConceptDesign[]; // 概念设计 models: ThreeDModel[]; // 三维模型 renderings: Rendering[]; // 渲染图 documents: TechnicalDocument[]; // 技术文档 }; // 质量控制 quality: { designReview: DesignReviewResult; // 设计评审结果 technicalValidation: ValidationResult; // 技术验证结果 clientFeedback: FeedbackRecord[]; // 客户反馈 }; } interface DesignReview { id: string; type: 'internal' | 'client' | 'technical'; participants: string[]; // 参与者ID scheduledDate: Date; // 计划日期 duration: number; // 评审时长(分钟) status: 'scheduled' | 'in_progress' | 'completed' | 'cancelled'; // 评审内容 criteria: ReviewCriteria[]; // 评审标准 findings: ReviewFinding[]; // 评审发现 decisions: ReviewDecision[]; // 评审决策 actionItems: ActionItem[]; // 行动项 // 评审结果 overallScore: number; // 整体评分 approved: boolean; // 是否通过 nextReviewDate?: Date; // 下次评审日期 } interface BatchOperation { id: string; type: 'style_sync' | 'color_adjustment' | 'material_update' | 'quality_standard_apply'; targetProducts: string[]; // 目标产品列表 operation: any; // 具体操作内容 status: 'pending' | 'in_progress' | 'completed' | 'failed'; createdBy: string; createdAt: Date; completedAt?: Date; results?: OperationResult[]; // 操作结果 } ``` #### 2.2.4 售后归档阶段多产品适配 ```typescript // 扩展售后数据结构 interface MultiProductAfterCare { productReviews: ProductReview[]; // 各产品评价 crossProductAnalysis: CrossProductAnalysis; // 跨产品分析 productComparison: ProductComparison[]; // 产品对比 projectSummary: ProjectSummary; // 项目总结 } interface ProductReview { productId: string; // 产品ID productName: string; // 产品名称 productType: ProductType; // 产品类型 // 客户评价 customerRating: { overall: number; // 整体评分 1-5 aspects: { design: number; // 设计评分 functionality: number; // 功能性评分 aesthetics: number; // 美观度评分 practicality: number; // 实用性评分 value: number; // 性价比评分 }; feedback: string; // 具体反馈 suggestions: string[]; // 改进建议 }; // 使用情况跟踪 usageMetrics: { satisfaction: number; // 满意度 0-100 usageFrequency: string; // 使用频率 adaptations: string[]; // 后续改动 issues: string[]; // 问题记录 maintenance: MaintenanceRecord[]; // 维护记录 }; // 经济价值分析 economicValue: { costPerProduct: number; // 单产品成本 perceivedValue: number; // 感知价值 roi: number; // 投资回报率 marketComparison: MarketComparison; // 市场对比 }; // 专业评价 professionalReview: { technicalQuality: number; // 技术质量 innovation: number; // 创新性 sustainability: number; // 可持续性 scalability: number; // 可扩展性 }; } interface CrossProductAnalysis { styleConsistency: { score: number; // 风格一致性评分 0-100 issues: string[]; // 不一致问题 improvements: string[]; // 改进建议 }; functionalFlow: { score: number; // 功能流线评分 bottlenecks: string[]; // 瓶颈问题 optimizations: string[]; // 优化建议 }; spaceUtilization: { efficiency: number; // 空间利用率 recommendations: string[]; // 优化建议 }; designCohesion: { overallScore: number; // 设计凝聚力评分 thematicUnity: number; // 主题统一性 transitionQuality: number; // 过渡质量 }; } interface ProjectSummary { overallSuccess: { score: number; // 项目成功度评分 achievements: string[]; // 主要成就 challenges: string[]; // 面临挑战 lessons: string[]; // 经验教训 }; businessMetrics: { totalRevenue: number; // 总收入 totalCost: number; // 总成本 profitMargin: number; // 利润率 clientSatisfaction: number; // 客户满意度 referralPotential: number; // 推荐潜力 }; teamPerformance: { collaborationScore: number; // 协作评分 efficiencyScore: number; // 效率评分 qualityScore: number; // 质量评分 innovationScore: number; // 创新评分 }; futureOpportunities: { followUpProjects: string[]; // 后续项目机会 serviceExtensions: string[]; // 服务扩展机会 portfolioAdditions: string[]; // 作品集补充 }; } ``` ## 3. 多产品业务流程设计 ### 3.1 产品识别与创建流程 #### 3.1.1 产品识别时机 ```mermaid graph TD A[客服接收需求] --> B{是否多产品项目?} B -->|否| C[创建单产品项目] B -->|是| D[分析产品需求] D --> E[识别潜在产品] E --> F[创建产品列表] F --> G[设置产品优先级] G --> H[分配产品ID] H --> I[进入订单分配阶段] style C fill:#e8f5e9 style I fill:#e3f2fd ``` #### 3.1.2 产品识别规则 ```typescript class ProductIdentifier { // 基于关键词识别产品 identifyProductsFromDescription(description: string): ProductIdentificationResult { const result: ProductIdentificationResult = { identifiedProducts: [], confidence: 0, reasoning: '', suggestedQuestions: [], recommendedProductTypes: [] }; // 产品类型关键词映射 const productKeywords = { [ProductType.LIVING_ROOM]: ['客厅', '起居室', '会客厅', '茶室', '待客区'], [ProductType.BEDROOM]: ['卧室', '主卧', '次卧', '儿童房', '老人房', '客房', '主人房'], [ProductType.KITCHEN]: ['厨房', '开放式厨房', '中西厨', '餐厨一体'], [ProductType.BATHROOM]: ['卫生间', '浴室', '洗手间', '盥洗室', '主卫', '次卫'], [ProductType.DINING_ROOM]: ['餐厅', '餐厅区', '用餐区', '就餐空间'], [ProductType.STUDY]: ['书房', '工作室', '办公室', '学习区', '阅读区'], [ProductType.BALCONY]: ['阳台', '露台', '花园阳台', '休闲阳台'], [ProductType.CORRIDOR]: ['走廊', '过道', '玄关', '门厅', '入户'], [ProductType.STORAGE]: ['储物间', '衣帽间', '杂物间', '收纳空间'] }; // 分析描述中的产品关键词 const foundProducts: Array<{ type: ProductType; keywords: string[]; confidence: number }> = []; for (const [productType, keywords] of Object.entries(productKeywords)) { const matchedKeywords = keywords.filter(keyword => description.toLowerCase().includes(keyword.toLowerCase()) ); if (matchedKeywords.length > 0) { foundProducts.push({ type: productType as ProductType, keywords: matchedKeywords, confidence: matchedKeywords.length / keywords.length }); } } // 按置信度排序 foundProducts.sort((a, b) => b.confidence - a.confidence); // 构建识别结果 result.identifiedProducts = foundProducts.map(fp => ({ type: fp.type, productName: this.getDefaultProductName(fp.type), priority: this.calculateProductPriority(fp.type, fp.confidence), confidence: fp.confidence, identifiedKeywords: fp.keywords, estimatedArea: this.estimateProductArea(fp.type), suggestedComplexity: this.suggestProductComplexity(fp.type, description) })); // 计算整体置信度 result.confidence = foundProducts.length > 0 ? foundProducts.reduce((sum, fp) => sum + fp.confidence, 0) / foundProducts.length : 0; // 生成推理说明 result.reasoning = this.generateIdentificationReasoning(foundProducts); // 生成建议问题 result.suggestedQuestions = this.generateClarifyingQuestions(foundProducts); // 推荐相关产品类型 result.recommendedProductTypes = this.recommendRelatedProductTypes(foundProducts); return result; } // 基于面积和预算推断产品数量 estimateProductCount(totalArea: number, budget: number): ProductEstimationResult { const result: ProductEstimationResult = { estimatedProductCount: 1, confidence: 0.5, reasoning: '', possibleProductTypes: [], recommendedAllocation: {} }; // 基于面积的产品数量估算 const areaBasedCount = Math.max(1, Math.floor(totalArea / 20)); // 每20平米一个主要产品 // 基于预算的产品数量估算 const budgetBasedCount = Math.max(1, Math.floor(budget / 30000)); // 每3万一个产品 // 综合判断 const finalCount = Math.min(areaBasedCount, budgetBasedCount); result.estimatedProductCount = finalCount; // 推断可能的产品类型 result.possibleProductTypes = this.inferPossibleProductTypes(totalArea, budget); // 推荐预算分配 result.recommendedAllocation = this.calculateBudgetAllocation( result.possibleProductTypes, budget ); // 生成推理 result.reasoning = `基于面积${totalArea}平米和预算${budget}元,估算需要${finalCount}个主要产品设计产品`; return result; } } ``` ### 3.2 多产品报价策略 #### 3.2.1 报价计算逻辑 ```typescript class MultiProductPricingCalculator { calculateProductPricing( products: Project[], globalRequirements: GlobalRequirements, pricingRules: PricingRule[] ): MultiProductQuotation { const productQuotations: ProductQuotation[] = []; let totalAmount = 0; for (const product of products) { const productQuotation = this.calculateSingleProductPricing(product, globalRequirements, pricingRules); productQuotations.push(productQuotation); totalAmount += productQuotation.amount; } // 应用多产品折扣 const discount = this.calculateMultiProductDiscount(products.length, totalAmount); const finalAmount = totalAmount - discount.value; return { projectId: this.getProjectId(), quotationDate: new Date(), currency: 'CNY', productQuotations, totalBaseAmount: totalAmount, discountAmount: discount.value, finalAmount, breakdown: this.calculateBreakdown(productQuotations), discount: discount.value > 0 ? discount : undefined }; } private calculateSingleProductPricing( product: Project, globalRequirements: GlobalRequirements, pricingRules: PricingRule[] ): ProductQuotation { const basePrice = this.getBasePriceForProductType(product.type, product.area || 0); const complexityMultiplier = this.getComplexityMultiplier(product.complexity); const priorityAdjustment = this.getPriorityAdjustment(product.priority); const styleFactor = this.getStyleFactor(globalRequirements.overallStyle); const items: QuotationItem[] = [ { id: `${product.id}_design`, category: 'design', description: '概念设计费', quantity: 1, unitPrice: basePrice * 0.25 * complexityMultiplier * styleFactor, totalPrice: basePrice * 0.25 * complexityMultiplier * styleFactor }, { id: `${product.id}_modeling`, category: 'modeling', description: '三维建模费', quantity: 1, unitPrice: basePrice * 0.30 * complexityMultiplier, totalPrice: basePrice * 0.30 * complexityMultiplier }, { id: `${product.id}_rendering`, category: 'rendering', description: '效果图渲染费', quantity: 1, unitPrice: basePrice * 0.25 * complexityMultiplier, totalPrice: basePrice * 0.25 * complexityMultiplier }, { id: `${product.id}_soft_decor`, category: 'soft_decor', description: '软装设计费', quantity: 1, unitPrice: basePrice * 0.15 * complexityMultiplier, totalPrice: basePrice * 0.15 * complexityMultiplier }, { id: `${product.id}_technical`, category: 'technical', description: '技术文档费', quantity: 1, unitPrice: basePrice * 0.05 * complexityMultiplier, totalPrice: basePrice * 0.05 * complexityMultiplier } ]; const totalAmount = items.reduce((sum, item) => sum + item.totalPrice, 0); return { productId: product.id, productName: product.name, productType: product.type as ProductType, amount: totalAmount * priorityAdjustment, items, priority: product.priority, estimatedDays: this.calculateEstimatedDays(product, totalAmount), notes: `复杂度系数: ${complexityMultiplier}, 优先级调整: ${priorityAdjustment}, 风格系数: ${styleFactor}` }; } private calculateMultiProductDiscount(productCount: number, totalAmount: number): { type: string; value: number; reason: string } { if (productCount >= 5) { return { type: 'percentage', value: totalAmount * 0.12, // 12% 折扣 reason: '5产品以上项目享受12%折扣' }; } else if (productCount >= 3) { return { type: 'percentage', value: totalAmount * 0.08, // 8% 折扣 reason: '3-4产品项目享受8%折扣' }; } else if (productCount >= 2) { return { type: 'percentage', value: totalAmount * 0.05, // 5% 折扣 reason: '双产品项目享受5%折扣' }; } else if (totalAmount > 200000) { return { type: 'fixed', value: 5000, reason: '高额度项目固定优惠5000元' }; } return { type: 'percentage', value: 0, reason: '无折扣' }; } } ``` ### 3.3 多产品需求采集流程 #### 3.3.1 需求采集策略 ```typescript class MultiProductRequirementCollector { async collectRequirements( products: Project[], globalRequirements: GlobalRequirements ): Promise { const productRequirements: ProductRequirement[] = []; // 1. 并行采集各产品需求 const requirementPromises = products.map(product => this.collectProductRequirements(product, globalRequirements) ); const collectedRequirements = await Promise.all(requirementPromises); productRequirements.push(...collectedRequirements); // 2. 分析跨产品需求 const crossProductRequirements = await this.analyzeCrossProductRequirements(productRequirements); // 3. 验证需求一致性 await this.validateRequirementConsistency(productRequirements, crossProductRequirements); return { products: productRequirements, globalRequirements, crossProductRequirements }; } private async collectProductRequirements( product: Project, globalRequirements: GlobalRequirements ): Promise { // 基于产品类型预填充需求模板 const template = this.getProductRequirementTemplate(product.type); // 采集四大核心需求 const colorRequirement = await this.collectColorRequirement(product, template.colorTemplate); const spaceStructureRequirement = await this.collectSpaceStructureRequirement(product, template.structureTemplate); const materialRequirement = await this.collectMaterialRequirement(product, template.materialTemplate); const lightingRequirement = await this.collectLightingRequirement(product, template.lightingTemplate); // 采集产品特定需求 const specificRequirements = await this.collectSpecificRequirements(product, template.specificTemplate); // 管理参考资料 const referenceImages = await this.collectReferenceImages(product); const referenceFiles = await this.collectReferenceFiles(product); return { productId: product.id, productName: product.name, productType: product.type as ProductType, colorRequirement, spaceStructureRequirement, materialRequirement, lightingRequirement, specificRequirements, referenceImages, referenceFiles, priority: product.priority, complexity: this.assessProductComplexity(product, specificRequirements) }; } private async analyzeCrossProductRequirements( productRequirements: ProductRequirement[] ): Promise { const crossProductRequirements: CrossProductRequirement[] = []; // 分析风格一致性需求 const styleRequirement = this.analyzeStyleConsistency(productRequirements); if (styleRequirement) crossProductRequirements.push(styleRequirement); // 分析色彩流线需求 const colorFlowRequirement = this.analyzeColorFlow(productRequirements); if (colorFlowRequirement) crossProductRequirements.push(colorFlowRequirement); // 分析材质匹配需求 const materialMatchingRequirement = this.analyzeMaterialMatching(productRequirements); if (materialMatchingRequirement) crossProductRequirements.push(materialMatchingRequirement); // 分析功能连接需求 const functionalConnectionRequirement = this.analyzeFunctionalConnections(productRequirements); if (functionalConnectionRequirement) crossProductRequirements.push(functionalConnectionRequirement); return crossProductRequirements; } } ``` ### 3.4 多产品交付协调机制 #### 3.4.1 产品依赖管理 ```typescript class ProductDependencyManager { analyzeProductDependencies(products: Project[]): ProductDependency[] { const dependencies: ProductDependency[] = []; // 分析风格参考依赖 const styleDependencies = this.analyzeStyleDependencies(products); dependencies.push(...styleDependencies); // 分析色彩流线依赖 const colorDependencies = this.analyzeColorDependencies(products); dependencies.push(...colorDependencies); // 分析尺寸参考依赖 const sizeDependencies = this.analyzeSizeDependencies(products); dependencies.push(...sizeDependencies); // 分析功能连接依赖 const functionalDependencies = this.analyzeFunctionalDependencies(products); dependencies.push(...functionalDependencies); return dependencies; } private analyzeStyleDependencies(products: Project[]): ProductDependency[] { const dependencies: ProductDependency[] = []; const livingRoom = products.find(p => p.type === ProductType.LIVING_ROOM); if (livingRoom) { // 客厅通常是风格参考基准 const otherProducts = products.filter(p => p.id !== livingRoom.id); for (const product of otherProducts) { dependencies.push({ fromProduct: livingRoom.id, toProduct: product.id, type: 'style_reference', description: `${product.name}需要与客厅风格保持一致`, status: 'pending', priority: this.calculateDependencyPriority(livingRoom, product) }); } } return dependencies; } async resolveDependency(dependency: ProductDependency): Promise { switch (dependency.type) { case 'style_reference': return await this.resolveStyleDependency(dependency); case 'color_flow': return await this.resolveColorDependency(dependency); case 'material_matching': return await this.resolveMaterialDependency(dependency); case 'size_reference': return await this.resolveSizeDependency(dependency); case 'functional_connection': return await this.resolveFunctionalDependency(dependency); default: return false; } } private async resolveStyleDependency(dependency: ProductDependency): Promise { // 实现风格依赖解决逻辑 // 1. 获取源产品的设计方案 // 2. 提取关键风格元素 // 3. 应用到目标产品 // 4. 验证一致性 console.log(`解决风格依赖: ${dependency.fromProduct} -> ${dependency.toProduct}`); dependency.status = 'satisfied'; return true; } } ``` #### 3.4.2 批量操作支持 ```typescript class ProductBatchOperationManager { async executeBatchOperation(operation: BatchOperation): Promise { try { operation.status = 'in_progress'; switch (operation.type) { case 'style_sync': return await this.executeStyleSync(operation); case 'color_adjustment': return await this.executeColorAdjustment(operation); case 'material_update': return await this.executeMaterialUpdate(operation); case 'quality_standard_apply': return await this.executeQualityStandardApply(operation); default: throw new Error(`未知的批量操作类型: ${operation.type}`); } } catch (error) { console.error(`批量操作失败:`, error); operation.status = 'failed'; return false; } } private async executeStyleSync(operation: BatchOperation): Promise { const { targetProducts, operation: syncData } = operation; // 获取风格同步数据 const sourceStyle = syncData.sourceStyle; const styleElements = syncData.elements; const results: OperationResult[] = []; // 批量应用到目标产品 for (const productId of targetProducts) { try { await this.applyStyleToProduct(productId, sourceStyle, styleElements); results.push({ productId, success: true, message: '风格同步成功' }); } catch (error) { results.push({ productId, success: false, message: `风格同步失败: ${error.message}` }); } } operation.results = results; operation.status = 'completed'; operation.completedAt = new Date(); return results.every(r => r.success); } private async executeQualityStandardApply(operation: BatchOperation): Promise { const { targetProducts, operation: standardData } = operation; // 获取质量标准数据 const qualityStandard = standardData.qualityStandard; const applicableProductTypes = standardData.applicableProductTypes; const results: OperationResult[] = []; // 批量应用质量标准 for (const productId of targetProducts) { try { // 验证产品类型是否适用 const product = await this.getProductById(productId); if (applicableProductTypes.includes(product.type)) { await this.applyQualityStandard(productId, qualityStandard); results.push({ productId, success: true, message: '质量标准应用成功' }); } else { results.push({ productId, success: false, message: '产品类型不适用该质量标准' }); } } catch (error) { results.push({ productId, success: false, message: `质量标准应用失败: ${error.message}` }); } } operation.results = results; operation.status = 'completed'; operation.completedAt = new Date(); return results.every(r => r.success); } } ``` ## 4. 界面交互设计 ### 4.1 产品概览界面 #### 4.1.1 产品卡片布局 ```html

{{ projectTitle }}

{{ products.length }}个产品 总预算: ¥{{ totalBudget.toLocaleString() }} {{ isMultiProductProject ? '多产品项目' : '单产品项目' }}
{{ overallProgress }}% 总体进度
@for (product of products; track product.id) {

{{ product.name }}

{{ getProductTypeName(product.type) }} @if (product.area) { {{ product.area }}m² }
{{ getProductProgress(product.id) }}%
当前阶段: {{ getCurrentStage(product.id) }}
@if (getProductAssignee(product.id)) {
{{ getProductAssignee(product.id).name }} } @else { 未分配 }
@if (product.priority >= 8) { 高优先级 } @if (product.complexity === 'complex') { 复杂 } @if (hasCrossProductDependencies(product.id)) { 依赖 } @if (product.estimatedBudget) { ¥{{ product.estimatedBudget.toLocaleString() }} }
}
添加产品
@if (isMultiProductProject) {

产品协调管理

依赖关系

@for (dependency of productDependencies; track dependency.id) {
{{ getProductName(dependency.fromProduct) }} {{ getProductName(dependency.toProduct) }} {{ getDependencyTypeName(dependency.type) }}
@if (dependency.status === 'pending') { }
}

批量操作

}
``` #### 4.1.2 产品详情弹窗 ```html
``` ### 4.2 多产品文件管理界面 #### 4.2.1 产品文件浏览器 ```html
@for (product of products; track product.id) { }
@if (selectedProducts.length > 0) {
已选择 {{ selectedProducts.length }} 个产品
}
@if (selectedProductId) {

{{ getProduct(selectedProductId).name }}

{{ getProductFileCount(selectedProductId) }} 个文件 {{ getProductTypeName(getProduct(selectedProductId).type) }}

拖拽文件到此处上传

或点击上传按钮选择文件

支持格式: JPG, PNG, PDF, DWG, SKP, 3DM, PSD
@if (viewMode === 'grid') {
@for (file of getFilteredProductFiles(selectedProductId); track file.id) {
@if (isImageFile(file)) { } @else {
} @if (file.category) {
{{ getCategoryName(file.category) }}
}
{{ file.name }} {{ formatFileSize(file.size) }} {{ formatDate(file.uploadTime) }} @if (file.version) { v{{ file.version }} }
}
} @if (viewMode === 'list') {
文件名
类别
大小
类型
上传时间
版本
操作
@for (file of getFilteredProductFiles(selectedProductId); track file.id) {
{{ file.name }}
@if (file.category) { {{ getCategoryName(file.category) }} }
{{ formatFileSize(file.size) }}
{{ getFileTypeLabel(file.type) }}
{{ formatDate(file.uploadTime) }}
@if (file.version) { v{{ file.version }} }
}
}
} @else {

请选择一个产品查看文件

}
``` ## 5. 数据库迁移方案 ### 5.1 数据结构变更 #### 5.1.1 Project 表迁移 ```sql -- 为主项目Project表添加多产品支持字段 ALTER TABLE Project ADD COLUMN projectType VARCHAR(20) DEFAULT 'single'; ALTER TABLE Project ADD COLUMN productIds JSON; ALTER TABLE Project ADD COLUMN productProgress JSON; ALTER TABLE Project ADD COLUMN productAssignment JSON; ALTER TABLE Project ADD COLUMN productDependencies JSON; ALTER TABLE Project ADD COLUMN coordinationInfo JSON; -- 创建产品索引 CREATE INDEX idx_project_projectType ON Project(projectType); CREATE INDEX idx_project_productIds ON Project USING GIN(productIds); ``` #### 5.1.2 新增产品相关表 ```sql -- 创建产品设计表(基于现有Product表) -- Product表已存在,添加新的字段支持 ALTER TABLE Product ADD COLUMN area DECIMAL(8,2); ALTER TABLE Product ADD COLUMN priority INTEGER DEFAULT 5; ALTER TABLE Product ADD COLUMN complexity VARCHAR(20) DEFAULT 'medium'; ALTER TABLE Product ADD COLUMN orderNumber INTEGER DEFAULT 0; ALTER TABLE Product ADD COLUMN estimatedBudget DECIMAL(12,2); ALTER TABLE Product ADD COLUMN estimatedDuration INTEGER; -- 创建产品进度表 CREATE TABLE ProductProgress ( id VARCHAR(50) PRIMARY KEY, productId VARCHAR(50) NOT NULL, stage VARCHAR(50) NOT NULL, progress INTEGER DEFAULT 0, status VARCHAR(20) DEFAULT 'not_started', timeline JSON, blockers JSON, estimatedCompletion DATETIME, actualCompletion DATETIME, createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (productId) REFERENCES Product(objectId) ); -- 创建产品分配表 CREATE TABLE ProductAssignment ( id VARCHAR(50) PRIMARY KEY, productId VARCHAR(50) NOT NULL, stage VARCHAR(50) NOT NULL, assigneeId VARCHAR(50) NOT NULL, assigneeName VARCHAR(100) NOT NULL, role VARCHAR(50) NOT NULL, assignedAt DATETIME DEFAULT CURRENT_TIMESTAMP, assignedBy VARCHAR(50), status VARCHAR(20) DEFAULT 'active', workload DECIMAL(3,2) DEFAULT 0.0, notes TEXT, FOREIGN KEY (productId) REFERENCES Product(objectId) ); -- 创建产品依赖表 CREATE TABLE ProductDependency ( id VARCHAR(50) PRIMARY KEY, fromProductId VARCHAR(50) NOT NULL, toProductId VARCHAR(50) NOT NULL, type VARCHAR(50) NOT NULL, description TEXT, status VARCHAR(20) DEFAULT 'pending', priority INTEGER DEFAULT 5, createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (fromProductId) REFERENCES Product(objectId), FOREIGN KEY (toProductId) REFERENCES Product(objectId) ); ``` ### 5.2 数据迁移脚本 #### 5.2.1 现有项目数据迁移 ```typescript class ProductMigrationService { async migrateExistingProjects(): Promise { console.log('开始迁移现有项目数据到产品管理模式...'); // 1. 获取所有现有项目 const projects = await this.getAllProjects(); for (const project of projects) { await this.migrateProjectToProducts(project); } console.log('项目数据迁移完成'); } private async migrateProjectToProducts(project: any): Promise { // 2. 分析项目是否为多产品 const isMultiProduct = await this.analyzeProjectProductType(project); if (isMultiProduct) { // 3. 创建产品记录 const products = await this.createProductsForProject(project); // 4. 更新项目记录 await this.updateProjectWithProducts(project.objectId, products); // 5. 迁移交付数据到产品维度 await this.migrateDeliveryDataToProducts(project, products); // 6. 迁移需求数据到产品维度 await this.migrateRequirementDataToProducts(project, products); } else { // 单产品项目,创建默认产品 const defaultProduct = await this.createDefaultProduct(project); await this.updateProjectWithProducts(project.objectId, [defaultProduct]); } } private async analyzeProjectProductType(project: any): Promise { // 基于项目标题、描述、文件等信息判断是否为多产品 const indicators = [ project.title?.includes('全屋') || project.title?.includes('整套'), project.data?.description?.includes('多空间'), (project.data?.quotation?.items?.length || 0) > 3, await this.hasMultipleRoomTypes(project) ]; return indicators.some(indicator => indicator === true); } private async createProductsForProject(project: any): Promise { const products: Project[] = []; // 基于报价项创建产品 if (project.data?.quotation?.items) { for (const item of project.data.quotation.items) { const productType = this.inferProductTypeFromDescription(item.description); if (productType) { const product: Project = { id: `product_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, name: item.room || this.getDefaultProductName(productType), type: productType, status: 'not_started', priority: this.calculateProductPriority(item.amount), complexity: 'medium', area: this.estimateProductArea(productType, item.amount), estimatedBudget: item.amount, estimatedDuration: this.estimateProductDuration(productType, item.amount), order: products.length + 1, projectId: project.objectId, createdAt: new Date(), updatedAt: new Date() }; products.push(product); } } } // 如果没有从报价识别出产品,创建默认产品 if (products.length === 0) { const defaultProduct = await this.createDefaultProduct(project); products.push(defaultProduct); } return products; } private async createDefaultProduct(project: any): Promise { return { id: `product_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, name: project.title || '主空间设计', type: 'living_room', status: 'not_started', priority: 5, complexity: 'medium', estimatedBudget: project.data?.quotation?.totalAmount || 0, estimatedDuration: 30, order: 1, projectId: project.objectId, createdAt: new Date(), updatedAt: new Date() }; } private async migrateDeliveryDataToProducts(project: any, products: Project[]): Promise { // 迁移交付执行数据到对应产品 if (project.data?.deliveryProcesses) { for (const process of project.data.deliveryProcesses) { for (const product of products) { // 将交付数据关联到对应产品 await this.createProductDeliveryData(product.id, process); } } } } private async migrateRequirementDataToProducts(project: any, products: Project[]): Promise { // 迁移需求数据到对应产品 if (project.data?.requirements) { for (const product of products) { await this.createProductRequirementData(product.id, project.data.requirements); } } } } ``` ### 5.3 向后兼容性保证 #### 5.3.1 数据访问层适配 ```typescript class ProjectDataAdapter { // 适配旧的单产品项目数据格式 adaptLegacyProject(legacyProject: any): any { const adaptedProject: any = { ...legacyProject, projectType: 'single', products: this.createDefaultProductsFromLegacy(legacyProject), productProgress: this.createDefaultProgressFromLegacy(legacyProject), productAssignment: this.createDefaultAssignmentFromLegacy(legacyProject) }; return adaptedProject; } private createDefaultProductsFromLegacy(legacyProject: any): Project[] { return [{ id: `default_product_${legacyProject.objectId}`, name: legacyProject.title || '主空间设计', type: this.inferProductTypeFromLegacy(legacyProject), status: this.legacyStatusToProductStatus(legacyProject.status), priority: 5, complexity: 'medium', estimatedBudget: legacyProject.data?.quotation?.totalAmount || 0, estimatedDuration: 30, order: 1, projectId: legacyProject.objectId, createdAt: legacyProject.createdAt, updatedAt: legacyProject.updatedAt, requirements: legacyProject.data?.requirements, quotation: legacyProject.data?.quotation, reviews: legacyProject.data?.reviews }]; } // 适配新的多产品数据格式到旧格式(用于兼容性接口) adaptToLegacyFormat(multiProductProject: any): any { if (multiProductProject.projectType === 'single') { return { ...multiProductProject, // 将单产品数据扁平化到原有格式 data: { ...multiProductProject.data, deliveryProcesses: this.extractDeliveryProcessesFromProducts(multiProductProject), requirements: this.extractRequirementsFromProducts(multiProductProject), quotation: this.extractQuotationFromProducts(multiProductProject) } }; } // 多产品项目返回增强格式的数据 return multiProductProject; } } ``` ## 6. 实施建议 ### 6.1 分阶段实施计划 #### 6.1.1 第一阶段:基础架构(2周) - [ ] 数据库结构设计和迁移 - [ ] 核心Product表模型重构 - [ ] 产品管理基础服务(ProductSpaceService) - [ ] 向后兼容性保证 - [ ] 数据迁移脚本开发 #### 6.1.2 第二阶段:界面适配(3周) - [ ] 产品概览界面开发 - [ ] 产品详情弹窗实现 - [ ] 多产品文件管理界面 - [ ] 产品协调管理界面 - [ ] 响应式布局适配 #### 6.1.3 第三阶段:业务逻辑(3周) - [ ] 多产品报价计算系统 - [ ] 产品依赖关系管理 - [ ] 批量操作支持 - [ ] 跨产品协调机制 - [ ] 产品进度跟踪系统 #### 6.1.4 第四阶段:测试优化(2周) - [ ] 单元测试和集成测试 - [ ] 性能优化 - [ ] 用户体验优化 - [ ] 文档完善 - [ ] 数据迁移验证 ### 6.2 风险控制 #### 6.2.1 数据一致性风险 - **风险**:数据迁移过程中可能出现数据丢失或不一致 - **应对**:完整的数据备份、分步迁移、数据校验机制、回滚方案 #### 6.2.2 性能风险 - **风险**:多产品查询可能影响系统性能 - **应对**:合理的数据库索引、查询优化、缓存策略、分页加载 #### 6.2.3 用户体验风险 - **风险**:界面复杂度增加可能影响用户体验 - **应对**:渐进式界面更新、用户培训、智能默认配置、简化操作流程 #### 6.2.4 业务连续性风险 - **风险**:系统升级可能影响现有业务 - **应对**:平滑迁移、双系统并行、灰度发布、快速回滚机制 ### 6.3 成功指标 #### 6.3.1 功能指标 - [ ] 支持单产品到10+产品的项目管理 - [ ] 产品间依赖关系自动识别率 > 80% - [ ] 批量操作成功率 > 95% - [ ] 数据迁移零丢失 - [ ] 向后兼容性100%保证 #### 6.3.2 性能指标 - [ ] 产品切换响应时间 < 200ms - [ ] 多产品项目加载时间 < 1s - [ ] 并发用户支持数 > 100 - [ ] 文件上传成功率 > 99% #### 6.3.3 用户体验指标 - [ ] 用户满意度 > 4.5/5 - [ ] 操作流程简化度提升 > 30% - [ ] 错误率降低 > 50% - [ ] 学习成本降低 > 40% #### 6.3.4 业务指标 - [ ] 项目交付效率提升 > 25% - [ ] 设计质量评分提升 > 20% - [ ] 客户满意度提升 > 15% - [ ] 跨产品协作成功率 > 90% --- **文档版本**:v4.0 (基于Project表统一产品设计管理) **更新日期**:2025-10-20 **维护者**:YSS Development Team