# 报价空间重复问题修复方案 ## 问题描述 在报价页面中发现存在重复的空间报价条目,例如: - 儿童房出现2次 - 卫生间出现2次 - 厨房出现2次 - 客厅出现2次 - 次卧出现2次 - 阳台出现2次 - 餐厅出现2次 这导致页面显示混乱,报价计算不准确。 ## 问题原因 1. **数据库层面**:在`Product`表中可能存在同名空间的重复记录 2. **前端展示**:虽然之前的代码已经有去重逻辑,但未能检测和提醒用户清理数据库中的重复数据 ## 解决方案 ### 1. 增强报价生成的去重逻辑 **位置**: `quotation-editor.component.ts` - `generateQuotationFromProducts()` 方法 **改进内容**: - 使用 `Map` 数据结构确保同名空间只保留第一个 - 记录所有重复的产品ID - 如果检测到重复,提示用户是否自动清理 - 在控制台输出详细的去重日志 ```typescript // 使用 Map 去重,key 为空间名称,value 为空间数据 const spaceMap = new Map(); const duplicateProductIds: string[] = []; for (const product of this.products) { const productName = product.get('productName'); // 如果该空间名称已存在,记录重复的产品ID if (spaceMap.has(productName)) { console.log(`⚠️ 检测到重复空间: ${productName} (产品ID: ${product.id})`); duplicateProductIds.push(product.id); continue; } // ... 处理唯一空间 } // 如果检测到重复产品,提示用户清理 if (duplicateProductIds.length > 0) { console.warn(`⚠️ 检测到 ${duplicateProductIds.length} 个重复产品,建议清理`); if (this.canEdit && await window?.fmode?.confirm(`检测到 ${duplicateProductIds.length} 个重复空间产品,是否自动清理?`)) { await this.removeDuplicateProducts(duplicateProductIds); return; // 清理后重新生成报价 } } ``` ### 2. 新增批量删除重复产品方法 **方法**: `removeDuplicateProducts(productIds: string[])` **功能**: - 批量删除指定的重复产品记录 - 删除后自动重新加载产品列表 - 重新生成报价确保数据一致性 - 提供详细的操作日志 ```typescript async removeDuplicateProducts(productIds: string[]): Promise { console.log(`🗑️ 开始清理 ${productIds.length} 个重复产品...`); // 批量删除重复产品 for (const productId of productIds) { const product = this.products.find(p => p.id === productId); if (product) { await product.destroy(); console.log(` ✓ 已删除: ${product.get('productName')} (${productId})`); } } // 重新加载产品列表并生成报价 await this.loadProjectProducts(); await this.generateQuotationFromProducts(); console.log('✅ 重复产品清理完成'); } ``` ### 3. 新增手动清理工具方法 **方法**: `cleanupDuplicateProducts()` **功能**: - 扫描所有产品,检测重复的空间名称 - 显示详细的重复信息(空间名称和数量) - 保留第一个产品,删除后续重复的 - 用户确认后执行清理操作 ```typescript async cleanupDuplicateProducts(): Promise { // 使用 Map 检测重复 const productNameMap = new Map(); for (const product of this.products) { const productName = product.get('productName'); if (!productNameMap.has(productName)) { productNameMap.set(productName, []); } productNameMap.get(productName)!.push(product); } // 找出所有重复的产品 const duplicateProductIds: string[] = []; const duplicateNames: string[] = []; for (const [name, products] of productNameMap.entries()) { if (products.length > 1) { duplicateNames.push(name); // 保留第一个,删除其余的 for (let i = 1; i < products.length; i++) { duplicateProductIds.push(products[i].id); } } } if (duplicateProductIds.length === 0) { window?.fmode?.alert('没有检测到重复产品'); return; } const message = `检测到以下空间存在重复:\n${duplicateNames.join('、')}\n\n共 ${duplicateProductIds.length} 个重复产品,是否清理?`; if (await window?.fmode?.confirm(message)) { await this.removeDuplicateProducts(duplicateProductIds); } } ``` ### 4. UI 界面改进 **位置**: `quotation-editor.component.html` 在产品管理工具栏添加"清理重复"按钮: ```html ``` ## 使用方法 ### 方式一:生成报价时自动检测(推荐) 1. 打开项目的订单页面 2. 点击"生成报价"按钮 3. 如果检测到重复空间,系统会弹出确认对话框 4. 点击"确定"自动清理重复产品 5. 清理完成后自动重新生成报价 ### 方式二:手动清理重复 1. 打开项目的订单页面 2. 点击工具栏的"清理重复"按钮 3. 系统显示重复空间的详细信息 4. 确认后自动清理并重新生成报价 ## 技术细节 ### 去重策略 - **保留原则**: 保留第一个创建的产品,删除后续重复的 - **识别标准**: 使用 `productName` 字段作为唯一标识 - **数据安全**: 删除操作前会弹出确认对话框 ### 数据流程 ``` 加载产品列表 → 检测重复 → 提示用户 → 删除重复记录 → 重新加载 → 生成唯一报价 ``` ### 日志输出 系统会在控制台输出详细日志,方便调试: - `⚠️ 检测到重复空间`: 发现重复时 - `🗑️ 开始清理`: 开始删除操作 - `✓ 已删除`: 每个产品删除成功 - `✅ 报价空间生成完成`: 显示最终的唯一空间数量 ## 预期效果 ### 修复前 - 报价列表显示16个空间(包含8个重复) - 多个空间名称相同 - 报价总额可能重复计算 ### 修复后 - 报价列表显示8个唯一空间 - 每个空间类型只显示一次 - 报价总额准确反映实际空间 ## 样式保留 本次修复完全保留了原有的UI样式: - ✅ 蓝色产品卡片标识 - ✅ 价格显示样式 - ✅ 状态徽章(未开始、进行中等) - ✅ 百分比显示 - ✅ 展开/折叠功能 - ✅ 编辑和删除按钮 ## 测试建议 1. **功能测试**: - 创建多个同名空间产品 - 点击"生成报价"验证自动检测 - 点击"清理重复"手动清理 2. **边界测试**: - 无重复产品时的提示 - 全部产品都重复的情况 - 删除操作取消的情况 3. **数据验证**: - 确认只删除重复的产品 - 确认保留第一个产品 - 确认报价总额正确 ## 注意事项 1. **权限控制**: 只有具有编辑权限(`canEdit = true`)的用户才能看到清理按钮 2. **数据备份**: 删除操作不可逆,建议在测试环境先验证 3. **并发问题**: 如果多人同时编辑,可能需要刷新页面 4. **性能考虑**: 批量删除时会逐个调用API,大量重复时可能需要一定时间 ## 相关文件 - `src/modules/project/components/quotation-editor.component.ts` - 核心逻辑 - `src/modules/project/components/quotation-editor.component.html` - UI界面 - `src/modules/project/components/quotation-editor.component.scss` - 样式(无改动) ## 版本信息 - **修复日期**: 2025-10-31 - **影响范围**: 报价编辑器组件 - **向下兼容**: 是 - **破坏性变更**: 否