# 项目管理 - 交付执行阶段 PRD (Product表版本) ## 1. 功能概述 ### 1.1 阶段定位 交付执行阶段是项目管理流程的核心执行环节,包含建模、软装、渲染、后期四个连续子阶段。该阶段负责将设计方案转化为可交付的视觉成果,是项目价值实现的关键环节。 ### 1.2 核心目标 - **多产品设计协同管理**:支持单产品设计到多产品设计项目的灵活管理 - **按产品设计维度组织文件上传和进度管理** - **实现四个执行阶段的串行推进** - **跨产品设计协调与依赖管理**:处理产品设计间的风格一致性、色彩流线、材质匹配 - **提供实时进度跟踪和状态可视化** - **支持组长审核和质量把控** - **确保交付物符合质量标准** ### 1.3 涉及角色 - **设计师**:负责建模、软装、后期等设计工作 - **渲染师**:负责渲染阶段的大图输出 - **组长**:审核各阶段交付物、把控质量 - **技术**:验收最终交付物、确认质量 ### 1.4 四大执行子阶段 ```mermaid graph LR A[方案确认] --> B[建模] B --> C[软装] C --> D[渲染] D --> E[后期] E --> F[尾款结算] style B fill:#e3f2fd style C fill:#fff3e0 style D fill:#fce4ec style E fill:#f3e5f5 ``` ## 2. 基于Product表的交付管理系统 ### 2.1 产品交付管理架构 #### 2.1.1 增强的DeliveryProcess接口 ```typescript interface ProductDeliveryProcess { id: string; // 流程ID: 'modeling' | 'softDecor' | 'rendering' | 'postProcess' name: string; // 流程名称:建模/软装/渲染/后期 type: 'modeling' | 'softDecor' | 'rendering' | 'postProcess'; isExpanded: boolean; // 是否展开 // 产品管理(基于Product表) products: ProductDelivery[]; content: Record; // 跨产品协调(基于Product表) crossProductCoordination: { dependencies: ProductDependency[]; // 产品依赖关系 batchOperations: BatchOperation[]; // 批量操作 qualityStandards: QualityStandard[]; // 质量标准 }; // 整体进度管理 overallProgress: { total: number; // 总体进度 byProduct: Record; // 各产品进度 byStage: Record; // 各阶段进度 estimatedCompletion: Date; }; } interface ProductDelivery { productId: string; // 产品ID(与Product.objectId关联) productName: string; // 产品名称:李总主卧设计 productType: string; // 产品类型:bedroom isExpanded: boolean; // 是否展开 order: number; // 排序顺序 priority: number; // 优先级 status: ProductStatus; // 产品状态 assigneeId: string; // 负责人ID(Product.profile) estimatedHours: number; // 预估工时 actualHours: number; // 实际工时 // 产品报价信息 quotation: { price: number; breakdown: { design: number; modeling: number; rendering: number; softDecor: number; }; status: string; }; } interface ProductContent { // 产品文件(基于ProjectFile分类) files: Array<{ id: string; name: string; url: string; size?: string; fileCategory: string; // 'delivery' | 'reference' | 'other' reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean; // 是否已同步到客户端 uploadTime: Date; // 上传时间 uploadedBy: string; // 上传人 }>; progress: number; // 进度 0-100 status: 'pending' | 'in_progress' | 'completed' | 'approved'; notes: string; // 备注信息 lastUpdated: Date; // 最后更新时间 // 产品特定字段 productSpecific: { // 建模阶段特有 modelingComplexity?: 'simple' | 'medium' | 'complex'; structuralConstraints?: string[]; // 软装阶段特有 furnitureList?: string[]; materialSelection?: string[]; // 渲染阶段特有 renderingQuality?: 'standard' | 'high' | 'ultra'; outputResolution?: string; // 后期阶段特有 postProcessingTypes?: string[]; finalTouches?: string[]; }; } ``` #### 2.1.2 基于Product表的交付管理服务 ```typescript class ProductDeliveryService { // 获取项目的交付管理数据 async getProjectDeliveryData(projectId: string): Promise { // 1. 获取项目的所有产品 const productQuery = new Parse.Query("Product"); productQuery.equalTo("project", { __type: "Pointer", className: "Project", objectId: projectId }); productQuery.include("profile"); productQuery.ascending("order"); const products = await productQuery.find(); // 2. 构建交付管理数据结构 const deliveryProcesses: ProductDeliveryProcess[] = []; for (const stage of ['modeling', 'softDecor', 'rendering', 'postProcess']) { const process: ProductDeliveryProcess = { id: stage, name: this.getStageName(stage), type: stage as any, isExpanded: false, products: [], content: {}, crossProductCoordination: { dependencies: [], batchOperations: [], qualityStandards: [] }, overallProgress: { total: 0, byProduct: {}, byStage: {}, estimatedCompletion: new Date() } }; // 3. 为每个产品构建交付数据 for (const product of products) { const productDelivery: ProductDelivery = { productId: product.id, productName: product.get("productName"), productType: product.get("productType"), isExpanded: false, order: product.get("order") || 0, priority: product.get("space")?.priority || 5, status: product.get("status") || "not_started", assigneeId: product.get("profile")?.id, estimatedHours: product.get("estimatedDuration") * 8, // 天数转小时 actualHours: 0, quotation: product.get("quotation") || {} }; // 4. 获取产品的交付文件 const productFiles = await this.getProductDeliveryFiles(product.id, stage); // 5. 构建产品内容 const productContent: ProductContent = { files: productFiles.map(file => ({ id: file.id, name: file.get("fileName"), url: file.get("fileUrl"), size: this.formatFileSize(file.get("fileSize")), fileCategory: file.get("fileCategory"), reviewStatus: file.get("data")?.reviewStatus || "pending", uploadTime: file.get("createdAt"), uploadedBy: file.get("uploadedBy")?.get("name") })), progress: this.calculateProductProgress(product, stage), status: this.getProductStatus(product, stage), notes: product.get("data")?.deliveryNotes || "", lastUpdated: product.get("updatedAt"), productSpecific: this.getProductSpecificFields(product, stage) }; process.products.push(productDelivery); process.content[product.id] = productContent; process.overallProgress.byProduct[product.id] = productContent.progress; } deliveryProcesses.push(process); } return deliveryProcesses; } // 获取产品的交付文件 async getProductDeliveryFiles(productId: string, stage: string): Promise { const fileQuery = new Parse.Query("ProjectFile"); fileQuery.equalTo("product", { __type: "Pointer", className: "Product", objectId: productId }); fileQuery.equalTo("fileCategory", "delivery"); fileQuery.equalTo("stage", stage); fileQuery.notEqualTo("isDeleted", true); fileQuery.descending("createdAt"); return await fileQuery.find(); } // 计算产品进度 calculateProductProgress(product: Parse.Object, stage: string): number { const productFiles = product.get("deliveryFiles") || []; const stageFiles = productFiles.filter((file: any) => file.stage === stage); if (stageFiles.length === 0) return 0; const completedFiles = stageFiles.filter((file: any) => file.reviewStatus === "approved" ); return Math.round((completedFiles.length / stageFiles.length) * 100); } // 获取产品状态 getProductStatus(product: Parse.Object, stage: string): string { const currentStage = product.get("stage"); if (currentStage === stage) { return product.get("status") || "not_started"; } else if (this.isStageCompleted(stage, currentStage)) { return "completed"; } else { return "pending"; } } // 获取产品特定字段 getProductSpecificFields(product: Parse.Object, stage: string): any { const space = product.get("space") || {}; const baseFields = { structuralConstraints: space.constraints || [] }; switch (stage) { case "modeling": return { ...baseFields, modelingComplexity: space.complexity || "medium" }; case "softDecor": return { ...baseFields, furnitureList: product.get("data")?.furnitureList || [], materialSelection: product.get("data")?.materialSelection || [] }; case "rendering": return { ...baseFields, renderingQuality: product.get("data")?.renderingQuality || "standard", outputResolution: product.get("data")?.outputResolution || "1920x1080" }; case "postProcess": return { ...baseFields, postProcessingTypes: product.get("data")?.postProcessingTypes || [], finalTouches: product.get("data")?.finalTouches || [] }; default: return baseFields; } } } ``` ### 2.2 产品交付进度管理 #### 2.2.1 进度跟踪服务 ```typescript class ProductProgressService { // 更新产品进度 async updateProductProgress( productId: string, stage: string, progressData: ProgressUpdateData ): Promise { const productQuery = new Parse.Query("Product"); const product = await productQuery.get(productId); // 更新产品状态 if (progressData.status) { product.set("status", progressData.status); } if (progressData.stage) { product.set("stage", progressData.stage); } // 更新产品数据 const currentData = product.get("data") || {}; const updatedData = { ...currentData, [`${stage}Progress`]: progressData.progress, [`${stage}Notes`]: progressData.notes, [`${stage}LastUpdated`]: new Date() }; product.set("data", updatedData); await product.save(); // 触发进度更新事件 this.emitProgressUpdate(productId, stage, progressData); } // 批量更新产品进度 async batchUpdateProgress( productIds: string[], stage: string, progressData: ProgressUpdateData ): Promise { const productQuery = new Parse.Query("Product"); productQuery.containedIn("objectId", productIds); const products = await productQuery.find(); for (const product of products) { await this.updateProductProgress(product.id, stage, progressData); } } // 计算整体项目进度 calculateOverallProjectProgress( deliveryProcesses: ProductDeliveryProcess[] ): ProjectProgress { const totalProducts = deliveryProcesses.reduce((sum, process) => sum + process.products.length, 0); if (totalProducts === 0) { return { total: 0, byStage: {}, byProduct: {} }; } const progress: ProjectProgress = { total: 0, byStage: {}, byProduct: {} }; // 计算各阶段进度 deliveryProcesses.forEach(process => { const stageProgress = process.products.reduce((sum, product) => { return sum + (process.content[product.productId]?.progress || 0); }, 0); progress.byStage[process.id] = Math.round(stageProgress / process.products.length); }); // 计算各产品进度 deliveryProcesses.forEach(process => { process.products.forEach(product => { const productProgress = process.content[product.productId]?.progress || 0; progress.byProduct[product.productId] = productProgress; }); }); // 计算总体进度 const stageSum = Object.values(progress.byStage).reduce((sum, val) => sum + val, 0); progress.total = Math.round(stageSum / Object.keys(progress.byStage).length); return progress; } } ``` ### 2.3 跨产品协调管理 #### 2.3.1 产品依赖管理 ```typescript class ProductDependencyManager { // 分析产品间依赖关系 analyzeProductDependencies(products: Product[]): ProductDependency[] { const dependencies: ProductDependency[] = []; // 基于产品类型分析依赖 for (let i = 0; i < products.length; i++) { for (let j = i + 1; j < products.length; j++) { const fromProduct = products[i]; const toProduct = products[j]; const dependency = this.analyzeDependency(fromProduct, toProduct); if (dependency) { dependencies.push(dependency); } } } return dependencies; } // 分析两个产品间的依赖关系 private analyzeDependency( fromProduct: Product, toProduct: Product ): ProductDependency | null { const fromType = fromProduct.productType; const toType = toProduct.productType; // 定义产品类型间的依赖关系 const dependencyRules: Record = { 'living_room': { dependsOn: [], reason: '客厅通常是风格参考的起点' }, 'dining_room': { dependsOn: ['living_room'], reason: '餐厅通常需要与客厅风格保持一致' }, 'kitchen': { dependsOn: ['dining_room'], reason: '厨房与餐厅在空间和功能上紧密相关' }, 'bedroom': { dependsOn: ['living_room', 'corridor'], reason: '卧室通常需要参考客厅的整体风格' }, 'bathroom': { dependsOn: ['bedroom'], reason: '卫生间与卧室在功能上紧密相关' }, 'balcony': { dependsOn: ['living_room', 'bedroom'], reason: '阳台通常连接客厅或卧室' } }; const rule = dependencyRules[toType]; if (rule && rule.dependsOn.includes(fromType)) { return { id: `${fromProduct.productId}-${toProduct.productId}`, fromProductId: fromProduct.productId, toProductId: toProduct.productId, fromProductName: fromProduct.productName, toProductName: toProduct.productName, type: 'style_reference', description: rule.reason, priority: this.calculateDependencyPriority(fromType, toType), confidence: 0.8 }; } return null; } // 生成协调建议 generateCoordinationSuggestions( dependencies: ProductDependency[] ): CoordinationSuggestion[] { const suggestions: CoordinationSuggestion[] = []; dependencies.forEach(dep => { suggestions.push({ id: `coord-${dep.id}`, dependencyId: dep.id, type: 'style_consistency', title: `风格一致性建议:${dep.fromProductName} → ${dep.toProductName}`, description: `建议${dep.toProductName}在设计时参考${dep.fromProductName}的整体风格,确保空间的协调统一`, actions: [ `参考${dep.fromProductName}的色彩方案`, `保持材质选择的一致性`, `考虑空间功能的连续性` ], priority: dep.priority }); }); return suggestions; } } ``` ### 2.4 批量操作管理 #### 2.4.1 批量操作服务 ```typescript class BatchOperationService { // 批量上传文件 async batchUploadFiles( productIds: string[], files: File[], fileCategory: string, stage: string, uploaderId: string ): Promise { const results: BatchUploadResult = { successful: [], failed: [], summary: { total: files.length, uploaded: 0, failed: 0 } }; for (const file of files) { try { // 为每个产品上传文件 for (const productId of productIds) { const projectFile = new Parse.Object("ProjectFile"); projectFile.set("product", { __type: "Pointer", className: "Product", objectId: productId }); projectFile.set("fileCategory", fileCategory); projectFile.set("stage", stage); projectFile.set("uploadedBy", { __type: "Pointer", className: "Profile", objectId: uploaderId }); // 设置文件基本信息 projectFile.set("fileName", file.name); projectFile.set("fileSize", file.size); // 上传文件到存储 const fileData = await this.uploadFile(file); projectFile.set("fileUrl", fileData.url); projectFile.set("attach", fileData.attachment); await projectFile.save(); results.successful.push({ productId, fileName: file.name, fileId: projectFile.id }); } results.summary.uploaded++; } catch (error) { results.failed.push({ fileName: file.name, error: error.message }); results.summary.failed++; } } return results; } // 批量更新产品状态 async batchUpdateProductStatus( productIds: string[], status: string, stage: string ): Promise { const productQuery = new Parse.Query("Product"); productQuery.containedIn("objectId", productIds); const products = await productQuery.find(); for (const product of products) { product.set("status", status); product.set("stage", stage); await product.save(); } } // 批量发送审核通知 async batchSendReviewNotifications( productIds: string[], stage: string, reviewerIds: string[] ): Promise { // 获取需要审核的产品 const productQuery = new Parse.Query("Product"); productQuery.containedIn("objectId", productIds); productQuery.include("profile"); const products = await productQuery.find(); // 发送通知给审核人员 for (const reviewerId of reviewerIds) { for (const product of products) { await this.sendReviewNotification({ reviewerId, productId: product.id, productName: product.get("productName"), stage, designerId: product.get("profile")?.id }); } } } } ``` ## 3. 交付执行界面设计 ### 3.1 产品交付管理主界面 ```html

