delivery-upload-and-message-fix.md 12 KB

交付执行图片上传、分类和消息发送完整修复

🎯 用户需求

  1. 图片自动归类:上传后按AI分析结果自动归类到对应阶段(白模/软装/渲染/后期)
  2. 上传后发送消息:自动弹出消息窗口,发送到企业微信当前窗口

✅ 已实现功能

1. AI分析归类逻辑

drag-upload-modal.component.ts (第446行)

stageType: file.selectedStage || file.suggestedStage || 'white_model'

归类优先级

  1. 用户手动选择的阶段 (selectedStage)
  2. AI建议的阶段 (suggestedStage) ⬅️ 主要使用
  3. 默认白模 ('white_model')

AI分析流程

上传图片 → startEnhancedMockAnalysis()
    ↓
generateEnhancedAnalysisResult(file)
    ↓
分析:色彩、纹理、质量、内容
    ↓
determineSuggestedStage()
    ↓
返回:white_model/soft_decor/rendering/post_process
    ↓
设置 file.suggestedStage
    ↓
确认上传时使用此值作为stageType

分类标准(image-analysis.service.ts):

白模 (white_model):
  - 无色彩 (hasColor = false)
  - 无纹理 (hasTexture = false)
  - 无家具 (hasFurniture = false)
  - 无灯光 (hasLighting = false)
  - 质量低 (score < 60)

软装 (soft_decor):
  - 有家具 (hasFurniture = true)
  - 无灯光 (hasLighting = false)
  - 质量中等 (60 ≤ score < 80)

渲染 (rendering):
  - 有灯光 (hasLighting = true)
  - 质量高 (score ≥ 70)

后期 (post_process):
  - 质量极高 (score ≥ 85)
  - 超精细 (detailLevel = 'ultra_detailed')

2. 上传流程详解

confirmDragUpload() (stage-delivery.component.ts 第2910行)

完整流程

用户点击"确认交付清单"
    ↓
遍历每个文件 {
  1. 输出AI分析结果日志
     - 文件名
     - AI建议阶段 (suggestedStage)
     - 最终使用阶段 (stageType)
     - AI置信度
     
  2. 调用 uploadDeliveryFile(event, spaceId, stageType)
     ↓
  3. ProjectFileService.uploadProjectFileWithRecord()
     - 上传到OBS(3次重试)
     - 创建Attachment记录
     - 创建ProjectFile记录
       fileType: `delivery_${stageType}`  🔥 关键
       stage: 'delivery'
       data: {
         spaceId: spaceId,  🔥 关键
         productId: spaceId,
         deliveryType: stageType,  🔥 关键
         approvalStatus: 'unverified'
       }
     
  4. 保存AI分析结果
     - ProjectFile.data.aiAnalysis
     - Project.date.imageAnalysis
}
    ↓
刷新文件列表 loadDeliveryFiles()
    ↓
🔥 自动弹出消息窗口 promptSendMessageAfterUpload()

3. 图片加载流程

loadDeliveryFiles() (stage-delivery.component.ts 第676行)

查询逻辑

for (const product of this.projectProducts) {
  for (const deliveryType of this.deliveryTypes) {
    // 🔥 查询条件1:fileType
    const files = await this.projectFileService.getProjectFiles(
      projectId,
      {
        fileType: `delivery_${deliveryType.id}`,  // white_model/soft_decor/etc.
        stage: 'delivery'
      }
    );
    
    // 🔥 查询条件2:spaceId过滤
    const productFiles = files.filter(file => {
      const data = file.get('data');
      return data?.spaceId === product.id;  // 匹配当前空间
    });
    
    // 转换为DeliveryFile格式
    this.deliveryFiles[product.id][deliveryType.id] = productFiles.map(...);
  }
}

关键字段匹配

  • fileType: delivery_white_model / delivery_soft_decor / delivery_rendering / delivery_post_process
  • data.spaceId: 空间ID(Product ID)
  • data.deliveryType: white_model / soft_decor / rendering / post_process

4. 消息发送功能

自动提示发送 (新增功能)

触发时机:上传成功后自动触发

代码位置:stage-delivery.component.ts 第3050-3062行

