# 项目空间与交付物统计服务使用指南 ## 概述 `ProjectSpaceDeliverableService` 是一个封装的服务,用于计算项目中的空间数量和每个空间对应的交付物上传状态。这个服务可以在不同的地方使用,如组长端的项目时间轴、看板等。 ## 功能特性 ✅ **空间统计**:根据 Product 表计算项目中有多少个空间 ✅ **交付物统计**:根据 ProjectFile 表统计每个空间的交付物上传情况 ✅ **多类型支持**:支持白模、软装、渲染、后期四种交付类型 ✅ **自动去重**:自动去除重复的空间(按名称) ✅ **完成率计算**:自动计算每个空间和整体的完成率 ✅ **状态标签**:提供状态文本和颜色标识 ## 服务位置 ``` src/modules/project/services/project-space-deliverable.service.ts ``` ## 数据结构 ### 空间交付物信息 (SpaceDeliverableInfo) ```typescript interface SpaceDeliverableInfo { spaceId: string; // 空间ID(Product ID) spaceName: string; // 空间名称 spaceType: string; // 空间类型 deliverableTypes: { whiteModel: number; // 白模文件数量 softDecor: number; // 软装文件数量 rendering: number; // 渲染文件数量 postProcess: number; // 后期文件数量 }; totalFiles: number; // 总文件数 hasDeliverables: boolean; // 是否已上传交付物 completionRate: number; // 完成度(0-100) } ``` ### 项目统计摘要 (ProjectSpaceDeliverableSummary) ```typescript interface ProjectSpaceDeliverableSummary { projectId: string; // 项目ID projectName: string; // 项目名称 totalSpaces: number; // 空间总数 spacesWithDeliverables: number; // 已上传交付物的空间数 spaces: SpaceDeliverableInfo[]; // 空间详细列表 totalDeliverableFiles: number; // 总交付文件数 totalByType: { // 各类型总计 whiteModel: number; softDecor: number; rendering: number; postProcess: number; }; overallCompletionRate: number; // 整体完成率(0-100) } ``` ## 主要方法 ### 1. 获取项目空间与交付物统计摘要 ```typescript async getProjectSpaceDeliverableSummary(projectId: string): Promise ``` **用途**:获取项目的完整统计信息 **示例**: ```typescript import { ProjectSpaceDeliverableService } from '@modules/project/services/project-space-deliverable.service'; constructor( private projectSpaceDeliverableService: ProjectSpaceDeliverableService ) {} async loadProjectStats() { const summary = await this.projectSpaceDeliverableService .getProjectSpaceDeliverableSummary('project123'); console.log(`项目有 ${summary.totalSpaces} 个空间`); console.log(`已上传交付物的空间:${summary.spacesWithDeliverables} 个`); console.log(`总完成率:${summary.overallCompletionRate}%`); // 遍历每个空间的详细信息 summary.spaces.forEach(space => { console.log(`空间:${space.spaceName}`); console.log(` 白模:${space.deliverableTypes.whiteModel} 个文件`); console.log(` 软装:${space.deliverableTypes.softDecor} 个文件`); console.log(` 渲染:${space.deliverableTypes.rendering} 个文件`); console.log(` 后期:${space.deliverableTypes.postProcess} 个文件`); console.log(` 完成率:${space.completionRate}%`); }); } ``` ### 2. 检查项目是否所有空间都已交付 ```typescript async isAllSpacesDelivered(projectId: string): Promise ``` **用途**:快速检查项目是否全部完成 **示例**: ```typescript const isCompleted = await this.projectSpaceDeliverableService .isAllSpacesDelivered('project123'); if (isCompleted) { console.log('✅ 项目所有空间都已完成交付'); } else { console.log('⚠️ 还有空间未完成交付'); } ``` ### 3. 获取未完成空间列表 ```typescript async getIncompleteSpaces(projectId: string): Promise ``` **用途**:获取还未上传交付物的空间名称列表 **示例**: ```typescript const incompleteSpaces = await this.projectSpaceDeliverableService .getIncompleteSpaces('project123'); if (incompleteSpaces.length > 0) { console.log('未完成的空间:', incompleteSpaces.join(', ')); // 例如:未完成的空间:客厅, 主卧, 厨房 } ``` ### 4. 获取项目交付进度百分比 ```typescript async getProjectDeliveryProgress(projectId: string): Promise ``` **用途**:获取项目的整体完成进度(0-100) **示例**: ```typescript const progress = await this.projectSpaceDeliverableService .getProjectDeliveryProgress('project123'); console.log(`项目完成进度:${progress}%`); // 在进度条中使用 this.progressWidth = `${progress}%`; ``` ### 5. 获取交付状态标签 ```typescript getDeliveryStatusLabel(completionRate: number): string ``` **用途**:根据完成率获取状态文本 **返回值**: - `0%`: "未开始" - `1-24%`: "刚开始" - `25-49%`: "进行中" - `50-74%`: "接近完成" - `75-99%`: "即将完成" - `100%`: "已完成" **示例**: ```typescript const rate = 65; const status = this.projectSpaceDeliverableService .getDeliveryStatusLabel(rate); console.log(status); // "接近完成" ``` ### 6. 获取交付状态颜色 ```typescript getDeliveryStatusColor(completionRate: number): string ``` **用途**:根据完成率获取对应的颜色值 **返回值**: - `0%`: `#94a3b8` (灰色) - `1-24%`: `#fbbf24` (黄色) - `25-49%`: `#fb923c` (橙色) - `50-74%`: `#60a5fa` (蓝色) - `75-99%`: `#818cf8` (紫色) - `100%`: `#34d399` (绿色) **示例**: ```typescript const rate = 75; const color = this.projectSpaceDeliverableService .getDeliveryStatusColor(rate); // 在HTML中使用
{{ rate }}%
``` ### 7. 格式化统计摘要为文本 ```typescript formatSummaryText(summary: ProjectSpaceDeliverableSummary): string ``` **用途**:将统计摘要格式化为易读的文本 **示例**: ```typescript const summary = await this.projectSpaceDeliverableService .getProjectSpaceDeliverableSummary('project123'); const text = this.projectSpaceDeliverableService .formatSummaryText(summary); console.log(text); // 输出: // 项目:某某项目 // 空间总数:3 // 已完成空间:2/3 // 总文件数:15 // - 白模:4 // - 软装:5 // - 渲染:4 // - 后期:2 // 完成率:67% ``` ## 在组件中使用 ### 示例1:在组长端时间轴中使用 ```typescript // project-timeline.ts import { ProjectSpaceDeliverableService, ProjectSpaceDeliverableSummary } from '@modules/project/services/project-space-deliverable.service'; @Component({ selector: 'app-project-timeline', // ... }) export class ProjectTimelineComponent implements OnInit { spaceDeliverableCache: Map = new Map(); constructor( private projectSpaceDeliverableService: ProjectSpaceDeliverableService ) {} async ngOnInit() { await this.loadProjectStats(); } private async loadProjectStats() { for (const project of this.projects) { try { const summary = await this.projectSpaceDeliverableService .getProjectSpaceDeliverableSummary(project.projectId); // 缓存统计数据 this.spaceDeliverableCache.set(project.projectId, summary); console.log(`✅ 项目 ${project.projectName} 统计完成:`, { 空间数: summary.totalSpaces, 已完成空间: summary.spacesWithDeliverables, 完成率: `${summary.overallCompletionRate}%` }); } catch (error) { console.warn(`⚠️ 加载项目统计失败:`, error); } } } // 获取项目空间数量 getProjectSpaceCount(projectId: string): number { const summary = this.spaceDeliverableCache.get(projectId); return summary?.totalSpaces || 0; } // 获取项目交付完成率 getProjectDeliveryCompletionRate(projectId: string): number { const summary = this.spaceDeliverableCache.get(projectId); return summary?.overallCompletionRate || 0; } // 格式化工具提示 formatTooltip(projectId: string): string { const summary = this.spaceDeliverableCache.get(projectId); if (!summary) return '加载中...'; return `📦 空间与交付物统计\n\n` + `空间总数: ${summary.totalSpaces}\n` + `已完成空间: ${summary.spacesWithDeliverables}/${summary.totalSpaces}\n` + `完成率: ${summary.overallCompletionRate}%`; } } ``` ### 示例2:在HTML模板中显示 ```html

