| 阶段 | 数据来源 | 查询方法 | 空间数量获取 |
|---|---|---|---|
| 🏷️ 订单分配 | Product表 | productSpaceService.getProjectProductSpaces(projectId) |
projectSpaces.length |
| 💰 报价明细 | Project.data | project.get('data').quotation.spaces |
quotation.spaces.length |
| 📦 交付执行 | Product表 | productSpaceService.getProjectProductSpaces(projectId) |
projectProducts.length |
| 👥 设计师分配 | Product表 | productSpaceService.getProjectProductSpaces(projectId) |
spaceScenes.length |
Product
├─ id: string // 空间ID
├─ name: string // 空间名称
├─ type: string // 空间类型
├─ area: number // 面积
├─ status: string // 状态
├─ complexity: string // 复杂度
├─ estimatedBudget: number // 预算
├─ order: number // 排序
├─ project: Pointer // 关联项目
├─ company: Pointer // 关联公司
└─ isDeleted: boolean // 软删除标记
Project.data
├─ quotation: {
│ ├─ spaces: [{
│ │ ├─ name: string // 空间名称
│ │ ├─ spaceId: string // 关联Product ID
│ │ ├─ processes: {...} // 工序明细
│ │ └─ subtotal: number // 小计
│ │}]
│ ├─ total: number // 总价
│ └─ spaceBreakdown: [{...}] // 空间占比
├─ spaceSpecialRequirements: {
│ ├─ [spaceId]: {
│ │ ├─ content: string // 特殊需求内容
│ │ ├─ updatedAt: Date // 更新时间
│ │ └─ updatedBy: string // 更新人
│ └─ }
└─ designerSpaceAssignments: {
├─ [designerId]: string[] // 设计师分配的空间ID列表
└─ }
// 文件:stage-order.component.ts
// 行号:695-758
// 加载空间
this.projectSpaces = await this.productSpaceService
.getProjectProductSpaces(this.project.id);
// 自动同步缺失空间
if (this.projectSpaces.length > 0) {
const missing = quotationSpaces.filter(s => !existingNames.has(s.name));
for (const spaceData of missing) {
await this.productSpaceService.createProductSpace(
this.project.id,
{ name: spaceData.name, type: this.inferSpaceType(spaceData.name) }
);
}
}
// 生成报价
await this.regenerateQuotationFromSpaces();
// 文件:quotation-editor.component.ts
// 读取报价空间
const quotationSpaces = this.project.get('data').quotation.spaces;
// 空间数量
const spaceCount = quotationSpaces.length;
// 通过spaceId关联Product
quotationSpaces.forEach(space => {
const productId = space.spaceId; // 指向Product.id
});
// 文件:stage-delivery.component.ts
// 行号:145-188
// 自动同步报价中的缺失空间
private async syncProductsWithQuotation(): Promise<void> {
const quotationSpaces = this.project.get('data').quotation.spaces;
const existingProducts = await this.productSpaceService
.getProjectProductSpaces(this.project.id);
// 找出缺失的空间并创建
const missing = quotationSpaces.filter(s =>
!existingProducts.some(p => p.name === s.name)
);
for (const s of missing) {
await this.productSpaceService.createProductSpace(
this.project.id,
{ name: s.name, type: 'other' }
);
}
}
// 文件:designer-team-assignment-modal.component.ts
// 行号:951-987
// 加载真实空间数据
async loadRealProjectSpaces() {
this.parseProducts = await this.productSpaceService
.getProjectProductSpaces(this.projectId);
// 转换为SpaceScene格式
this.spaceScenes = this.parseProducts.map(product => ({
id: product.id,
name: product.name,
area: product.area,
description: this.getProductDescription(product)
}));
}
// 获取设计师分配的空间
getDesignerSpacesText(designerId: string): string {
const spaces = this.getDesignerSpaces(designerId);
return spaces.map(s => s.name).join(', ');
}
症状:报价显示5个空间,交付执行显示3个空间
原因:
解决:
// 在报价保存时调用
await this.syncQuotationToProducts();
// 或在交付执行时调用
await this.syncProductsWithQuotation();
症状:弹窗打开时显示空间加载错误
原因:
解决:
// 检查projectId是否正确
console.log('projectId:', this.projectId);
// 确保Product表中有数据
const spaces = await this.productSpaceService
.getProjectProductSpaces(this.projectId);
console.log('spaces:', spaces);
// 如果为空,从报价创建
if (spaces.length === 0) {
await this.createSpacesFromQuotation(
this.project.get('data').quotation.spaces
);
}
症状:分配空间后刷新页面,分配信息消失
原因:
解决:
// 在确认分配时保存
async onConfirmAssignment(result: DesignerAssignmentResult) {
// 保存空间分配到Project.data
const data = this.project.get('data') || {};
data.designerSpaceAssignments = {};
for (const assignment of result.spaceAssignments) {
data.designerSpaceAssignments[assignment.designerId] = assignment.spaceIds;
}
this.project.set('data', data);
await this.project.save();
}
// 查询项目空间
getProjectProductSpaces(projectId: string): Promise<ProductSpace[]>
// 创建空间
createProductSpace(projectId: string, spaceData: Partial<ProductSpace>): Promise<ProductSpace>
// 更新空间
updateProductSpace(spaceId: string, updates: Partial<ProductSpace>): Promise<void>
// 删除空间(软删除)
deleteProductSpace(spaceId: string): Promise<void>
// 计算空间进度
calculateProductProgress(spaceId: string, processTypes: string[]): number
// 加载空间
loadProjectSpaces(): Promise<void>
// 从报价创建空间
createSpacesFromQuotation(quotationSpaces: any[]): Promise<void>
// 推断空间类型
inferSpaceType(spaceName: string): string
// 计算空间预算
calculateSpaceRate(spaceData: any): number
// 从空间生成报价
regenerateQuotationFromSpaces(): Promise<void>
// 更新空间占比
updateSpaceBreakdown(): void
// 同步报价中的空间到Product表
syncProductsWithQuotation(): Promise<void>
// 加载真实空间数据
loadRealProjectSpaces(): Promise<void>
// 获取设计师分配的空间
getDesignerSpaces(designerId: string): SpaceScene[]
// 获取设计师空间文本
getDesignerSpacesText(designerId: string): string
// 检查空间是否被选中
isSpaceSelected(designerId: string, spaceId: string): boolean
// 切换空间选择
toggleSpaceSelection(designerId: string, spaceId: string): void
| 功能 | 文件路径 | 关键行号 |
|---|---|---|
| 空间服务 | src/modules/project/services/product-space.service.ts |
- |
| 订单分配 | src/modules/project/pages/project-detail/stages/stage-order.component.ts |
695-1008 |
| 交付执行 | src/modules/project/pages/project-detail/stages/stage-delivery.component.ts |
145-188 |
| 设计师分配 | src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.ts |
84-88, 296-298, 951-987, 1305-1315 |
始终通过ProductSpaceService查询空间
在保存报价时同步Product表
使用spaceId关联Product和报价
设计师空间分配要持久化
定期验证数据一致性