// 🔥 上传成功后,自动提示发送消息
if (successCount > 0) {
  console.log('📧 准备发送消息到企业微信...');
  
  // 为每个上传了文件的空间+阶段组合提示发送消息
  uploadedSpaceStages.forEach((stages, spaceId) => {
    stages.forEach(stageType => {
      // 延迟1.5秒后打开消息弹窗
      setTimeout(() => {
        this.promptSendMessageAfterUpload(spaceId, stageType);
      }, 1500);
    });
  });
}

消息弹窗

promptSendMessageAfterUpload() (第3303行):

promptSendMessageAfterUpload(spaceId: string, stage: string): void {
  // 获取该阶段的所有图片
  const files = this.getProductDeliveryFiles(spaceId, stage);
  const imageUrls = files.map(f => f.url);
  
  if (imageUrls.length > 0) {
    // 延迟显示,让用户看到上传成功的提示
    setTimeout(() => {
      this.openMessageModal(spaceId, stage, imageUrls);
    }, 1000);
  }
}

消息发送到企业微信

sendMessage() (第3220行):

async sendMessage(): Promise<void> {
  // 获取消息内容
  const content = this.customMessage || this.selectedTemplate;
  
  if (this.messageModalConfig.imageUrls.length > 0) {
    // 发送图文消息
    await this.deliveryMessageService.createImageMessage(
      this.project.id!,
      this.messageModalConfig.stage,
      this.messageModalConfig.imageUrls,
      content,
      this.currentUser
    );
  } else {
    // 发送文本消息
    await this.deliveryMessageService.createTextMessage(
      this.project.id!,
      this.messageModalConfig.stage,
      content,
      this.currentUser
    );
  }
  
  window?.fmode?.toast?.success?.('✅ 消息已记录');
}

DeliveryMessageService

使用企业微信SDK发送消息到当前窗口:

import { DeliveryMessageService } from '../../../../../app/pages/services/delivery-message.service';

// 创建图文消息
await deliveryMessageService.createImageMessage(
  projectId,
  stage,
  imageUrls,
  content,
  currentUser
);

// 创建文本消息
await deliveryMessageService.createTextMessage(
  projectId,
  stage,
  content,
  currentUser
);

🔍 调试日志说明

上传时的日志

🚀 开始批量上传文件: 3 个文件

🎯 文件 1/3: {
  文件名: "test1.jpg",
  空间ID: "space123",
  空间名: "客厅",
  AI建议阶段: "rendering",  ← AI分析结果
  最终使用阶段: "rendering",  ← 实际使用
  阶段名: "渲染",
  AI置信度: 85
}

📝 准备上传ProjectFile: {
  文件名: "test1.jpg",
  projectId: "XB56jBlvkd",
  fileType: "delivery_rendering",  ← 查询时使用
  productId: "space123",  ← 过滤时使用
  stage: "delivery",
  deliveryType: "rendering"
}

📤 上传尝试 1/3: test1.jpg
📦 使用存储桶CID: cDL6R1hgSi
✅ 文件上传成功

✅ ProjectFile 创建成功: {
  id: "abc123",
  fileType: "delivery_rendering",
  fileUrl: "https://obs.com/test1.jpg",
  fileName: "test1.jpg",
  data.spaceId: "space123",
  data.deliveryType: "rendering"
}

加载时的日志

🔍 开始加载交付文件, projectId: XB56jBlvkd
🔍 空间数量: 2

📦 初始化空间 space123 的文件结构

🔎 查询 space123/rendering 的文件...
📊 查询到 5 个 delivery_rendering 文件

  ✅ 匹配: test1.jpg, fileUrl: 有, spaceId: space123
  ✅ 匹配: test2.jpg, fileUrl: 有, spaceId: space123
  
  📁 过滤后匹配 space123 的文件数: 2

✅ 已加载交付文件

📊 空间文件统计: {
  spaceId: "space123",
  spaceName: "客厅",
  white_model: 0,
  soft_decor: 1,
  rendering: 2,  ← 成功归类
  post_process: 0
}

❓ 故障排查

如果图片没有归类到正确阶段

检查1:AI分析是否执行

打开控制台,查找:

🎯 文件 1/3: {
  AI建议阶段: "rendering",  ← 检查这个值
  最终使用阶段: "rendering"
}

