PRODUCT_SPACE_SYNC_ISSUE.md 5.0 KB

Product表空间同步问题分析

📊 问题概述

从截图和代码分析发现:

  1. ✅ Product表空间存储结构正确
  2. ⚠️ 订单分配阶段修改空间后,其他阶段不实时同步
  3. ⚠️ 可能存在重复的Product记录

🗄️ Product表存储结构(正确)

字段定义

Product {
  project: Pointer            // 关联项目
  productName: string         // 空间名称(如"客厅")
  productType: string         // 产品类型
  status: string             // 状态
  
  space: {                   // 空间信息
    spaceName: string
    area: number
    spaceType: string
    styleLevel: string
    complexity: string
  }
  
  quotation: {               // 报价信息
    price: number
    basePrice: number
    priceLevel: string
  }
  
  requirements: {}           // 需求信息
  profile: Pointer          // 分配的设计师
}

创建位置quotation-editor.component.ts 第336-414行


🔄 数据同步流程

1. 订单分配阶段(quotation-editor)

加载流程

ngOnInit()
  → loadProjectProducts()       // 查询Product表
  → 去重(按productName)
  → generateQuotationFromProducts()  // 生成报价
  → saveQuotationToProject()    // 保存到Project.data

添加空间

addProduct()
  → createProduct()             // 创建Product记录
  → product.save()             // 保存到Product表
  → loadProjectProducts()      // 重新加载
  → generateQuotationFromProducts()
  → saveQuotationToProject()

删除空间

deleteProduct()
  → product.destroy()          // 删除Product记录
  → 更新this.products
  → 更新quotation.spaces
  → saveQuotationToProject()

2. 其他阶段读取数据

确认需求、交付执行都通过:

this.projectProducts = await this.productSpaceService.getProjectProductSpaces(projectId);

ProductSpaceService.getProjectProductSpaces()

  • 查询Product表
  • 按名称去重(保留第一个)
  • 返回空间列表

⚠️ 核心问题

问题1:数据不实时同步

现象

  • 订单分配阶段添加/删除空间
  • 切换到其他阶段,显示旧数据
  • 需要刷新页面才能看到最新数据

原因

  • 各阶段在ngOnInit时读取数据并缓存
  • 订单分配修改后不会通知其他阶段
  • 缺少跨组件的数据同步机制

问题2:可能存在重复Product记录

检测方法

// quotation-editor已有检测逻辑
async generateQuotationFromProducts() {
  const spaceMap = new Map<string, any>();
  const duplicateProductIds: string[] = [];
  
  for (const product of this.products) {
    if (spaceMap.has(productName)) {
      duplicateProductIds.push(product.id);
    }
  }
  
  // 提示清理重复产品
  if (duplicateProductIds.length > 0) {
    await this.removeDuplicateProducts(duplicateProductIds);
  }
}

🔧 解决方案

方案1:添加事件通知机制(推荐)

步骤1:quotation-editor发出事件

// quotation-editor.component.ts
@Output() productsUpdated = new EventEmitter<void>();

async addProduct() {
  await this.createProduct(name);
  await this.loadProjectProducts();
  await this.generateQuotationFromProducts();
  this.productsUpdated.emit();  // 🔥 发出事件
}

async deleteProduct() {
  // ...
  await this.saveQuotationToProject();
  this.productsUpdated.emit();  // 🔥 发出事件
}

步骤2:stage-order监听并转发

// stage-order.component.html
<app-quotation-editor
  (productsUpdated)="onProductsUpdated()"
></app-quotation-editor>

// stage-order.component.ts
onProductsUpdated() {
  // 发出全局事件
  const event = new CustomEvent('product-spaces-updated', {
    detail: { projectId: this.project.id },
    bubbles: true
  });
  document.dispatchEvent(event);
}

步骤3:其他阶段监听全局事件

// stage-requirements/stage-delivery
ngOnInit() {
  document.addEventListener('product-spaces-updated', (event: any) => {
    if (event.detail?.projectId === this.projectId) {
      this.loadProjectProducts();  // 重新加载
    }
  });
}

方案2:各阶段主动刷新

// 每次进入阶段时重新加载
async ngOnInit() {
  await this.loadProjectProducts();  // 强制刷新
}

方案3:添加手动刷新按钮

<button (click)="refreshProductSpaces()">
  刷新空间列表
</button>

📝 需要修改的文件

  1. quotation-editor.component.ts

    • 添加@Output() productsUpdated
    • 在add/edit/delete中发出事件
  2. stage-order.component.ts/html

    • 监听productsUpdated事件
    • 发出全局事件
  3. stage-requirements.component.ts

    • 监听全局事件
    • 重新加载数据
  4. stage-delivery.component.ts

    • 监听全局事件
    • 重新加载数据

🎯 验证步骤

  1. 在订单分配添加空间
  2. 切换到确认需求→应显示新空间
  3. 切换到交付执行→应显示新空间
  4. 删除空间后,其他阶段应同步更新