Enhance smoking tracking features with AI next smoke time suggestions
- Added new API endpoint `GET /api/v1/smoke/next_smoke_time` to provide AI-generated suggestions for the next smoking time based on user data. - Introduced a new database table `fa_smoke_ai_next_smoke` to store structured AI time node suggestions. - Updated smoke handler and service to integrate the new AI next smoke time functionality. - Enhanced documentation to reflect the new API endpoint and its usage, including details on how to generate AI time nodes.
This commit is contained in:
+95
-2
@@ -22,7 +22,8 @@
|
||||
说明:
|
||||
- `smoke_time` 可选;不传则默认“当天”。
|
||||
- `smoke_at` 可选;真实抽烟时间(格式 `YYYY-MM-DD HH:MM:SS`)。用于“按时间节点分析/AI 建议”;不传则可用 `createtime` 近似。
|
||||
- `level/num` 可选;不传或传 `<=0` 时会按 `1` 处理。
|
||||
- `level/num` 可选;不传时后端会按 `1` 处理。
|
||||
- 如果要记录“想抽但忍住了”,请传 `level=0` 且 `num=0`(会在 `fa_smoke_log` 中展示为一条记录,但不会影响看板的支数累加)。
|
||||
|
||||
curl 示例:
|
||||
|
||||
@@ -120,7 +121,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
|
||||
|
||||
字段说明:
|
||||
- `today_count`:当天吸烟总支数(累加 `num`)
|
||||
- `minutes_since_last`:距最后一次抽烟的分钟数,通过最近一条 `smoke_at/smoke_time/createtime` 计算;若历史为空则字段不存在
|
||||
- `minutes_since_last`:距最后一次“实际抽烟”(忽略 `level=0 && num=0` 的忍住记录)的分钟数,通过最近一条 `smoke_at/smoke_time/createtime` 计算;若历史为空则字段不存在
|
||||
- `weekly`:起止日期内每日汇总,`count` 为当日总支数,`is_today` 标记当前日期(即便不在 `start/end` 范围内也会标记为 `false`)
|
||||
|
||||
## 5) 最近记录列表(轻量版)
|
||||
@@ -237,6 +238,8 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
|
||||
说明:
|
||||
- 该接口用于记录“已完成观看广告”,落库到 `fa_smoke_ai_advice_unlocks`(`uid + unlock_date` 唯一)。
|
||||
- `ad_watched_at` 可由后端取当前时间;如需审计/对账可保留前端上报并做校验。
|
||||
- 解锁是“按天”的:观看一次广告解锁一天内的 AI 生成功能(可用于「每日 AI 建议」以及「AI 下次抽烟时间节点」)。
|
||||
- 如果你要生成“明天”的 AI 时间节点,请把 `date` 传为明天日期(例如 `2026-01-06`)。
|
||||
|
||||
## 10) 获取用户基础信息(首次进入:判断是否需要补全)
|
||||
|
||||
@@ -321,3 +324,93 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
|
||||
```
|
||||
|
||||
成功响应:同 `GET /api/v1/smoke/profile`(返回最新 `profile` + `is_completed` + `baseline_interval_minutes`)。
|
||||
|
||||
## 12) 想抽但忍住了(写入一条 level=0,num=0 的记录)
|
||||
|
||||
`POST /api/v1/smoke/logs/resisted`
|
||||
|
||||
请求体(示例):
|
||||
```json
|
||||
{
|
||||
"smoke_time": "2026-01-05",
|
||||
"smoke_at": "2026-01-05 10:20:00",
|
||||
"remark": "压力大,想抽但忍住了"
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
- 该接口会在 `fa_smoke_log` 中新增一条记录:`level=0` 且 `num=0`,用于更直观记录“想抽/忍住”的过程。
|
||||
- 这类记录不会影响 `today_count/weekly.count` 的支数统计(因为 `num=0`)。
|
||||
|
||||
## 13) 获取“下次抽烟记录时间”(默认 + AI 自动切换)
|
||||
|
||||
`GET /api/v1/smoke/next_smoke_time`
|
||||
|
||||
说明:
|
||||
- 用于首页展示“建议的下次记录时间”。
|
||||
- 如果指定日期存在 AI 给出的时间节点(`time_nodes` 不为空),则优先使用 AI 的建议;否则使用默认策略。
|
||||
- 可选参数:
|
||||
- `date`:计划日期(默认今天),支持 `YYYY-MM-DD` 或 `today/tomorrow`。
|
||||
- `mode`(默认 `auto`)
|
||||
- `auto`:只在已存在 AI 时间节点时使用 AI(不主动生成)
|
||||
- `ai`:生成该 `date` 的 AI 时间节点(需要先看广告解锁;生成一次缓存一天)
|
||||
- `default`:永远返回默认策略
|
||||
|
||||
默认策略(不使用 AI):
|
||||
- 基础间隔:优先使用 `GET /api/v1/smoke/profile` 返回的 `baseline_interval_minutes`;若不存在则默认 `60` 分钟。
|
||||
- 阶梯式延时:最近 7 天内每累计 `5` 条“忍住记录(level=0,num=0)”,在基础间隔上 `+5` 分钟(最多 `+60` 分钟)。
|
||||
- 若用户已补全作息时间,会自动规避睡眠区间:若计算出的时间落在睡眠区间,顺延到下一次起床时间。
|
||||
|
||||
AI 生成说明:
|
||||
- 当 `mode=ai` 时,会把最近 3 天的抽烟数据(含“忍住记录”)作为输入提供给 AI,用于更贴合近期模式生成时间节点。
|
||||
- 未解锁时会返回 `403`:提示需要观看广告解锁。
|
||||
|
||||
成功响应(示例:回落到默认):
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"source": "default",
|
||||
"not_before_at": "2026-01-05T10:18:00+08:00",
|
||||
"suggested_at": "2026-01-05T10:18:00+08:00",
|
||||
"default": {
|
||||
"last_smoke_at": "2026-01-05T09:30:00+08:00",
|
||||
"next_smoke_at": "2026-01-05T10:18:00+08:00",
|
||||
"base_interval_minutes": 48,
|
||||
"interval_minutes": 48,
|
||||
"stage": 0,
|
||||
"resisted_7d": 3,
|
||||
"sleep_adjusted": false,
|
||||
"algorithm": "staircase_delay_v1",
|
||||
"as_of": "2026-01-05T10:00:00+08:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当存在 AI 建议且包含 `time_nodes` 时,响应会是(示例):
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"source": "ai",
|
||||
"not_before_at": "2026-01-05T10:18:00+08:00",
|
||||
"suggested_at": "2026-01-05T10:28:00+08:00",
|
||||
"time_nodes": ["10:30", "11:10", "14:00", "16:30"],
|
||||
"advice": "先把这次冲动延后到10:28,期间做一次5分钟快走+喝水,压力场景用深呼吸替代。",
|
||||
"default": { "algorithm": "staircase_delay_v1" },
|
||||
"ai": {
|
||||
"plan_date": "2026-01-05",
|
||||
"not_before_at": "2026-01-05T10:18:00+08:00",
|
||||
"suggested_at": "2026-01-05T10:28:00+08:00",
|
||||
"time_nodes": ["10:30", "11:10", "14:00", "16:30"],
|
||||
"advice": "先把这次冲动延后到10:28,期间做一次5分钟快走+喝水,压力场景用深呼吸替代。",
|
||||
"prompt_version": "v1",
|
||||
"model": "gpt-4.1-mini",
|
||||
"provider": "openai-compatible"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user