# 统一空间数据管理实现方案 ## 📋 实施概述 已成功实现**统一空间数据管理系统**,解决了项目空间在不同阶段显示不一致的问题。 ### 核心改进 1. ✅ **统一存储字段**: `Project.data.unifiedSpaces` 作为唯一真实数据源 2. ✅ **初始空间优化**: 家装项目只创建2个空间(客厅+主卧),工装项目只创建1个空间 3. ✅ **自动同步机制**: Product表与统一存储自动双向同步 4. ✅ **数据修复工具**: 提供数据迁移和一致性检查功能 --- ## 🔧 实现的核心方法 ### 1. `saveUnifiedSpaceData(projectId, spaces)` **功能**: 保存统一空间数据到 `Project.data.unifiedSpaces` **数据结构**: ```typescript { id: string, // 空间唯一ID name: string, // 空间名称 type: string, // 空间类型 area: number, // 面积 priority: number, // 优先级 status: string, // 状态 complexity: string, // 复杂度 estimatedBudget: number, // 预算 order: number, // 排序 quotation: { // 报价信息 price: number, processes: {}, subtotal: number }, requirements: {}, // 需求信息 designerId: string | null, // 设计师ID progress: [], // 进度信息 createdAt: string, // 创建时间 updatedAt: string // 更新时间 } ``` **同步行为**: - 保存到 `Project.data.unifiedSpaces` - 同时更新 `Project.data.quotation.spaces`(向后兼容) - 自动同步到 Product 表 --- ### 2. `getUnifiedSpaceData(projectId)` **功能**: 获取统一空间数据 **查询优先级**: 1. 优先从 `Project.data.unifiedSpaces` 读取 2. 如果为空,从 Product 表迁移 3. 如果都没有,返回空数组 **自动迁移**: 首次调用时会自动将 Product 表数据迁移到统一存储 --- ### 3. `createInitialSpaces(projectId, projectType)` **功能**: 创建初始空间(解决一次性生成9个空间的问题) **家装项目** (`projectType = '家装'`): - 创建2个空间:**客厅** + **主卧** - 每个空间预算: 300元 - 工序: 建模(100) + 软装(100) + 渲染(100) **工装项目** (`projectType = '工装'`): - 创建1个空间:**主要空间** - 预算: 500元 - 工序: 建模(150) + 软装(150) + 渲染(150) + 后期(50) --- ### 4. `forceRepairSpaceData(projectId)` **功能**: 强制修复项目空间数据 **修复流程**: 1. 从 Product 表读取所有空间 2. 从 `Project.data.quotation.spaces` 读取报价信息 3. 合并数据,以 Product 表为准 4. 保存到 `Project.data.unifiedSpaces` 5. 同步到 Product 表和报价数据 **使用场景**: 修复历史项目的空间数据不一致问题 --- ### 5. `debugProjectSpaceData(projectId)` **功能**: 检查项目空间数据存储情况 **检查内容**: - `Project.data.unifiedSpaces` 数量 - `Project.data.quotation.spaces` 数量 - Product 表空间数量 - 数据一致性验证 **输出示例**: ``` 🔍 [调试] 检查项目 xxx 的空间数据存储情况... 📊 [调试] Project.data.unifiedSpaces: 3 个空间 - 统一空间列表: ['客厅', '主卧', '次卧'] 📊 [调试] Project.data.quotation.spaces: 3 个空间 - 报价空间列表: ['客厅', '主卧', '次卧'] 📊 [调试] Product表: 3 个空间 - Product空间列表: ['客厅', '主卧', '次卧'] 🔍 [调试] 数据一致性检查: - 统一存储: 3 个 - 报价数据: 3 个 - Product表: 3 个 ✅ [调试] 数据一致性检查通过 ``` --- ## 📊 数据存储结构 ### Project 表 - data 字段 ```typescript { // ✅ 新增:统一空间数据(唯一真实来源) unifiedSpaces: [ { id: 'space_xxx_1', name: '客厅', type: 'living_room', area: 30, priority: 5, status: 'not_started', complexity: 'medium', estimatedBudget: 300, order: 0, quotation: { price: 300, processes: { modeling: { enabled: true, price: 100, unit: '张', quantity: 1 }, softDecor: { enabled: true, price: 100, unit: '张', quantity: 1 }, rendering: { enabled: true, price: 100, unit: '张', quantity: 1 }, postProcess: { enabled: false, price: 0, unit: '张', quantity: 1 } }, subtotal: 300 }, requirements: {}, designerId: null, progress: [], createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-01T00:00:00.000Z' } ], // 保留:报价数据(向后兼容) quotation: { spaces: [ { name: '客厅', spaceId: 'space_xxx_1', // 关联 unifiedSpaces.id processes: { ... }, subtotal: 300 } ], total: 300, spaceBreakdown: [ ... ] }, // 保留:特殊需求 spaceSpecialRequirements: { 'space_xxx_1': { content: '需要充足的储物空间', updatedAt: '2024-01-01T00:00:00.000Z', updatedBy: 'user_id' } }, // 保留:设计师分配 designerSpaceAssignments: { 'designer_id_1': ['space_xxx_1', 'space_xxx_2'], 'designer_id_2': ['space_xxx_3'] } } ``` --- ## 🔄 同步机制 ### 数据流向 ``` 订单分配阶段 ↓ 创建/编辑空间 ↓ saveUnifiedSpaceData() ├─ 保存到 Project.data.unifiedSpaces ✅ ├─ 同步到 Project.data.quotation.spaces └─ 同步到 Product 表 需求确认阶段 ↓ getUnifiedSpaceData() ├─ 从 Project.data.unifiedSpaces 读取 ✅ └─ 如果为空,从 Product 表迁移 交付执行阶段 ↓ getUnifiedSpaceData() ├─ 从 Project.data.unifiedSpaces 读取 ✅ └─ 显示交付物列表 设计师分配 ↓ getUnifiedSpaceData() ├─ 从 Project.data.unifiedSpaces 读取 ✅ └─ 显示可分配空间列表 ``` --- ## 🚀 使用指南 ### 1. 创建新项目时 ```typescript // 在订单分配阶段,初始化空间 await this.productSpaceService.createInitialSpaces( projectId, '家装' // 或 '工装' ); // 结果:家装项目创建2个空间(客厅+主卧) // 工装项目创建1个空间(主要空间) ``` ### 2. 添加/编辑空间时 ```typescript // 获取当前空间列表 const spaces = await this.productSpaceService.getUnifiedSpaceData(projectId); // 添加新空间 spaces.push({ id: `space_${Date.now()}`, name: '次卧', type: 'bedroom', area: 15, priority: 5, status: 'not_started', complexity: 'medium', estimatedBudget: 300, order: spaces.length, quotation: { price: 300, processes: {}, subtotal: 300 }, requirements: {}, designerId: null, progress: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }); // 保存更新 await this.productSpaceService.saveUnifiedSpaceData(projectId, spaces); ``` ### 3. 加载空间数据时 ```typescript // 所有阶段统一使用此方法 const spaces = await this.productSpaceService.getUnifiedSpaceData(projectId); // 空间数量 const spaceCount = spaces.length; // 遍历空间 spaces.forEach(space => { console.log(`空间: ${space.name}, 状态: ${space.status}`); }); ``` ### 4. 修复历史数据时 ```typescript // 修复单个项目 await this.productSpaceService.forceRepairSpaceData(projectId); // 检查数据一致性 await this.productSpaceService.debugProjectSpaceData(projectId); ``` --- ## ✅ 解决的问题 ### 问题1: 空间数量不一致 **原因**: 不同阶段从不同数据源读取空间 **解决**: 统一从 `Project.data.unifiedSpaces` 读取 ### 问题2: 初始创建9个空间 **原因**: 订单分配阶段默认创建所有常见空间类型 **解决**: 只创建1-2个默认空间,用户可自行添加 ### 问题3: 数据同步延迟 **原因**: Product 表和 Project.data 不同步 **解决**: 保存时自动双向同步 ### 问题4: 历史数据不一致 **原因**: 旧项目使用旧的数据结构 **解决**: 提供 `forceRepairSpaceData` 修复工具 --- ## 🔍 验证方法 ### 1. 创建新项目 1. 进入订单分配阶段 2. 检查初始空间数量(应为1-2个) 3. 添加新空间 4. 进入需求确认阶段,检查空间数量是否一致 5. 进入交付执行阶段,检查空间数量是否一致 6. 打开设计师分配弹窗,检查空间数量是否一致 ### 2. 修复历史项目 1. 打开浏览器控制台 2. 执行: `await productSpaceService.debugProjectSpaceData('项目ID')` 3. 查看数据一致性报告 4. 如果不一致,执行: `await productSpaceService.forceRepairSpaceData('项目ID')` 5. 再次检查一致性 --- ## 📝 注意事项 1. **向后兼容**: `Project.data.quotation.spaces` 仍然保留,确保旧代码正常运行 2. **自动迁移**: 首次调用 `getUnifiedSpaceData` 会自动迁移 Product 表数据 3. **双向同步**: 修改 `unifiedSpaces` 会自动同步到 Product 表和报价数据 4. **数据修复**: 对于历史项目,建议运行 `forceRepairSpaceData` 进行一次性修复 --- ## 🎯 下一步建议 1. **批量修复**: 创建后台任务,批量修复所有历史项目 2. **监控告警**: 添加数据一致性监控,发现不一致时自动告警 3. **UI优化**: 在订单分配阶段添加"快速添加空间"功能 4. **权限控制**: 限制只有特定角色可以修改空间数据 --- ## 📞 技术支持 如有问题,请查看: - `SPACE_SYNC_ANALYSIS_PART1.md` - 详细分析报告 - `SPACE_SYNC_ANALYSIS_PART2.md` - 实现细节 - `SPACE_SYNC_QUICK_REFERENCE.md` - 快速参考指南