Files
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:03:48 +08:00

2.8 KiB
Raw Permalink Blame History

P9→NS1/RNS1 缺失项 #1客户详情页分段加载策略

简要结论

  • 状态:⚠️ 部分解决
  • 风险等级:🔴
  • 后端采用单 API 返回全部数据(无分段端点),但各扩展模块有独立 try/except 优雅降级;前端无 skeleton 占位,仅有全局 loading toast。

详细审查

审查范围

  • apps/backend/app/routers/xcx_customers.py — CUST-1 路由
  • apps/backend/app/services/customer_service.pyget_customer_detail() 实现
  • apps/miniprogram/miniprogram/pages/customer-detail/customer-detail.ts — 前端加载逻辑
  • apps/miniprogram/miniprogram/pages/customer-detail/customer-detail.wxml — 前端模板

发现

  1. 后端:单 API无分段端点

    • GET /api/xcx/customers/{customer_id} 一次性返回全部数据(基本信息 + Banner + AI 洞察 + 关联助教 + 最亲密助教 + 消费记录 + 备注)
    • 无独立的 /ai-insight/notes/records 等子端点
    • P9 定义的"基本信息→消费汇总→AI 洞察→消费记录→备注"分段加载策略未实现
  2. 后端:优雅降级已实现

    • 各扩展模块(ai_insightretention_cluesnotesconsumption_recordscoach_tasksfavorite_coaches)均有独立 try/except失败时降级为空默认值
    • 核心字段member_info失败直接 500符合预期
  3. 前端:无 skeleton 占位

    • 加载态为全局 g-toast-loading(圆形 loading + "加载中..."文字),非 P9 定义的分段 skeleton
    • loadDetail() 调用单个 fetchCustomerDetail(id) 后一次性 setData
    • 无分段渲染逻辑(先展示基本信息,再逐步加载扩展模块)

证据

后端 get_customer_detail() 一次性返回所有模块:

return {
    "id": customer_id, "name": name, "phone": phone, ...
    "balance": balance, "consumption_60d": consumption_60d, ...
    "ai_insight": ai_insight,
    "coach_tasks": coach_tasks,
    "favorite_coaches": favorite_coaches,
    "retention_clues": retention_clues,
    "consumption_records": consumption_records,
    "notes": notes,
}

前端加载逻辑(无分段):

async loadDetail(id?: string) {
    this.setData({ pageState: 'loading' })
    try {
      if (id) {
        const detail = await fetchCustomerDetail(id)
        // 一次性 setData
      }
      this.setData({ pageState: 'normal' })
    } catch { ... }
}

建议(如未完全解决)

  1. 短期:前端可在单 API 返回后,先渲染 Banner 区域,再用 nextTicksetTimeout 分批 setData 扩展模块,减少首屏白屏时间
  2. 中期:为各扩展模块添加 skeleton 占位组件(参考 TDesign t-skeleton
  3. 长期:后端拆分为多个子端点(/basic/ai-insight/records 等),前端并行请求 + 分段渲染