{{ stage.name }}

{{ stage.progress }}%
已选择 {{ selectedProducts.length }} 个产品

产品交付管理 - {{ getStageName(activeStage) }}

{{ product.productName }}

{{ getProductTypeLabel(product.productType) }}
{{ product.designerName }}
{{ getStatusLabel(product.status) }}
{{ product.content.progress }}%
{{ product.content.files.length }}
{{ product.actualHours }}/{{ product.estimatedHours }}h
¥{{ product.quotation.price.toLocaleString() }} {{ getQuotationStatusLabel(product.quotation.status) }}
{{ getBreakdownTypeLabel(key) }}: ¥{{ item.toLocaleString() }}
交付文件
{{ file.name }} {{ file.size }}
产品特定信息
{{ formatFieldValue(key, value) }}
备注信息
最后更新: {{ formatDateTime(product.content.lastUpdated) }}

产品协调报告

{{ coordinationReport.dependencies.length }}个
{{ coordinationReport.suggestions.length }}个

产品依赖关系

{{ dep.fromProductName }} {{ dep.toProductName }}
{{ dep.description }}

协调建议

{{ suggestion.title }}
{{ suggestion.description }}
• {{ action }}
``` ### 3.2 批量操作界面 ```html ``` ## 4. 技术实现要点 ### 4.1 性能优化 - **懒加载**:按需加载产品详情和文件列表 - **虚拟滚动**:处理大量产品时的性能问题 - **缓存机制**:缓存产品状态和进度数据 ### 4.2 用户体验优化 - **拖拽上传**:支持文件拖拽批量上传 - **实时同步**:进度更新实时推送到界面 - **离线支持**:基本的离线操作支持 ### 4.3 数据一致性 - **事务处理**:确保批量操作的数据一致性 - **冲突检测**:检测并发修改冲突 - **版本控制**:文件版本管理和回滚 --- **文档版本**: v3.0 (Product表统一空间管理) **最后更新**: 2025-10-20 **维护者**: YSS Development Team