This commit is contained in:
Neo
2026-03-15 10:15:02 +08:00
parent 2dd217522c
commit 72bb11b34f
916 changed files with 65306 additions and 16102803 deletions

View File

@@ -38,7 +38,7 @@
- 商城订单:助教列表(花名+级别+课程类型+服务时长+定档绩效)、支付金额、食品酒水总金额
- 充值:充值金额、支付方式
- 备注列表
- AI 维客线索(应用 8 整合线索 + 人工,读取 `member_retention_clue`Emoji 作为二级标签、提供者逗号分隔展示
- AI 维客线索(应用 8 整合线索 + 人工,读取 `member_retention_clue`Emoji 作为二级标签、提供者显示规则见下方"维客线索提供者显示规则"章节
- AI 客户分析(应用 7 缓存:运营策略数组 + 总结,结账单出现后自动生成;从 `ai_cache` cache_type=app7_customer_analysis 读取)
- "问问助手"入口 → chat.html
@@ -88,7 +88,7 @@
| settle_type | 含义 | 数量占比 | 消费记录样式 |
|:-----------:|------|---------|-------------|
| 1 | 台桌结账 | 78.6% | 下沉到 `dwd_table_fee_log` 台费明细 |
| 3 | 商城订单 | 21.4% | 助教列表 + 支付金额 + 食品酒水 |
| 3 | 商城订单 | 21.4% | 助教列表 + 支付金额 + 食品酒水(含 477 笔纯超休/激励课订单) |
| 5 | 正常充值 | — | 从 `dwd_recharge_order` 单独查询 |
| 7 | 充值退款 | 极少10 笔) | 不在消费记录中展示 |
| 6 | 结算退款 | 极少1 笔) | 不在消费记录中展示 |
@@ -126,6 +126,79 @@ items_sum = table_charge_money + goods_money + assistant_pd_money
---
## 维客线索提供者显示规则
### 后端过滤策略(安全性优先)
⚠️ **重要**:维客线索的过滤必须在后端完成,客户端不进行任何过滤逻辑,以防止数据泄露风险。
**客户详情页后端返回规则**
后端应返回所有相关的维客线索(包括系统生成、当前用户、他人记录、备注分析),但需要根据用户权限进行脱敏:
| 线索类型 | 返回条件 | 说明 |
|---------|--------|------|
| 系统生成 | 总是返回 | `source = 'ai_consumption'`,完整返回 |
| 我的记录 | 总是返回 | `source = 'manual'``recorded_by_assistant_id = 当前用户ID`,完整返回 |
| 他人记录 | 返回完整版本 | `source = 'manual'``recorded_by_assistant_id ≠ 当前用户ID`,返回 `recorded_by_name` |
| 备注分析 | 返回完整版本 | `source = 'ai_note'`,返回原备注的 `recorded_by_name` |
### 前端显示规则
**客户详情页**:前端直接显示后端返回的所有维客线索,显示具体人名:
| source 值 | 显示文案 |
|----------|--------|
| `ai_consumption` | By:系统 |
| `manual` 且有 `recordedByAssistantId` | By:我 |
| `manual``ai_note` 且有 `recordedByName` | By:{recordedByName} |
多条线索时,提供者用逗号分隔展示(如"By:系统, 王芳, 李明"
**任务详情页**:前端根据后端返回的脱敏数据显示(详见 P6 规范)
### 多人情况处理
当同一客户有多条维客线索时,前端按以下规则展示:
1. **按时间排序**:按 `created_at` 升序排列(最早的在前)
2. **取最先反馈**
- 如果有"By:系统"的线索,优先显示最早的"By:系统"
- 如果没有"By:系统",则显示最早的"By:我"或其他人名
3. **单条展示**:维客线索卡片中仅显示一条(最优先的),其他线索可通过"查看全部"或列表展开查看
### 前端实现示例
```typescript
// 客户详情页:直接显示后端返回的数据
function getClueProvider(clue: RetentionClue): string {
if (clue.source === 'ai_consumption') {
return 'By:系统'
}
if (clue.source === 'manual' && clue.recordedByAssistantId) {
return 'By:我'
}
if (clue.recordedByName) {
return `By:${clue.recordedByName}`
}
return 'By:某人' // 备用
}
// 从多条线索中选择最优先的
function selectPrimaryClue(clues: RetentionClue[]): RetentionClue {
const sorted = clues.sort((a, b) =>
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
)
const systemClue = sorted.find(c => c.source === 'ai_consumption')
if (systemClue) return systemClue
return sorted[0]
}
```
---
## 小程序前端开发强制规范
> 以下规范适用于本 SPEC 中所有小程序页面实现,具有强制约束力。