{{ project.name }}

@if (getSpaceDeliverableSummary(project.id); as summary) { 📦 {{ summary.spacesWithDeliverables }}/{{ summary.totalSpaces }} }
{{ getProjectDeliveryCompletionRate(project.id) }}%
@if (getSpaceDeliverableSummary(project.id); as summary) {
{{ summary.totalSpaces }}
{{ summary.spacesWithDeliverables }}
{{ summary.totalDeliverableFiles }}
{{ summary.totalByType.whiteModel }}
{{ summary.totalByType.softDecor }}
{{ summary.totalByType.rendering }}
{{ summary.totalByType.postProcess }}
}
``` ## 性能优化建议 ### 1. 使用缓存 ```typescript // 缓存统计数据,避免重复查询 private cache: Map = new Map(); async getStats(projectId: string) { // 检查缓存 if (this.cache.has(projectId)) { return this.cache.get(projectId)!; } // 加载并缓存 const summary = await this.projectSpaceDeliverableService .getProjectSpaceDeliverableSummary(projectId); this.cache.set(projectId, summary); return summary; } ``` ### 2. 异步加载 ```typescript // 异步加载,不阻塞主流程 private async loadStatsInBackground() { for (const project of this.projects) { // 使用 setTimeout 避免阻塞UI setTimeout(async () => { const summary = await this.projectSpaceDeliverableService .getProjectSpaceDeliverableSummary(project.id); this.updateProjectStats(project.id, summary); }, 0); } } ``` ### 3. 批量加载 ```typescript // 并行加载多个项目的统计数据 private async loadStatsInBatch(projectIds: string[]) { const promises = projectIds.map(id => this.projectSpaceDeliverableService.getProjectSpaceDeliverableSummary(id) ); const results = await Promise.allSettled(promises); results.forEach((result, index) => { if (result.status === 'fulfilled') { this.cache.set(projectIds[index], result.value); } else { console.warn(`加载项目 ${projectIds[index]} 统计失败:`, result.reason); } }); } ``` ## 注意事项 1. **空间去重**:服务会自动去除重复的空间(按名称去重,忽略大小写和首尾空格) 2. **文件类型**:只统计 `delivery_*` 类型的文件(白模、软装、渲染、后期) 3. **异步操作**:所有方法都是异步的,需要使用 `await` 或 `.then()` 4. **错误处理**:建议在调用时添加 try-catch 处理错误情况 5. **缓存策略**:建议在组件中实现缓存,避免频繁查询数据库 ## 完整应用示例 请参考以下文件中的实际应用: - **时间轴组件**:`src/app/pages/team-leader/project-timeline/project-timeline.ts` - **交付阶段组件**:`src/modules/project/pages/project-detail/stages/stage-delivery.component.ts` ## 相关文档 - [项目文件服务](./PROJECT-FILE-SERVICE.md) - [产品空间服务](./PRODUCT-SPACE-SERVICE.md) - [组长端时间轴使用指南](./TEAM-LEADER-TIMELINE-GUIDE.md) ## 技术支持 如有问题,请联系开发团队或查看源码注释。