修复轮播遮罩并补充方案文档

This commit is contained in:
yml2213
2026-07-25 17:55:20 +08:00
parent 3461c02560
commit e0cb15f408
4 changed files with 362 additions and 4 deletions
@@ -0,0 +1,342 @@
# 租客成长等级与主动短信触达方案
## 一、租客成长等级
### 功能范围
- 只统计租号订单,即 `rental_orders`
- 不统计撞车订单,即 `mohong_orders`
- 积分只按已完成租号订单的实付租金累计,不含押金。
- 等级三档:铂金、钻石、巅峰。
- 下单租号时按用户当前等级使用折扣。
- 折扣和升级门槛后台可配置。
- 历史订单保存价格、等级、折扣快照,后台修改配置不影响历史订单。
### 积分规则
推荐规则:
```text
成长积分 = 已完成租号订单实付租金金额
1 元实付租金 = 1 积分
```
不建议统计押金,原因是押金可能退款、免押、暂扣或赔付,直接计入成长积分会让财务口径变复杂。
积分发放时机建议放在租号订单完成后,而不是支付成功后。这样可以避免用户付款后退款、取消或关闭订单导致刷积分。
### 后台配置
使用现有 `system_configs`,新增配置项:
```text
renter.growth_level_rules
```
建议默认值:
```json
{
"enabled": true,
"points_per_yuan": 1,
"levels": [
{ "code": "platinum", "name": "铂金", "min_points": 0, "discount_bps": 9800 },
{ "code": "diamond", "name": "钻石", "min_points": 1000, "discount_bps": 9500 },
{ "code": "peak", "name": "巅峰", "min_points": 5000, "discount_bps": 9000 }
]
}
```
`discount_bps` 使用万分比,避免小数误差。例如 `9800` 表示 9.8 折。
### 数据库字段
`users` 建议新增:
- `renter_growth_points`:租客成长积分。
- `renter_growth_level`:当前租客成长等级。
`rental_orders` 建议新增:
- `rent_original_amount_cent`:原始租金。
- `rent_discount_amount_cent`:租金优惠金额。
- `renter_growth_level`:下单时命中的等级编码。
- `renter_growth_level_name`:下单时命中的等级名称。
- `renter_discount_bps`:下单时命中的折扣。
- `growth_points_awarded`:本单已发放积分,用于防重复。
### 下单折扣
在订单创建阶段应用折扣,支付阶段不重新计算。
现有租号订单创建位置:
```text
backend/internal/modules/order/lifecycle.go
```
现有支付金额来自:
```text
backend/internal/modules/payment/payment_start.go
amountCent := row.RentAmountCent + row.DepositAmountCent
```
因此订单创建时应直接把 `RentAmountCent` 写成折后租金,后续支付、退款、结算、仲裁都沿用订单金额。
推荐折扣范围:
- 只折扣租金。
- 押金不参与折扣。
- 折扣优先扣平台费,不影响号主收入。
- 如果折扣金额超过平台费,第一版建议限制为最多扣到平台费为 0,避免平台费出现负数。
### 自动升级
租号订单首次完成时:
1. 校验 `growth_points_awarded = 0`,避免重复发放。
2. 根据折后租金计算本单积分。
3. 累加到 `users.renter_growth_points`
4. 根据 `min_points` 自动计算用户当前等级。
5. 更新 `users.renter_growth_level`
6. 回写 `rental_orders.growth_points_awarded`
默认只升级不降级。若后台未来调整门槛,可以选择只影响后续升级判断,不主动批量降级。
### 前端范围
后台系统配置页:
- 配置是否启用。
- 配置每元积分。
- 配置三个等级的门槛积分。
- 配置三个等级的折扣。
后台用户管理:
- 展示成长等级。
- 展示成长积分。
- 支持后台调整积分或等级,操作写审计日志。
用户端订单页:
- 展示租金原价。
- 展示等级折扣。
- 展示优惠金额。
- 展示折后租金。
- 展示押金。
- 展示应付合计。
### 测试范围
- 铂金、钻石、巅峰不同等级折扣计算正确。
- 押金不打折。
- 折扣不影响号主收入。
- 支付金额等于折后租金加实付押金。
- 撞车订单完成不增加成长积分。
- 租号订单完成只发放一次成长积分。
- 积分达到门槛后自动升级。
- 后台修改配置不影响历史订单快照。
## 二、主动短信触达
### 业务目标
用户完成一笔租号订单后,平台可以主动发送短信,告知用户本月已经累计完成多少笔租号订单,以及距离领取奖励还差多少笔。
示例文案:
```text
尊敬的 用户名:
您好,您已经在 大锤商行 累计完成 1 笔租号订单,再完成 x 笔即可领取 xxxx。
```
### 统计口径
- 只统计 `rental_orders`
- 只统计状态为 `completed` 的租号订单。
- 不统计 `mohong_orders` 撞车订单。
- 按自然月统计,建议使用订单完成时间 `settled_at`
- 月统计区间为当前月第一天 00:00:00 到下月第一天 00:00:00。
统计 SQL 口径示例:
```sql
SELECT COUNT(*)
FROM rental_orders
WHERE renter_id = ?
AND status = 'completed'
AND settled_at >= ?
AND settled_at < ?;
```
### 触发时机
推荐触发点:租号订单完成后。
现有完成入口:
```text
backend/internal/modules/order/checkout_finalize.go
```
`finalizeCheckout` 会把订单状态改为 `completed`。短信不建议在事务内直接发送,避免短信服务失败导致订单完成失败。
推荐流程:
1. 订单完成事务内写入短信待发送记录。
2. 事务提交后由后台任务发送短信。
3. 发送成功、失败、重试次数都落库。
### 短信通道
项目已有短信集成:
```text
backend/internal/integrations/sms
```
当前 `Provider` 只支持登录验证码:
```go
SendLoginCode(ctx context.Context, phone string, code string) error
```
主动短信需要扩展为模板短信能力,例如:
```go
SendTemplate(ctx context.Context, phone string, templateCode string, params map[string]string) error
```
阿里云短信实际发送不能随意拼接任意文案,必须使用已审核的短信模板。因此后台可配置“模板 code、奖励规则、预览文案”,真实发送时只传模板变量。
### 后台配置
使用 `system_configs`,新增配置项:
```text
sms.rental_completion_reminder
```
建议默认值:
```json
{
"enabled": false,
"brand_name": "大锤商行",
"template_code": "",
"monthly_user_limit": 4,
"cooldown_hours": 24,
"rewards": [
{ "target_orders": 3, "reward_name": "成长礼包", "enabled": true },
{ "target_orders": 5, "reward_name": "专属优惠券", "enabled": true }
],
"preview_template": "尊敬的 {{nickname}}:您好,您已经在 {{brand_name}} 累计完成 {{completed_count}} 笔租号订单,再完成 {{remaining_count}} 笔即可领取 {{reward_name}}。"
}
```
规则说明:
- `enabled`:总开关。
- `brand_name`:短信里展示的品牌名。
- `template_code`:阿里云审核通过的营销或通知短信模板 code。
- `monthly_user_limit`:单用户单月最多发送次数。
- `cooldown_hours`:同一用户两次主动短信最小间隔。
- `rewards`:奖励门槛,从小到大配置。
- `preview_template`:后台预览使用,真实发送以短信供应商模板为准。
计算 `x` 的规则:
1. 获取用户本月完成租号订单数 `completed_count`
2. 找到第一个 `target_orders > completed_count` 的奖励。
3. `remaining_count = target_orders - completed_count`
4. 如果没有下一个奖励,默认不发送,或后续配置为发送达成提醒。
### 数据库表
建议新增短信发送记录表:
```text
sms_messages
```
字段建议:
- `id`
- `user_id`
- `phone`
- `biz_type`:例如 `rental_completion_reminder`
- `biz_id`:租号订单 ID。
- `template_code`
- `template_params`
- `content_preview`
- `status``pending``sent``failed``cancelled`
- `retry_count`
- `last_error`
- `sent_at`
- `created_at`
- `updated_at`
建议加唯一索引:
```text
uk_sms_messages_biz_type_biz_id_user
```
用于保证同一笔完成订单不会重复创建短信任务。
### 发送任务
新增后台任务,例如:
```text
backend/internal/jobs/smsdispatch
```
任务逻辑:
1. 查询 `pending` 且重试次数未超限的短信。
2. 调用短信 provider 发送模板短信。
3. 成功后标记 `sent`,写 `sent_at`
4. 失败后记录 `last_error`,增加 `retry_count`
5. 超过最大重试次数后标记 `failed`
### 限流与防打扰
发送前需要校验:
- 系统配置已启用。
- 用户手机号有效。
- 本订单尚未创建过同类短信。
- 用户本月主动短信次数未超过 `monthly_user_limit`
- 用户距离上次主动短信超过 `cooldown_hours`
- 找得到下一个奖励门槛。
第一版可以先不做用户退订,但如果短信属于营销性质,建议后续加用户短信订阅状态或退订名单。
### 前端范围
后台系统配置页:
- 开关。
- 品牌名。
- 模板 code。
- 单用户月发送上限。
- 冷却时间。
- 奖励门槛和奖励名称。
- 文案预览。
后台短信记录页可以作为二期,第一版可先通过数据库和日志排查。
### 测试范围
- 租号订单完成后创建短信待发送记录。
- 撞车订单完成不创建短信。
- 本月完成订单数统计正确。
- 根据奖励门槛计算 `remaining_count` 正确。
- 找不到下一奖励时不发送。
- 单用户月上限生效。
- 冷却时间生效。
- 同一订单不会重复创建短信任务。
- 短信发送失败不影响订单完成。