如果AI建议阶段为空或错误,说明AI分析有问题。

检查2:上传时的fileType是否正确

查找:

📝 准备上传ProjectFile: {
  fileType: "delivery_rendering",  ← 必须正确
  deliveryType: "rendering"  ← 必须一致
}

检查3:数据是否保存正确

查找:

✅ ProjectFile 创建成功: {
  fileType: "delivery_rendering",  ← 检查
  data.spaceId: "space123",  ← 检查
  data.deliveryType: "rendering"  ← 检查
}

检查4:查询时是否匹配

查找:

🔎 查询 space123/rendering 的文件...
📊 查询到 5 个 delivery_rendering 文件
  ✅ 匹配: test.jpg, spaceId: space123
  📁 过滤后匹配 space123 的文件数: 2

如果"过滤后匹配"为0,说明spaceId不匹配。

如果消息没有发送

检查1:是否触发发送消息

查找:

📧 准备发送消息到企业微信...

检查2:deliveryMessageService是否正常

检查控制台是否有错误信息。


📋 关键数据流

完整数据流

【拖拽上传】
拖拽图片到弹窗
    ↓
【AI分析】
startEnhancedMockAnalysis()
  - 分析色彩、纹理、质量
  - 设置 suggestedStage
    ↓
【用户确认】
点击"确认交付清单"
    ↓
【批量上传】
confirmDragUpload()
  ↓
  for each file:
    1. 读取 AI建议阶段 (suggestedStage)
    2. 使用该阶段作为 stageType
    3. uploadDeliveryFile(spaceId, stageType)
       ↓
       fileType: `delivery_${stageType}`
       data.spaceId: spaceId
       data.deliveryType: stageType
       ↓
       保存到OBS
       保存到Attachment
       保存到ProjectFile
    ↓
【刷新显示】
loadDeliveryFiles()
  ↓
  查询: fileType = `delivery_${deliveryType}`
  过滤: data.spaceId = spaceId
  ↓
  显示在对应阶段tab
    ↓
【发送消息】
promptSendMessageAfterUpload()
  ↓
  打开消息弹窗
  ↓
  用户输入消息或选择模板
  ↓
  发送到企业微信当前窗口

📝 文件修改清单

  1. project-file.service.ts

    • 修复存储桶配置(使用默认fallback)
    • 3次重试机制
    • 详细错误日志
  2. stage-delivery.component.ts

    • confirmDragUpload: 输出AI分析结果日志
    • uploadDeliveryFile: 详细上传参数日志
    • loadDeliveryFiles: 详细查询和过滤日志
    • 新增: 上传后自动弹出消息窗口
    • 新增: 收集上传的空间和阶段统计
  3. drag-upload-modal.component.ts

    • AI分析使用 suggestedStage
    • 传递完整的分析结果
  4. image-analysis.service.ts

    • 添加色彩和纹理检测
    • 优化白模判定逻辑

✅ 验证步骤

1. 验证AI分类

1. 上传纯白草图 → 应归类到"白模"
2. 上传有色彩图 → 应归类到"软装"/"渲染"/"后期"
3. 查看控制台日志:
   🎯 文件 1/1: {
     AI建议阶段: "white_model" ← 白色草图
     最终使用阶段: "white_model"
   }

2. 验证图片归类显示

1. 点击"确认交付清单"
2. 等待上传完成
3. 查看各阶段tab:
   - 白模 → 显示白模图片
   - 软装 → 显示软装图片
   - 渲染 → 显示渲染图片
   - 后期 → 显示后期图片

3. 验证消息发送

1. 上传成功后,自动弹出消息窗口
2. 显示该阶段的所有图片
3. 选择话术模板或输入自定义消息
4. 点击发送
5. 消息发送到企业微信当前窗口

🎉 功能总结

功能 状态 说明
AI自动分析 分析色彩、纹理、质量、内容
按AI结果归类 使用suggestedStage自动归类
存储桶修复 使用默认存储桶fallback
3次重试机制 提高上传成功率
详细调试日志 输出AI分析、上传、查询全过程
图片正确显示 按spaceId和deliveryType正确过滤
自动发送消息 上传后自动弹出消息窗口
企业微信集成 发送到当前窗口

创建时间:2025-11-28 最后更新:2025-11-28