不同阶段显示的空间数量和名称不一致:
结果:各阶段显示的空间数量不一致,数据不同步。
数据来源:直接查询 Product 表
// quotation-editor.component.ts 第276-281行
const productQuery = new Parse.Query('Product');
productQuery.equalTo('project', this.project.toPointer());
const results = await productQuery.find();
// ✅ 查询到4条Product记录
this.products = results; // 去重后4个
显示逻辑:
数据来源:从 Project.data.unifiedSpaces 读取
// stage-requirements.component.ts 第366行
const unifiedSpaces = await this.productSpaceService.getUnifiedSpaceData(projectId);
// ✅ 从Project.data.unifiedSpaces读取 → 9个空间
getUnifiedSpaceData() 逻辑:
// product-space.service.ts 第571-582行
async getUnifiedSpaceData(projectId: string) {
const data = project.get('data') || {};
// 优先返回统一空间数据
if (data.unifiedSpaces && data.unifiedSpaces.length > 0) {
return data.unifiedSpaces; // ✅ 返回9个空间
}
// 否则从Product表迁移
const productSpaces = await this.getProjectProductSpaces(projectId);
return productSpaces;
}
【订单分配】
↓ 查询
Product表 (4条记录)
↓ 显示
订单分配界面 (4个空间) ❌
【确认需求/交付执行】
↓ 查询
Project.data.unifiedSpaces (9个空间)
↓ 显示
确认需求/交付执行界面 (9个空间) ❌
核心问题:
确保订单分配(数据源头)在保存时同步更新 unifiedSpaces
订单分配阶段是数据的唯一入口,其他阶段应该从它同步数据。因此需要:
Project.data.unifiedSpacesunifiedSpaces 读取文件:quotation-editor.component.ts
位置:第664-713行
方法:saveQuotationToProject()
private async saveQuotationToProject(): Promise<void> {
if (!this.project) return;
try {
const data = this.project.get('data') || {};
data.quotation = this.quotation;
this.project.set('data', data);
await this.project.save();
this.quotationChange.emit(this.quotation);
} catch (error) {
console.error('保存报价失败:', error);
}
}
问题:只保存了 quotation,没有更新 unifiedSpaces
private async saveQuotationToProject(): Promise<void> {
if (!this.project) return;
try {
const data = this.project.get('data') || {};
data.quotation = this.quotation;
// 🔥 关键修复:同步更新 unifiedSpaces,确保各阶段数据一致
data.unifiedSpaces = this.products.map((product, index) => {
const quotation = product.get('quotation') || {};
const space = product.get('space') || {};
const requirements = product.get('requirements') || {};
const profile = product.get('profile');
// 从quotation.spaces中查找对应的工序信息
const quotationSpace = this.quotation.spaces.find((s: any) => s.productId === product.id);
return {
id: product.id,
name: product.get('productName') || '',
type: product.get('productType') || 'other',
area: space.area || 0,
priority: space.priority || 5,
status: product.get('status') || 'not_started',
complexity: space.complexity || 'medium',
estimatedBudget: quotation.price || 0,
order: index,
quotation: {
price: quotation.price || 0,
processes: quotationSpace?.processes || {},
subtotal: quotationSpace?.subtotal || 0
},
requirements: requirements,
designerId: profile?.id || null,
progress: [],
createdAt: product.get('createdAt')?.toISOString() || new Date().toISOString(),
updatedAt: new Date().toISOString()
};
});
console.log(`🔄 [报价编辑器] 同步更新 unifiedSpaces: ${data.unifiedSpaces.length} 个空间`);
this.project.set('data', data);
await this.project.save();
this.quotationChange.emit(this.quotation);
} catch (error) {
console.error('保存报价失败:', error);
}
}
修复内容:
this.products 数组构建 unifiedSpacesProject.data.unifiedSpaces订单分配阶段修改空间
↓
quotation-editor.addProduct()
↓
createProduct() → Product表新增记录
↓
loadProjectProducts() → 重新加载Product表
↓
generateQuotationFromProducts() → 生成报价
↓
saveQuotationToProject() → 保存到Project
├─ data.quotation = {...}
└─ data.unifiedSpaces = [...] 🔥 同步更新
↓
this.products (4个) === Project.data.unifiedSpaces (4个) ✅
↓
发出 productsUpdated 事件
↓
其他阶段重新加载
├─ 确认需求:从unifiedSpaces读取 → 4个空间 ✅
└─ 交付执行:从unifiedSpaces读取 → 4个空间 ✅
添加空间
订单分配点击"添加产品" → 输入"书房"
↓
Product表新增1条记录(总共5条)
↓
saveQuotationToProject() 同步更新 unifiedSpaces(5个空间)
↓
确认需求阶段:显示5个空间 ✅
交付执行阶段:显示5个空间 ✅
删除空间
订单分配删除"餐厅"
↓
Product表删除1条记录(总共3条)
↓
saveQuotationToProject() 同步更新 unifiedSpaces(3个空间)
↓
确认需求阶段:显示3个空间 ✅
交付执行阶段:显示3个空间 ✅
编辑空间
订单分配修改"客厅"为"大客厅"
↓
Product表更新记录
↓
saveQuotationToProject() 同步更新 unifiedSpaces
↓
确认需求阶段:显示"大客厅" ✅
交付执行阶段:显示"大客厅" ✅
如果当前项目的 unifiedSpaces 数据不正确(有9个空间),需要先清理:
在浏览器控制台执行:
const Parse = window.Parse;
const query = new Parse.Query('Project');
const project = await query.get('YOUR_PROJECT_ID');
const data = project.get('data') || {};
console.log('当前unifiedSpaces:', data.unifiedSpaces?.length);
// 清空旧数据
delete data.unifiedSpaces;
project.set('data', data);
await project.save();
console.log('✅ 已清空unifiedSpaces,等待从订单分配重新生成');
观察日志:
🔍 [报价编辑器] Product表查询结果: 4 条记录
✅ 保留空间: 客厅 (ID: xxx)
✅ 保留空间: 次卧 (ID: xxx)
✅ 保留空间: 阳台 (ID: xxx)
✅ 保留空间: 餐厅 (ID: xxx)
✅ [报价编辑器] 最终加载 4 个唯一空间
页面会自动调用 generateQuotationFromProducts()
然后调用 saveQuotationToProject()
观察日志:
🔄 [报价编辑器] 同步更新 unifiedSpaces: 4 个空间
观察控制台日志:
✅ [需求确认] 从统一存储加载到 4 个空间
✅ [需求确认] 空间加载完成,共 4 个空间
验证界面显示:应该显示4个空间(与订单分配一致)
切换到"交付执行"阶段
观察控制台日志:
✅ [交付执行] 从统一存储加载到 4 个空间
✅ [交付执行] 空间加载完成,共 4 个空间
验证界面显示:应该显示4个空间(与订单分配一致)
观察日志:
✅ [产品变更] 已添加产品,当前数量: 5
🔄 [报价编辑器] 同步更新 unifiedSpaces: 5 个空间
切换到"确认需求"或"交付执行"
观察日志(如果已实现监听器):
🔄 [确认需求] 检测到产品添加事件,重新加载空间...
✅ [确认需求] 空间加载完成,共 5 个空间
验证:所有阶段都显示5个空间
如果确认Product表确实只有4条记录,但界面应该显示9个空间(业务需要),那么需要:
补充缺失的Product记录
或者批量创建
在浏览器控制台执行:
const Parse = window.Parse;
const projectId = 'YOUR_PROJECT_ID';
const projectPointer = { __type: 'Pointer', className: 'Project', objectId: projectId };
const missingSpaces = ['主卧', '儿童房', '书房', '厨房', '卫生间'];
for (const spaceName of missingSpaces) {
const product = new Parse.Object('Product');
product.set('project', projectPointer);
product.set('productName', spaceName);
product.set('productType', 'other');
product.set('status', 'not_started');
product.set('space', {
spaceName: spaceName,
area: 0,
spaceType: '平层',
styleLevel: '基础风格组',
complexity: 'medium',
priority: 5
});
product.set('quotation', {
price: 300,
basePrice: 300,
currency: 'CNY',
status: 'draft'
});
await product.save();
console.log(`✅ 已创建空间: ${spaceName}`);
}
console.log('✅ 批量创建完成,请刷新页面');
刷新页面
saveQuotationToProject() 同步更新 unifiedSpaces修复完成时间:2024年11月15日 14:45
问题状态:已修复,等待测试验证