diff --git a/docs/ALGORITHM.md b/docs/ALGORITHM.md
index 4b54bb5..30ea753 100644
--- a/docs/ALGORITHM.md
+++ b/docs/ALGORITHM.md
@@ -21,7 +21,7 @@
| 参数 | 来源 | 默认值 | 说明 |
|------|------|--------|------|
-| base_interval | profile.baseline_interval_minutes | 60 分钟 | 用户初始平均抽烟间隔 |
+| base_interval | profile.baseline_interval_minutes | 60 分钟 | 用户初始平均抽烟间隔(为空/0 时默认 60) |
| resisted_7d | 近7天忍住次数 | 0 | level=0,num=0 的记录数 |
| bonus_interval | 计算得出 | 0 | 奖励延长时间 |
@@ -31,7 +31,7 @@
```
bonus_interval = min(floor(resisted_7d / 5) * 5, 60)
-final_interval = base_interval + bonus_interval
+final_interval = clamp(base_interval + bonus_interval, 5, 240)
```
**示例**:
@@ -41,17 +41,22 @@ final_interval = base_interval + bonus_interval
### 2.4 睡眠规避
-若计算出的时间落在睡眠区间,顺延到次日起床时间:
+若计算出的时间落在睡眠区间,顺延到**下一次**起床时间(可能是当天也可能是次日):
```
if suggested_time in [sleep_time, wake_up_time]:
suggested_time = next_day_wake_up_time
```
-### 2.5 算法流程图
+### 2.5 边界与兜底
+
+- 若没有历史记录,则以“当前时间”作为 `last_smoke_at` 参与计算。
+- 若生成未来日期计划(如明天),默认建议不早于该日起床时间;未配置作息时按 `07:00` 处理。
+
+### 2.6 算法流程图
```
-获取上次抽烟时间 (last_smoke_at)
+获取上次抽烟时间 (last_smoke_at, 若无记录则取当前时间)
↓
获取用户基础间隔 (base_interval_minutes)
↓
@@ -59,7 +64,7 @@ if suggested_time in [sleep_time, wake_up_time]:
↓
计算奖励间隔: bonus = min(floor(resisted_7d / 5) * 5, 60)
↓
-计算建议时间: suggested = last_smoke_at + base + bonus
+计算建议时间: suggested = last_smoke_at + base + bonus (并限制在 5~240 分钟区间)
↓
检查是否在睡眠时间?
├── 是 → 顺延到起床时间
@@ -91,20 +96,14 @@ if suggested_time in [sleep_time, wake_up_time]:
### 3.2 AI 建议内容
-AI 会生成以下内容:
+AI 会生成以下内容(实际接口格式):
```json
{
- "advice": "昨天你的吸烟量比限额少了2支,这是一个巨大的胜利!数据显示你的烟瘾在下午2点左右达到顶峰——今天试着那个时候去散散步。",
- "time_nodes": [
- { "time": "09:30", "type": "suggested", "note": "第一支,早餐后" },
- { "time": "12:30", "type": "suggested", "note": "午餐后" },
- { "time": "15:30", "type": "suggested", "note": "下午茶时间" },
- { "time": "19:00", "type": "suggested", "note": "晚餐后" },
- { "time": "22:00", "type": "suggested", "note": "睡前最后一支" }
- ],
- "daily_target": 5,
- "tips": ["2点是你的高峰期,准备一颗薄荷糖", "试着用深呼吸替代"]
+ "not_before_at": "2026-01-05T10:18:00+08:00",
+ "suggested_at": "2026-01-05T10:28:00+08:00",
+ "time_nodes": ["09:30", "12:30", "15:30", "19:00", "22:00"],
+ "advice": "昨天你的吸烟量比限额少了2支,这是一个巨大的胜利!数据显示你的烟瘾在下午2点左右达到顶峰——今天试着那个时候去散散步。"
}
```
@@ -299,6 +298,7 @@ function getMotivationMessage(context) {
| 忍住成功率 | 忍住次数 / (忍住+抽烟次数) | 意志力评估 |
| 平均间隔 | 总时长 / 抽烟次数 | 递减效果 |
| 最长无烟时长 | 最大间隔记录 | 成就激励 |
+| 较昨日减少 | 昨日支数 - 今日支数(可为负) | 若为负,表示今天超出昨日 |
### 8.2 周报数据结构
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
deleted file mode 100644
index 72af959..0000000
--- a/docs/DEVELOPMENT.md
+++ /dev/null
@@ -1,922 +0,0 @@
-# 开发计划与任务拆分
-
-## 1. 开发阶段概览
-
-```
-Phase 1: 基础框架搭建 (2天)
- ↓
-Phase 2: 首页核心功能 (3天) ★ 优先保证首页体验
- ↓
-Phase 3: 记录与历史 (2天)
- ↓
-Phase 4: 统计与图表 (2天)
- ↓
-Phase 5: AI助手与个人中心 (3天)
- ↓
-Phase 6: 优化与测试 (2天)
-```
-
----
-
-## 2. Phase 1: 基础框架搭建 (2天)
-
-### 2.1 项目初始化
-- [ ] 创建 uni-app 项目 (Vue3 + JavaScript)
-- [ ] 配置路径别名 (@/)
-- [ ] 创建目录结构
-
-### 2.2 基础配置
-- [ ] 配置 pages.json (页面路由 + TabBar)
-- [ ] 配置全局样式 (暗色主题变量)
-- [ ] 配置环境变量 (开发/生产 API 地址)
-
-### 2.3 核心模块
-- [ ] 封装 request.js (请求拦截、Token管理、错误处理)
-- [ ] 封装 storage.js (本地存储工具)
-- [ ] 配置 Pinia stores 结构
-- [ ] 实现登录流程 (wx.login + 后端认证)
-
-### 2.4 公共组件
-- [ ] 创建 Loading 组件
-- [ ] 创建 Skeleton 骨架屏组件
-- [ ] 创建 Button 组件 (主按钮/次按钮样式)
-- [ ] 创建 Card 组件 (卡片容器)
-
-**交付物**:可运行的空白项目,登录功能正常
-
----
-
-## 3. Phase 2: 首页核心功能 (3天) ★
-
-> ⚠️ 首页是用户最常访问的页面,必须保证 < 500ms 首屏渲染
-
-### 3.1 Day 1: 页面结构 + 数据层
-
-#### API 封装
-- [ ] `api/smoke.js`: getDashboard()
-- [ ] `api/smoke.js`: getNextSmokeTime()
-- [ ] `api/profile.js`: getProfile()
-
-#### Store 设计
-- [ ] `stores/dashboard.js`: 看板数据 + 缓存逻辑
-- [ ] `stores/user.js`: 用户信息 + 登录状态
-
-#### 页面结构
-- [ ] 首页骨架屏
-- [ ] 页面布局 (header + timer + cards + buttons)
-
-### 3.2 Day 2: 核心组件
-
-#### 计时器组件 (TimerRing)
-- [ ] Canvas 绘制进度环
-- [ ] 时间格式化 (HH:MM:SS)
-- [ ] requestAnimationFrame 优化
-- [ ] 页面可见性处理 (切后台暂停)
-
-#### 统计卡片
-- [ ] 今日已抽卡片 (X/目标, 较昨日±N)
-- [ ] 烟瘾发作已抵抗卡片
-
-#### 快捷按钮
-- [ ] 记录抽烟按钮 → 弹出记录表单
-- [ ] 想抽忍住了按钮 → 快速提交
-
-### 3.3 Day 3: 交互 + 优化
-
-#### AI 提示卡片
-- [ ] 延迟加载 (300ms后)
-- [ ] 可关闭 (本地存储关闭状态)
-- [ ] 下次建议时间显示
-
-#### 性能优化
-- [ ] 并行请求优化
-- [ ] 骨架屏过渡动画
-- [ ] 首屏性能埋点
-
-#### 新用户引导
-- [ ] 检测 profile.exists
-- [ ] 跳转引导页逻辑
-
-**交付物**:完整可用的首页,首屏 < 500ms
-
----
-
-## 4. Phase 3: 记录与历史 (2天)
-
-### 4.1 Day 1: 记录表单组件
-
-#### 4.1.1 smoke-record-dialog 组件开发
-
-**组件结构** (`components/smoke-record-dialog/smoke-record-dialog.vue`)
-- [x] 底部弹出动画 (从底部滑入,半屏展示)
-- [x] 明亮主题 UI (白色背景 + 翡翠绿主题色 #10B981)
-- [x] 遮罩层点击关闭
-- [x] 表单项布局
-
-**表单字段实现**
-- [x] 时间选择器
- - 日期选择 (picker mode="date")
- - 时间选择 (picker mode="time")
- - 默认当前时间
- - 自动拼接为 `smoke_at` 字段
-
-- [x] 数量选择器 (仅抽烟模式显示)
- - 加减按钮 (+/-)
- - 数字输入框
- - 最小值 1
- - 默认值 1
-
-- [x] 烟瘾等级选择 (仅抽烟模式显示)
- - 1-5 级按钮组
- - 选中态样式切换
- - 默认值 2
-
-- [x] 备注输入框
- - 多行文本域 (textarea)
- - 最大长度 200 字符
- - 根据模式显示不同占位符
- - 抽烟: "记录抽烟原因..."
- - 忍住: "记录抵抗心得..."
-
-**组件逻辑**
-- [x] Props 定义
- ```javascript
- {
- show: Boolean, // 控制显示
- type: String // 'smoke' | 'resisted'
- }
- ```
-
-- [x] 数据初始化
- - 打开弹框时自动初始化当前时间
- - 根据 type 设置默认值
- - smoke: num=1, level=2
- - resisted: num=0, level=2
-
-- [x] 提交逻辑
- ```javascript
- {
- smoke_time: "2025-01-25",
- smoke_at: "2025-01-25 14:30:00",
- remark: "",
- level: 2,
- num: 1 // 或 0 (忍住时)
- }
- ```
-
-- [x] 关闭动画
- - 延迟 300ms 触发 update:show
- - 平滑过渡效果
-
-#### 4.1.2 组件配置
-
-**easycom 自动导入** (`pages.json`)
-- [x] 配置组件路径
- ```json
- {
- "easycom": {
- "autoscan": true,
- "custom": {
- "^smoke-record-dialog$": "@/components/smoke-record-dialog/smoke-record-dialog.vue"
- }
- }
- }
- ```
-
-**组件文档**
-- [x] 创建 `components/smoke-record-dialog/README.md`
-- [x] 包含使用示例、Props 说明、Events 说明
-- [x] 创建 `components/README.md` 全局组件使用指南
-
-#### 4.1.3 API 集成
-
-**API 封装** (`api/smoke.js`)
-- [x] `createLog(data)` - POST /api/v1/smoke/logs
- - 支持抽烟记录 (num > 0)
- - 支持忍住记录 (num = 0, level = 0)
-
-- [ ] `updateLog(id, data)` - PUT /api/v1/smoke/logs/:id
-- [ ] `deleteLog(id)` - DELETE /api/v1/smoke/logs/:id
-- [x] `getLatestLogs(limit)` - GET /api/v1/smoke/logs/latest
-
-**首页集成** (`pages/index/index.vue`)
-- [x] 引入组件 (easycom 自动导入)
-- [x] 双向绑定 show 状态
-- [x] 区分两种模式
- ```vue
-
- ```
-
-- [x] 提交处理
- - 调用 API 创建记录
- - 更新 dashboard store 数据
- - 抽烟: incrementTodayCount()
- - 抽烟: resetTimer()
- - 显示成功提示
- - 关闭弹框
-
-**性能优化**
-- [x] 组件懒加载 (easycom 按需加载)
-- [x] 表单数据仅在打开时初始化
-- [x] 提交后自动关闭
-
----
-
-### 4.2 Day 2: 历史记录页
-
-#### 4.2.1 页面结构 (`pages/logs/index.vue`)
-
-**顶部导航**
-- [ ] 导航栏标题 "历史记录"
-- [ ] 筛选 Tabs 组件
- ```javascript
- tabs: [
- { id: 'all', name: '全部' },
- { id: 'smoke', name: '已抽烟', filter: (item) => item.num > 0 },
- { id: 'resisted', name: '已忍住', filter: (item) => item.num === 0 }
- ]
- ```
-
-**列表容器**
-- [ ] scroll-view 组件
-- [ ] 下拉刷新 (refresher-enabled)
-- [ ] 上拉加载更多
-- [ ] 空状态提示
-
-#### 4.2.2 数据层
-
-**Store 设计** (`stores/logs.js`)
-```javascript
-{
- state: {
- logs: [], // 记录列表
- total: 0, // 总条数
- page: 1, // 当前页
- pageSize: 20, // 每页数量
- hasMore: true, // 是否有更多
- loading: false // 加载状态
- },
-
- getters: {
- groupedByDate: (state) => {
- // 按日期分组
- // { '2025-01-25': [...], '2025-01-24': [...] }
- },
- smokeCount: (state) => {
- // 抽烟记录数量
- },
- resistedCount: (state) => {
- // 忍住记录数量
- }
- },
-
- actions: {
- async fetchLogs(refresh = false),
- async loadMore(),
- async deleteLog(id),
- clearLogs()
- }
-}
-```
-
-**API 调用**
-- [ ] `getLogs({ page, page_size, start, end })`
-- [ ] `getLatestLogs(limit)` - 首次快速加载
-- [ ] `deleteLog(id)`
-
-#### 4.2.3 记录卡片组件 (`components/log-item/log-item.vue`)
-
-**卡片布局**
-```
-┌─────────────────────────────────────┐
-│ 🚬 14:30 3 支 │
-│ 压力大、工作繁忙 │
-│ 距上次 2小时15分 │
-└─────────────────────────────────────┘
-```
-
-**字段显示**
-- [ ] 类型图标
- - 🚬 抽烟 (num > 0)
- - 💪 忍住 (num = 0)
-
-- [ ] 时间显示
- - 格式: HH:mm
- - 今天/昨天/具体日期
-
-- [ ] 数量显示 (抽烟时)
- - `${num} 支`
- - 烟瘾等级 (1-5 级)
-
-- [ ] 备注内容
- - 单行显示,超出省略
- - 最多显示 50 字符
-
-- [ ] 间隔时间
- - 距上一条记录的时间差
- - 格式: "X小时Y分" / "X分钟"
-
-**卡片样式**
-- [ ] 白色背景
-- [ ] 圆角 16rpx
-- [ ] 阴影效果
-- [ ] 抽烟/忍住不同边框色
- - 抽烟: 红色左边框
- - 忍住: 绿色左边框
-
-#### 4.2.4 左滑操作
-
-**左滑按钮**
-- [ ] 使用 uni-ui 的 uni-swipe-action
-- [ ] 编辑按钮 (蓝色)
- - 打开编辑弹框
- - 预填充当前数据
-
-- [ ] 删除按钮 (红色)
- - 显示确认对话框
- - 调用删除 API
- - 更新列表数据
-
-**编辑功能**
-- [ ] 复用 smoke-record-dialog 组件
-- [ ] 添加 recordId 和 mode props
- ```vue
-
- ```
-
-- [ ] 预填充数据
-- [ ] 调用 updateLog API
-- [ ] 刷新列表
-
-**删除功能**
-- [ ] uni.showModal 确认对话框
-- [ ] 调用 deleteLog API
-- [ ] 乐观更新 (先删除本地数据)
-- [ ] 失败时回滚
-
-#### 4.2.5 日期分组
-
-**分组逻辑**
-```javascript
-function groupByDate(logs) {
- const groups = {}
- logs.forEach(log => {
- const date = formatDate(log.smoke_time)
- if (!groups[date]) {
- groups[date] = {
- date,
- displayDate: getDisplayDate(date), // 今天/昨天/MM-DD
- logs: []
- }
- }
- groups[date].logs.push(log)
- })
- return Object.values(groups)
-}
-```
-
-**渲染结构**
-```vue
-
-
-
-
-```
-
-#### 4.2.6 加载状态
-
-**下拉刷新**
-- [ ] refresher-triggered 状态控制
-- [ ] 重置 page = 1
-- [ ] 清空现有数据
-- [ ] 调用 fetchLogs(true)
-- [ ] 完成后关闭刷新状态
-
-**上拉加载**
-- [ ] onReachBottom 触发
-- [ ] 检查 hasMore 状态
-- [ ] page++
-- [ ] 调用 loadMore()
-- [ ] 追加数据到列表
-
-**加载骨架屏**
-- [ ] 初次加载显示
-- [ ] 3-5 个卡片骨架
-- [ ] shimmer 动画效果
-
-**空状态**
-- [ ] 无数据时显示
-- [ ] 空状态图标 + 文案
-- [ ] 引导按钮 "去记录"
-
-#### 4.2.7 浮动操作按钮
-
-**新增按钮**
-- [ ] 固定在右下角
-- [ ] 圆形按钮 (96rpx)
-- [ ] ➕ 图标
-- [ ] 点击打开记录弹框
-- [ ] 阴影 + 缩放动画
-
-**样式**
-```css
-.fab {
- position: fixed;
- right: 32rpx;
- bottom: 120rpx; /* 避开 tabbar */
- width: 96rpx;
- height: 96rpx;
- background: #10B981;
- border-radius: 50%;
- box-shadow: 0 8rpx 24rpx rgba(16, 185, 129, 0.4);
-}
-```
-
-#### 4.2.8 性能优化
-
-**列表优化**
-- [ ] 虚拟列表 (数据量 > 100 时)
-- [ ] 分页加载 (每页 20 条)
-- [ ] 图片懒加载 (如有头像等)
-
-**缓存策略**
-- [ ] 首次加载使用 getLatestLogs (快速)
-- [ ] 后续使用分页接口
-- [ ] 缓存最近 3 页数据
-- [ ] 超过 5 分钟刷新缓存
-
-**用户体验**
-- [ ] 乐观更新 (删除/编辑)
-- [ ] Loading 状态提示
-- [ ] 错误处理 + 重试按钮
-- [ ] 防抖处理 (下拉刷新/上拉加载)
-
----
-
-### 4.3 验收标准
-
-**记录功能**
-- [x] 弹框动画流畅 (< 300ms)
-- [x] 表单提交成功率 > 99%
-- [x] 支持快速记录 (< 3 步)
-- [ ] 编辑/删除操作正常
-
-**历史记录页**
-- [ ] 列表加载 < 1s
-- [ ] 滚动流畅 (60fps)
-- [ ] 分组显示正确
-- [ ] 筛选功能正常
-- [ ] 下拉刷新/上拉加载正常
-
-**数据同步**
-- [ ] 新增记录后首页数据实时更新
-- [ ] 删除记录后列表实时更新
-- [ ] 编辑记录后详情实时更新
-
-**异常处理**
-- [ ] 网络异常提示
-- [ ] 删除失败回滚
-- [ ] 空状态正确显示
-
-**交付物**:
-- ✅ smoke-record-dialog 组件 (已完成)
-- ✅ 组件文档和使用指南 (已完成)
-- ✅ 首页记录功能集成 (已完成)
-- [ ] 历史记录页完整功能
-- [ ] log-item 组件
-- [ ] logs store 状态管理
-- [ ] 编辑/删除功能
-
----
-
-### 4.4 Phase 3 技术要点与最佳实践
-
-#### 4.4.1 组件设计原则
-
-**组件命名规范**
-- ✅ 使用 kebab-case: `smoke-record-dialog`
-- ✅ 目录结构: `components/smoke-record-dialog/smoke-record-dialog.vue`
-- ❌ 避免 PascalCase: `SmokeRecordDialog.vue` (微信小程序依赖分析问题)
-
-**组件 API 风格**
-- ✅ 使用 Options API (更好的兼容性)
-- ✅ 支持 v-model:show 双向绑定
-- ✅ 使用 @submit 事件传递数据
-- ✅ Props 类型校验完整
-
-**组件复用性**
-- 通过 props.type 区分模式 ('smoke' / 'resisted')
-- 表单字段根据模式动态显示/隐藏
-- 提交数据格式统一,由组件内部处理差异
-
-#### 4.4.2 状态管理策略
-
-**Store 职责划分**
-```javascript
-// dashboard.js - 首页数据
-{
- todayCount, // 今日抽烟数
- minutesSinceLast, // 距上次时间
- nextSmokeTime, // 下次建议时间
- actions: {
- incrementTodayCount(),
- resetTimer()
- }
-}
-
-// logs.js - 历史记录
-{
- logs, // 记录列表
- page, total, hasMore, // 分页信息
- actions: {
- fetchLogs(),
- loadMore(),
- deleteLog()
- }
-}
-
-// user.js - 用户信息
-{
- user, // 用户基本信息
- token, // 认证令牌
- isLogin // 登录状态
-}
-```
-
-**数据流向**
-```
-用户操作 → 组件 emit → 页面处理 → 调用 API
- ↓
- 更新 Store ← API 响应
- ↓
- 触发视图更新
-```
-
-#### 4.4.3 API 错误处理
-
-**统一错误处理** (`api/request.js`)
-```javascript
-// 已实现
-- Token 失效自动刷新
-- 网络错误重试 (最多 3 次)
-- 错误码统一处理
-- Toast 提示
-
-// 需要注意
-- 记录提交失败要保留用户输入
-- 删除失败要回滚本地状态
-- 编辑冲突要提示用户
-```
-
-**乐观更新 vs 悲观更新**
-- 删除操作: 乐观更新 (先删除,失败回滚)
-- 新增操作: 悲观更新 (成功后添加)
-- 编辑操作: 悲观更新 (成功后更新)
-
-#### 4.4.4 性能优化清单
-
-**组件层面**
-- [x] easycom 按需加载
-- [x] 弹框懒加载 (打开时才初始化数据)
-- [ ] 虚拟列表 (历史记录 > 100 条)
-- [ ] 图片懒加载
-
-**请求层面**
-- [ ] 并行请求 (多个接口同时调用)
-- [ ] 请求缓存 (5 分钟内复用)
-- [ ] 防抖处理 (快速点击)
-- [ ] 请求取消 (页面离开时)
-
-**渲染层面**
-- [ ] 分页加载 (每页 20 条)
-- [ ] 骨架屏过渡
-- [ ] 平滑滚动
-- [ ] 动画性能优化 (CSS transform)
-
-#### 4.4.5 用户体验优化
-
-**反馈机制**
-- 提交成功: Toast 提示 + 自动关闭弹框
-- 提交失败: Toast 提示 + 保留输入内容
-- 删除确认: Modal 二次确认
-- 加载状态: Loading + 禁用按钮
-
-**快捷操作**
-- 首页快速记录按钮 (2 个按钮对应 2 种模式)
-- 历史记录页浮动新增按钮
-- 左滑快速删除/编辑
-- 下拉刷新快速更新
-
-**引导提示**
-- 首次使用引导
-- 空状态引导
-- 错误状态引导
-- 功能提示
-
-#### 4.4.6 测试要点
-
-**单元测试**
-- [ ] 组件 props 验证
-- [ ] 表单数据初始化
-- [ ] 日期分组逻辑
-- [ ] 时间格式化函数
-
-**集成测试**
-- [ ] 记录提交流程
-- [ ] 编辑/删除流程
-- [ ] 分页加载流程
-- [ ] 筛选切换流程
-
-**E2E 测试场景**
-```
-场景 1: 快速记录抽烟
-1. 点击"记录抽烟"按钮
-2. 不修改默认值
-3. 直接提交
-4. 验证首页数据更新
-
-场景 2: 详细记录
-1. 点击"记录抽烟"按钮
-2. 修改时间、数量、等级
-3. 输入备注
-4. 提交
-5. 在历史记录页验证
-
-场景 3: 编辑记录
-1. 进入历史记录页
-2. 左滑某条记录
-3. 点击编辑
-4. 修改内容
-5. 提交
-6. 验证更新成功
-
-场景 4: 删除记录
-1. 进入历史记录页
-2. 左滑某条记录
-3. 点击删除
-4. 确认删除
-5. 验证列表更新
-```
-
-#### 4.4.7 常见问题与解决方案
-
-**问题 1: 微信小程序组件依赖分析错误**
-```
-错误: components/SmokeRecordDialog.js 已被代码依赖分析忽略
-解决:
-1. 使用 kebab-case 命名
-2. 组件放在同名文件夹内
-3. 配置 easycom 自动导入
-4. 使用 Options API
-```
-
-**问题 2: 弹框关闭时数据未重置**
-```
-原因: 组件销毁前未清理数据
-解决: watch show 变化,false 时清理数据
-```
-
-**问题 3: 列表滚动性能差**
-```
-原因: 数据量大,DOM 节点过多
-解决:
-1. 虚拟列表
-2. 分页加载
-3. 使用 CSS transform 优化动画
-```
-
-**问题 4: 删除后列表显示错误**
-```
-原因: 本地状态未同步
-解决: 乐观更新时正确处理索引
-```
-
-#### 4.4.8 安全注意事项
-
-**输入校验**
-- 时间范围验证 (不能是未来时间)
-- 数量范围验证 (1-99)
-- 备注长度限制 (200 字符)
-- XSS 防护 (转义用户输入)
-
-**权限控制**
-- 只能编辑/删除自己的记录
-- Token 验证
-- 接口鉴权
-
-**数据保护**
-- 敏感信息脱敏
-- 本地存储加密
-- HTTPS 传输
-
----
-
-## 5. Phase 4: 统计与图表 (2天)
-
-### 5.1 Day 1: 统计页基础
-
-#### 时间范围切换
-- [ ] 周/月/年 Tabs
-- [ ] 日期范围计算
-- [ ] 数据请求 (`GET /dashboard?start=&end=`)
-
-#### 吸烟趋势图
-- [ ] 集成 uCharts / ECharts
-- [ ] 柱状图组件封装
-- [ ] 数据格式转换
-
-#### 每周洞察卡片
-- [ ] AI 分析展示 (异步加载)
-
-### 5.2 Day 2: 详细指标
-
-#### 健康与储蓄卡片
-- [ ] 节省金额计算 + 环形进度
-- [ ] 肺部功能恢复 + 环形进度
-
-#### 成就卡片
-- [ ] 连续记录天数
-- [ ] 已拒绝次数
-
-#### 趋势对比
-- [ ] 周同比变化计算
-- [ ] 日均吸烟量
-
-**交付物**:完整的统计页,图表正常显示
-
----
-
-## 6. Phase 5: AI助手与个人中心 (3天)
-
-### 6.1 Day 1: AI 助手页
-
-#### 阶段进度卡片
-- [ ] 阶段计算逻辑
-- [ ] 进度条展示
-- [ ] 天数倒计时
-
-#### 每日 AI 分析
-- [ ] 对话式 UI
-- [ ] `GET /ai/advice` 集成
-- [ ] 会员/广告解锁判断
-
-#### 今日目标
-- [ ] 任务列表
-- [ ] 完成状态切换 (本地存储)
-
-### 6.2 Day 2: 个人中心页
-
-#### 用户信息
-- [ ] 头像 + 昵称展示
-- [ ] 目标戒烟日期
-- [ ] 连续天数
-
-#### 设置项
-- [ ] 目标设定入口
-- [ ] AI 计划调整入口
-- [ ] 通知设置
-- [ ] 会员解锁
-
-#### 基础设置
-- [ ] 作息时间设置
-- [ ] 每包价格设置
-
-### 6.3 Day 3: 新用户引导
-
-#### 引导页面
-- [ ] 分步表单 (5步)
-- [ ] 进度指示器
-- [ ] 动画过渡
-
-#### 数据收集
-- [ ] 日均吸烟量
-- [ ] 烟龄
-- [ ] 抽烟/戒烟动机
-- [ ] 作息时间
-
-#### 提交流程
-- [ ] `PUT /profile` 提交
-- [ ] 完成后跳转首页
-
-**交付物**:AI助手页、个人中心页、引导流程完整
-
----
-
-## 7. Phase 6: 优化与测试 (2天)
-
-### 7.1 Day 1: 性能优化
-
-#### 首页优化
-- [ ] 首屏时间 < 500ms 验证
-- [ ] 图片懒加载
-- [ ] 组件按需加载
-
-#### 缓存优化
-- [ ] 请求缓存策略检查
-- [ ] 本地存储清理策略
-
-#### 包体积
-- [ ] 依赖分析
-- [ ] 无用代码移除
-- [ ] 分包加载配置
-
-### 7.2 Day 2: 测试与修复
-
-#### 功能测试
-- [ ] 全流程测试 (新用户 → 日常使用)
-- [ ] 边界情况测试
-- [ ] 网络异常测试
-
-#### UI 适配
-- [ ] 不同机型测试
-- [ ] 安全区域适配
-
-#### Bug 修复
-- [ ] 测试问题修复
-- [ ] 体验优化
-
-**交付物**:可发布的小程序版本
-
----
-
-## 8. 开发优先级
-
-按重要性和依赖关系排序:
-
-```
-P0 (必须完成):
-├── 登录认证
-├── 首页看板 (计时器 + 今日统计)
-├── 记录抽烟/忍住
-├── 历史记录查看
-└── 新用户引导
-
-P1 (核心功能):
-├── 统计图表 (周视图)
-├── 下次建议时间
-├── 个人设置
-└── 基础 AI 建议
-
-P2 (增强功能):
-├── 月/年统计
-├── AI 时间节点
-├── 会员/广告解锁
-└── 通知提醒
-
-P3 (未来迭代):
-├── 成就系统
-├── 社交分享
-└── 数据导出
-```
-
----
-
-## 9. 技术风险与应对
-
-| 风险 | 影响 | 应对措施 |
-|------|------|----------|
-| 首页加载慢 | 用户体验差 | 骨架屏 + 并行请求 + 缓存 |
-| 图表库体积大 | 包体积超标 | 按需引入 + 分包 |
-| AI 接口慢 | 等待时间长 | 异步加载 + Loading状态 |
-| 网络不稳定 | 数据丢失 | 离线缓存 + 重试机制 |
-| 微信审核不通过 | 延期上线 | 提前了解审核规范 |
-
----
-
-## 10. 验收标准
-
-### 首页
-- [ ] 首屏渲染 < 500ms
-- [ ] 计时器实时更新
-- [ ] 记录操作 < 3步完成
-
-### 记录
-- [ ] 支持快速记录
-- [ ] 支持编辑/删除
-- [ ] 数据实时同步
-
-### 统计
-- [ ] 图表正常显示
-- [ ] 数据计算准确
-- [ ] 切换流畅
-
-### 整体
-- [ ] 无明显卡顿
-- [ ] 无崩溃闪退
-- [ ] 视觉符合设计稿
diff --git a/docs/PHASE3_COMPLETED.md b/docs/PHASE3_COMPLETED.md
deleted file mode 100644
index f213de5..0000000
--- a/docs/PHASE3_COMPLETED.md
+++ /dev/null
@@ -1,434 +0,0 @@
-# Phase 3: 记录与历史 - 完成报告
-
-## ✅ 开发完成情况
-
-**开发时间**: 2025-01-25
-**完成度**: 100% (Day 1 + Day 2)
-
----
-
-## 📦 已完成功能
-
-### Day 1: 记录表单组件 ✅
-
-#### 1. smoke-record-dialog 组件
-**文件**: `components/smoke-record-dialog/smoke-record-dialog.vue`
-
-**功能清单**:
-- ✅ 底部弹出动画 (300ms 平滑过渡)
-- ✅ 明亮主题 UI (白色背景 + #10B981 主题色)
-- ✅ 双向绑定 (v-model:show)
-- ✅ 两种模式支持
- - type="smoke": 记录抽烟
- - type="resisted": 想抽忍住了
-- ✅ 完整表单字段
- - 日期时间选择 (默认当前时间)
- - 数量选择 (加减按钮 + 输入框)
- - 烟瘾等级选择 (1-5 级)
- - 备注输入 (最大 200 字符)
-- ✅ 编辑模式支持
- - initialData prop 预填充数据
- - 支持修改现有记录
-- ✅ 表单验证和提交
-- ✅ easycom 自动导入配置
-
-**API 集成**:
-- ✅ createLog - 新增记录
-- ✅ updateLog - 更新记录 (新增)
-- ✅ deleteLog - 删除记录 (新增)
-
-**文档**:
-- ✅ `components/smoke-record-dialog/README.md`
-- ✅ `components/README.md`
-- ✅ `CHANGELOG_COMPONENT.md`
-
----
-
-### Day 2: 历史记录页 ✅
-
-#### 1. logs Store
-**文件**: `stores/logs.js`
-
-**状态管理**:
-```javascript
-{
- logs: [], // 记录列表
- total: 0, // 总条数
- page: 1, // 当前页
- pageSize: 20, // 每页数量
- hasMore: true, // 是否有更多
- loading: false, // 加载状态
- refreshing: false // 刷新状态
-}
-```
-
-**Getters**:
-- ✅ groupedByDate - 按日期分组记录
-- ✅ smokeCount - 抽烟记录数量
-- ✅ resistedCount - 忍住记录数量
-- ✅ formattedLogs - 格式化记录列表(包含间隔时间计算)
-
-**Actions**:
-- ✅ fetchLogs - 获取记录列表
-- ✅ loadMore - 加载更多
-- ✅ deleteLog - 删除记录(乐观更新)
-- ✅ updateLog - 更新记录
-- ✅ clearLogs - 清空列表
-
-#### 2. 历史记录页面
-**文件**: `pages/logs/index.vue`
-
-**核心功能**:
-- ✅ 筛选 Tabs
- - 全部
- - 已抽烟
- - 已忍住
-- ✅ 时间轴布局
- - 按日期分组显示
- - 日期标签(今天/昨天/日期)
- - 时间线连接线
- - 类型图标(💪 忍住 / 🚬 抽烟)
-- ✅ 记录卡片
- - 类型标题
- - 时间显示 (HH:mm)
- - 数量和等级(抽烟时)
- - 备注内容
- - 间隔时间显示
- - 操作按钮(编辑/删除)
-- ✅ 下拉刷新
-- ✅ 上拉加载更多
-- ✅ 骨架屏加载状态
-- ✅ 空状态提示
-- ✅ 浮动新增按钮
-- ✅ 编辑功能
- - 打开编辑弹框
- - 预填充数据
- - 更新记录
-- ✅ 删除功能
- - 确认对话框
- - 乐观更新
- - 失败回滚
-
-**UI 优化**:
-- ✅ 明亮主题(渐变背景 #D1FAE5 → #FFFFFF)
-- ✅ 白色卡片 + 阴影
-- ✅ 彩色边框(绿色=忍住,红色=抽烟)
-- ✅ 流畅动画效果
-- ✅ 响应式布局
-
----
-
-## 🎨 UI/UX 改进
-
-### 配色方案更新
-
-**旧配色(深色主题)**:
-- 背景: #0D1F17 (深绿黑)
-- 卡片: #1A3325 (深绿)
-- 主题色: #4ADE80 (亮绿)
-
-**新配色(明亮主题)**:
-- 背景: 渐变 #D1FAE5 → #F0FDF4 → #FFFFFF
-- 卡片: #FFFFFF (白色 + 阴影)
-- 主题色: #10B981 (翡翠绿)
-- 文字: #1F2937 (深灰)
-- 次要文字: #6B7280 (中灰)
-
-### 交互优化
-
-1. **下拉刷新**
- - 原生下拉刷新组件
- - 加载状态提示
- - 自动重置页码
-
-2. **上拉加载**
- - 触底自动加载
- - hasMore 状态控制
- - 加载中提示
- - 没有更多提示
-
-3. **编辑/删除**
- - 卡片内置按钮
- - 编辑: 蓝色背景
- - 删除: 红色背景 + 确认对话框
- - 乐观更新提升体验
-
-4. **加载状态**
- - 骨架屏(首次加载)
- - shimmer 动画
- - 空状态友好提示
-
----
-
-## 🔧 技术实现
-
-### 1. 组件规范
-
-**命名**: kebab-case
-```
-✅ smoke-record-dialog
-✅ log-item (虽然未单独组件化,但集成在页面中)
-❌ SmokeRecordDialog
-```
-
-**目录结构**:
-```
-components/
-└── smoke-record-dialog/
- ├── smoke-record-dialog.vue
- └── README.md
-```
-
-**API 风格**: Options API
-```javascript
-export default {
- name: 'SmokeRecordDialog',
- props: { ... },
- data() { ... },
- methods: { ... }
-}
-```
-
-### 2. 状态管理
-
-**数据流**:
-```
-用户操作 → 页面事件 → Store Action → API 调用
- ↓
- Store 状态更新
- ↓
- 视图自动刷新
-```
-
-**更新策略**:
-- 新增记录: 悲观更新(成功后添加)
-- 删除记录: 乐观更新(先删除,失败回滚)
-- 编辑记录: 悲观更新(成功后更新)
-- 列表刷新: 清空后重新获取
-
-### 3. 性能优化
-
-**实现的优化**:
-- ✅ 分页加载(每页 20 条)
-- ✅ 骨架屏过渡
-- ✅ easycom 按需加载
-- ✅ 防抖处理(下拉刷新)
-- ✅ CSS transform 动画
-
-**未实现(可选)**:
-- ⏳ 虚拟列表(数据量 > 100 时)
-- ⏳ 请求缓存(5 分钟)
-- ⏳ 图片懒加载(目前无图片)
-
-### 4. 错误处理
-
-**已实现**:
-- ✅ API 调用异常捕获
-- ✅ Toast 错误提示
-- ✅ 删除失败回滚
-- ✅ 空状态处理
-- ✅ 加载失败提示
-
----
-
-## 📊 数据流程
-
-### 新增记录
-```
-首页/历史页 → 点击按钮 → 打开弹框 → 填写表单
-→ 提交 → createLog API → Store 更新 → 视图刷新
-```
-
-### 编辑记录
-```
-历史页 → 点击编辑 → 打开弹框 → 预填充数据
-→ 修改 → updateLog API → Store 更新 → 视图刷新
-```
-
-### 删除记录
-```
-历史页 → 点击删除 → 确认对话框 → deleteLog API
-→ 乐观更新(先删除) → 失败则刷新列表恢复
-```
-
-### 列表加载
-```
-进入页面 → fetchLogs(refresh=true) → 显示骨架屏
-→ 获取数据 → 渲染列表
-
-下拉刷新 → fetchLogs(refresh=true) → 重置页码
-→ 清空列表 → 重新获取
-
-上拉加载 → loadMore → page++ → 追加数据
-```
-
----
-
-## ✅ 验收测试
-
-### 功能测试 ✅
-
-**记录提交**:
-- ✅ 快速记录(使用默认值)
-- ✅ 完整记录(填写所有字段)
-- ✅ 记录抽烟模式
-- ✅ 记录忍住模式
-- ✅ 时间选择功能
-- ✅ 备注输入功能
-
-**历史记录**:
-- ✅ 列表正常显示
-- ✅ 日期分组正确
-- ✅ 筛选功能正常
-- ✅ 下拉刷新正常
-- ✅ 上拉加载正常
-- ✅ 编辑记录正常
-- ✅ 删除记录正常
-
-### 性能测试 ✅
-
-- ✅ 弹框动画 < 300ms
-- ✅ 列表首次加载 < 1s(模拟数据)
-- ✅ 滚动流畅(60fps)
-- ✅ 提交响应及时
-
-### UI/UX 测试 ✅
-
-- ✅ 明亮主题正确应用
-- ✅ 操作反馈及时
-- ✅ 错误提示友好
-- ✅ 空状态显示正确
-- ✅ 加载状态清晰
-
----
-
-## 📁 文件清单
-
-### 新增文件
-```
-stores/
-└── logs.js ✅ Logs Store
-
-components/
-└── smoke-record-dialog/
- ├── smoke-record-dialog.vue ✅ 记录弹框组件
- └── README.md ✅ 组件文档
-
-docs/
-├── PHASE3_SUMMARY.md ✅ Phase 3 总结
-├── PHASE3_TODO.md ✅ 待办清单
-└── PHASE3_COMPLETED.md ✅ 完成报告(本文件)
-```
-
-### 修改文件
-```
-pages/
-└── logs/
- └── index.vue ✅ 历史记录页
-
-pages/
-└── index/
- └── index.vue ✅ 首页(集成记录功能)
-
-stores/
-└── index.js ✅ 导出 logs store
-
-pages.json ✅ easycom 配置
-
-docs/
-└── DEVELOPMENT.md ✅ 完善 Phase 3 文档
-```
-
----
-
-## 🎯 已完成的任务
-
-### Day 1 任务 ✅
-- [x] 创建 smoke-record-dialog 组件
-- [x] 实现时间选择功能
-- [x] 实现数量选择功能
-- [x] 实现烟瘾等级选择
-- [x] 实现备注输入
-- [x] 底部弹出动画
-- [x] 双向绑定支持
-- [x] 两种模式支持
-- [x] easycom 配置
-- [x] 组件文档
-- [x] 首页集成
-
-### Day 2 任务 ✅
-- [x] 创建 logs store
-- [x] 实现状态管理
-- [x] 历史记录页面布局
-- [x] 筛选 Tabs 功能
-- [x] 时间轴展示
-- [x] 按日期分组
-- [x] 记录卡片渲染
-- [x] 编辑功能
-- [x] 删除功能
-- [x] 下拉刷新
-- [x] 上拉加载
-- [x] 骨架屏
-- [x] 空状态
-- [x] 浮动按钮
-- [x] 明亮主题
-
----
-
-## 🚀 下一步计划
-
-Phase 3 已全部完成,可以进入 Phase 4: 统计与图表
-
-### Phase 4 任务预览
-1. 统计页基础布局
-2. 时间范围切换(周/月/年)
-3. 吸烟趋势图(集成图表库)
-4. 健康与储蓄卡片
-5. 成就卡片
-6. 趋势对比
-
----
-
-## 📝 开发笔记
-
-### 遇到的问题
-
-1. **微信小程序组件依赖错误**
- - 问题: `SmokeRecordDialog.js` 被依赖分析忽略
- - 解决: 使用 kebab-case 命名 + 目录结构 + easycom
-
-2. **深色主题改为明亮主题**
- - 调整了所有颜色值
- - 添加了渐变背景
- - 优化了阴影和边框
-
-3. **编辑模式支持**
- - 添加 initialData prop
- - 在 initFormData 中判断是否有初始数据
- - 预填充表单字段
-
-### 最佳实践
-
-1. **组件设计**
- - 单一职责原则
- - Props 清晰定义
- - 事件命名规范
- - 支持扩展
-
-2. **状态管理**
- - Store 职责明确
- - Getters 处理计算逻辑
- - Actions 异步操作
- - 乐观/悲观更新策略
-
-3. **用户体验**
- - 操作反馈及时
- - 加载状态清晰
- - 错误提示友好
- - 空状态引导
-
----
-
-**完成时间**: 2025-01-25
-**开发者**: AI Assistant
-**状态**: ✅ 已完成并测试通过
diff --git a/docs/PHASE3_SUMMARY.md b/docs/PHASE3_SUMMARY.md
deleted file mode 100644
index ac4768b..0000000
--- a/docs/PHASE3_SUMMARY.md
+++ /dev/null
@@ -1,368 +0,0 @@
-# Phase 3: 记录与历史 - 开发总结
-
-## 📋 概览
-
-Phase 3 主要实现记录功能和历史记录页面,是用户日常使用的核心功能。
-
-**开发周期**: 2 天
-**当前进度**: Day 1 已完成 80%,Day 2 待开始
-
----
-
-## ✅ 已完成功能 (Day 1)
-
-### 1. smoke-record-dialog 组件
-
-**文件位置**: `components/smoke-record-dialog/smoke-record-dialog.vue`
-
-**核心特性**:
-- ✅ 底部弹出动画 (300ms 平滑过渡)
-- ✅ 明亮主题 UI (白色背景 + #10B981 主题色)
-- ✅ 支持两种模式
- - `type="smoke"`: 记录抽烟 (显示数量、等级)
- - `type="resisted"`: 想抽忍住了 (num=0)
-- ✅ 表单字段
- - 日期时间选择器 (默认当前时间)
- - 数量选择 (加减按钮 + 输入框)
- - 烟瘾等级 (1-5 级按钮组)
- - 备注输入 (最大 200 字符)
-- ✅ 数据验证和提交
-- ✅ easycom 自动导入配置
-
-**使用示例**:
-```vue
-
-```
-
-### 2. API 集成
-
-**已实现**:
-- ✅ `createLog(data)` - 新增记录
-- ✅ `getLatestLogs(limit)` - 获取最近记录
-- ⏳ `updateLog(id, data)` - 更新记录 (API 已定义,待集成)
-- ⏳ `deleteLog(id)` - 删除记录 (API 已定义,待集成)
-
-### 3. 首页集成
-
-**文件位置**: `pages/index/index.vue`
-
-**已实现**:
-- ✅ 两个快捷按钮
- - "记录抽烟" → 打开弹框 (type="smoke")
- - "想抽忍住了" → 打开弹框 (type="resisted")
-- ✅ 提交后数据更新
- - 更新今日抽烟数
- - 重置计时器
- - 显示成功提示
-
-### 4. 文档
-
-**已创建**:
-- ✅ `components/smoke-record-dialog/README.md` - 组件文档
-- ✅ `components/README.md` - 全局组件使用指南
-- ✅ `CHANGELOG_COMPONENT.md` - 组件错误修复说明
-
----
-
-## 📝 待完成功能 (Day 2)
-
-### 1. 历史记录页面
-
-**文件位置**: `pages/logs/index.vue`
-
-**核心功能**:
-```
-┌─────────────────────────────────────┐
-│ 历史记录 │
-│ ───────────────────────────────── │
-│ [全部] [已抽烟] [已忍住] │
-│ ───────────────────────────────── │
-│ │
-│ 今天 │
-│ ┌────────────────────────────┐ │
-│ │ 🚬 14:30 3 支 │ │
-│ │ 压力大、工作繁忙 │ │
-│ │ 距上次 2小时15分 │ │
-│ └────────────────────────────┘ │
-│ ┌────────────────────────────┐ │
-│ │ 💪 12:15 │ │
-│ │ 想抽但忍住了 │ │
-│ │ 距上次 30分钟 │ │
-│ └────────────────────────────┘ │
-│ │
-│ 昨天 │
-│ ┌────────────────────────────┐ │
-│ │ 🚬 18:00 2 支 │ │
-│ │ 下班应酬 │ │
-│ └────────────────────────────┘ │
-│ │
-│ [+] │
-└─────────────────────────────────────┘
-```
-
-**任务清单**:
-- [ ] 页面布局和导航
-- [ ] 筛选 Tabs (全部/已抽烟/已忍住)
-- [ ] 按日期分组显示
-- [ ] 记录卡片组件 (log-item)
-- [ ] 左滑操作 (编辑/删除)
-- [ ] 下拉刷新
-- [ ] 上拉加载更多
-- [ ] 浮动新增按钮
-- [ ] 空状态提示
-
-### 2. log-item 组件
-
-**文件位置**: `components/log-item/log-item.vue`
-
-**显示内容**:
-- 类型图标 (🚬 抽烟 / 💪 忍住)
-- 时间 (HH:mm)
-- 数量 (X 支) + 烟瘾等级
-- 备注内容
-- 间隔时间 (距上次 X 小时 Y 分)
-- 左滑按钮 (编辑/删除)
-
-### 3. logs Store
-
-**文件位置**: `stores/logs.js`
-
-**状态管理**:
-```javascript
-{
- logs: [], // 记录列表
- total: 0, // 总数
- page: 1, // 当前页
- pageSize: 20, // 每页条数
- hasMore: true, // 是否有更多
- loading: false, // 加载状态
-
- getters: {
- groupedByDate, // 按日期分组
- smokeCount, // 抽烟记录数
- resistedCount // 忍住记录数
- },
-
- actions: {
- fetchLogs, // 获取记录
- loadMore, // 加载更多
- deleteLog, // 删除记录
- updateLog // 更新记录
- }
-}
-```
-
-### 4. 编辑功能
-
-**复用组件**: `smoke-record-dialog`
-
-**新增 Props**:
-```javascript
-{
- mode: 'create' | 'edit', // 模式
- recordId: Number, // 记录 ID (编辑时)
- initialData: Object // 初始数据 (编辑时)
-}
-```
-
-**流程**:
-1. 点击编辑按钮
-2. 打开弹框,预填充数据
-3. 修改内容
-4. 调用 updateLog API
-5. 更新列表数据
-
-### 5. 删除功能
-
-**流程**:
-1. 左滑显示删除按钮
-2. 点击删除
-3. 显示确认对话框
-4. 确认后调用 deleteLog API
-5. 乐观更新列表 (失败时回滚)
-
----
-
-## 🎯 开发优先级
-
-### P0 (必须完成)
-- [ ] 历史记录页面基础布局
-- [ ] 记录列表显示
-- [ ] 分页加载
-- [ ] 删除功能
-
-### P1 (核心功能)
-- [ ] 编辑功能
-- [ ] 筛选功能
-- [ ] 日期分组
-- [ ] 下拉刷新
-
-### P2 (体验优化)
-- [ ] 骨架屏
-- [ ] 空状态
-- [ ] 加载动画
-- [ ] 错误处理
-
----
-
-## 🔧 技术要点
-
-### 1. 组件规范
-
-**命名规范**:
-- ✅ kebab-case: `smoke-record-dialog`, `log-item`
-- ✅ 目录结构: `components/xxx/xxx.vue`
-- ❌ 避免: PascalCase 单文件组件
-
-**API 风格**:
-- ✅ Options API (兼容性)
-- ✅ v-model 双向绑定
-- ✅ 事件传递数据
-
-### 2. 状态管理
-
-**数据流**:
-```
-用户操作 → 组件事件 → 页面处理 → API 调用
- ↓
- Store 更新 ← API 响应
- ↓
- 视图自动更新
-```
-
-**更新策略**:
-- 新增: 悲观更新 (成功后添加)
-- 删除: 乐观更新 (先删除,失败回滚)
-- 编辑: 悲观更新 (成功后更新)
-
-### 3. 性能优化
-
-**列表优化**:
-- 分页加载 (每页 20 条)
-- 虚拟列表 (数据量 > 100)
-- 图片懒加载
-- 防抖处理
-
-**请求优化**:
-- 请求缓存 (5 分钟)
-- 并行请求
-- 请求取消 (页面离开)
-
-**渲染优化**:
-- 骨架屏过渡
-- CSS transform 动画
-- 平滑滚动
-
-### 4. 用户体验
-
-**反馈机制**:
-- 操作成功: Toast + 自动关闭
-- 操作失败: Toast + 保留输入
-- 删除确认: Modal 二次确认
-- 加载状态: Loading + 禁用按钮
-
-**快捷操作**:
-- 首页快速记录 (2 个按钮)
-- 历史页浮动按钮 (+)
-- 左滑快速编辑/删除
-- 下拉刷新
-
----
-
-## 🧪 测试清单
-
-### 功能测试
-
-**记录提交**:
-- [ ] 快速记录 (使用默认值)
-- [ ] 完整记录 (填写所有字段)
-- [ ] 记录抽烟
-- [ ] 记录忍住
-- [ ] 时间选择
-- [ ] 备注输入
-
-**历史记录**:
-- [ ] 列表显示
-- [ ] 日期分组
-- [ ] 筛选切换
-- [ ] 下拉刷新
-- [ ] 上拉加载
-- [ ] 编辑记录
-- [ ] 删除记录
-
-### 边界测试
-
-- [ ] 空数据状态
-- [ ] 网络异常
-- [ ] 提交失败
-- [ ] 删除失败
-- [ ] 并发操作
-- [ ] 快速点击
-
-### 兼容性测试
-
-- [ ] iOS 系统
-- [ ] Android 系统
-- [ ] 不同机型
-- [ ] 不同屏幕尺寸
-- [ ] 安全区域适配
-
----
-
-## 📊 验收标准
-
-### 性能指标
-- [ ] 弹框动画 < 300ms
-- [ ] 列表首次加载 < 1s
-- [ ] 滚动帧率 60fps
-- [ ] 提交成功率 > 99%
-
-### 功能完整性
-- [ ] 记录提交 ✅
-- [ ] 记录编辑 ⏳
-- [ ] 记录删除 ⏳
-- [ ] 列表分页 ⏳
-- [ ] 数据筛选 ⏳
-
-### 用户体验
-- [ ] 操作流畅无卡顿
-- [ ] 反馈及时明确
-- [ ] 错误提示友好
-- [ ] 视觉符合设计稿
-
----
-
-## 📖 相关文档
-
-- [完整开发计划](./DEVELOPMENT.md)
-- [API 文档](./api.md)
-- [组件使用指南](../components/README.md)
-- [smoke-record-dialog 组件文档](../components/smoke-record-dialog/README.md)
-- [组件错误修复说明](../CHANGELOG_COMPONENT.md)
-
----
-
-## 🚀 下一步
-
-1. **开始 Day 2 开发**
- - 创建历史记录页面
- - 实现 log-item 组件
- - 创建 logs store
-
-2. **功能开发顺序**
- - 列表基础显示 → 分页加载 → 删除功能 → 编辑功能 → 筛选功能
-
-3. **测试与优化**
- - 功能测试
- - 性能测试
- - 用户体验优化
-
----
-
-**更新时间**: 2025-01-25
-**负责人**: 开发团队
-**状态**: Day 1 完成,Day 2 进行中
diff --git a/docs/PHASE3_TODO.md b/docs/PHASE3_TODO.md
deleted file mode 100644
index 91dabd7..0000000
--- a/docs/PHASE3_TODO.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# Phase 3: 记录与历史 - 待办清单
-
-> 快速查看待完成任务,详细说明请参考 [DEVELOPMENT.md](./DEVELOPMENT.md)
-
-## Day 1: 记录表单组件 ✅
-
-### smoke-record-dialog 组件
-- [x] 组件结构和布局
-- [x] 时间选择器 (日期 + 时间)
-- [x] 数量选择器 (加减按钮)
-- [x] 烟瘾等级选择 (1-5 级)
-- [x] 备注输入框
-- [x] 底部弹出动画
-- [x] 双向绑定 (v-model:show)
-- [x] 两种模式支持 (smoke/resisted)
-- [x] 数据提交逻辑
-
-### 配置和文档
-- [x] easycom 自动导入配置
-- [x] 组件文档 (README.md)
-- [x] 使用示例和说明
-- [x] 错误修复文档
-
-### 首页集成
-- [x] 导入组件
-- [x] 两个快捷按钮
-- [x] 提交处理逻辑
-- [x] Dashboard 数据更新
-
-### API 封装
-- [x] createLog API
-- [x] getLatestLogs API
-- [ ] updateLog API (已定义,待集成)
-- [ ] deleteLog API (已定义,待集成)
-
----
-
-## Day 2: 历史记录页 ⏳
-
-### 页面结构 (`pages/logs/index.vue`)
-- [ ] 创建页面文件
-- [ ] 导航栏配置
-- [ ] 页面基础布局
-- [ ] scroll-view 容器
-
-### 筛选功能
-- [ ] Tabs 组件
- - [ ] 全部
- - [ ] 已抽烟
- - [ ] 已忍住
-- [ ] 筛选逻辑实现
-- [ ] 切换动画
-
-### 数据层 (`stores/logs.js`)
-- [ ] 创建 store 文件
-- [ ] State 定义
- ```javascript
- {
- logs: [],
- total: 0,
- page: 1,
- pageSize: 20,
- hasMore: true,
- loading: false
- }
- ```
-- [ ] Getters 实现
- - [ ] groupedByDate (按日期分组)
- - [ ] smokeCount (抽烟记录数)
- - [ ] resistedCount (忍住记录数)
-- [ ] Actions 实现
- - [ ] fetchLogs (获取记录列表)
- - [ ] loadMore (加载更多)
- - [ ] deleteLog (删除记录)
- - [ ] updateLog (更新记录)
- - [ ] clearLogs (清空列表)
-
-### log-item 组件 (`components/log-item/log-item.vue`)
-- [ ] 创建组件文件
-- [ ] 卡片布局
-- [ ] 类型图标显示 (🚬/💪)
-- [ ] 时间显示 (HH:mm)
-- [ ] 数量和等级显示
-- [ ] 备注内容显示
-- [ ] 间隔时间计算
-- [ ] 样式实现
- - [ ] 基础样式
- - [ ] 抽烟/忍住边框色
- - [ ] 响应式布局
-
-### 左滑操作
-- [ ] 安装/导入 uni-swipe-action
-- [ ] 左滑菜单
- - [ ] 编辑按钮 (蓝色)
- - [ ] 删除按钮 (红色)
-- [ ] 编辑功能
- - [ ] 打开编辑弹框
- - [ ] 预填充数据
- - [ ] 调用 updateLog API
- - [ ] 更新列表
-- [ ] 删除功能
- - [ ] 确认对话框
- - [ ] 调用 deleteLog API
- - [ ] 乐观更新
- - [ ] 失败回滚
-
-### 日期分组
-- [ ] groupByDate 函数
-- [ ] 日期格式化
- - [ ] 今天
- - [ ] 昨天
- - [ ] MM-DD
-- [ ] 分组渲染
-- [ ] 日期头部样式
-
-### 加载状态
-- [ ] 骨架屏组件
- - [ ] 卡片骨架
- - [ ] shimmer 动画
-- [ ] 下拉刷新
- - [ ] refresher 配置
- - [ ] 刷新逻辑
- - [ ] 重置页码
-- [ ] 上拉加载
- - [ ] onReachBottom 处理
- - [ ] hasMore 检查
- - [ ] 加载动画
-- [ ] 空状态
- - [ ] 空状态图标
- - [ ] 提示文案
- - [ ] 引导按钮
-
-### 浮动按钮
-- [ ] 固定定位
-- [ ] 样式实现
- - [ ] 圆形按钮
- - [ ] 阴影效果
- - [ ] 动画效果
-- [ ] 点击打开记录弹框
-- [ ] 避开 tabbar
-
-### 性能优化
-- [ ] 虚拟列表 (可选)
-- [ ] 图片懒加载 (如有)
-- [ ] 请求缓存
-- [ ] 防抖处理
-- [ ] 请求取消
-
-### 错误处理
-- [ ] 网络异常提示
-- [ ] 加载失败重试
-- [ ] 删除失败回滚
-- [ ] 表单验证
-
----
-
-## 测试任务 ⏳
-
-### 功能测试
-- [ ] 记录提交
- - [ ] 快速记录 (默认值)
- - [ ] 完整记录
- - [ ] 抽烟模式
- - [ ] 忍住模式
-- [ ] 历史记录
- - [ ] 列表显示
- - [ ] 分页加载
- - [ ] 筛选功能
- - [ ] 编辑记录
- - [ ] 删除记录
-
-### 边界测试
-- [ ] 空数据状态
-- [ ] 网络异常
-- [ ] 提交失败
-- [ ] 删除失败
-- [ ] 并发操作
-- [ ] 快速点击
-
-### 性能测试
-- [ ] 弹框动画 < 300ms
-- [ ] 列表加载 < 1s
-- [ ] 滚动流畅度 (60fps)
-- [ ] 长列表性能
-
-### 兼容性测试
-- [ ] iOS 系统
-- [ ] Android 系统
-- [ ] 不同机型
-- [ ] 安全区域适配
-
----
-
-## 文档任务 ✅
-
-- [x] 完善 DEVELOPMENT.md Phase 3 部分
-- [x] 创建 PHASE3_SUMMARY.md
-- [x] 创建 PHASE3_TODO.md
-- [x] 组件使用文档
-- [x] API 集成说明
-
----
-
-## 进度统计
-
-**总任务**: ~60 个
-**已完成**: ~60 个 (100%) ✅
-**进行中**: 0 个
-**待开始**: 0 个
-
-**Day 1 进度**: ✅ 100% 完成
-**Day 2 进度**: ✅ 100% 完成
-
----
-
-## 优先级标记
-
-- 🔴 P0 - 必须完成
-- 🟡 P1 - 核心功能
-- 🟢 P2 - 体验优化
-
-### P0 任务
-- [ ] 🔴 历史记录页面基础布局
-- [ ] 🔴 记录列表显示
-- [ ] 🔴 分页加载功能
-- [ ] 🔴 删除功能
-- [ ] 🔴 logs store 创建
-
-### P1 任务
-- [ ] 🟡 编辑功能
-- [ ] 🟡 筛选功能
-- [ ] 🟡 日期分组
-- [ ] 🟡 下拉刷新
-- [ ] 🟡 log-item 组件
-
-### P2 任务
-- [ ] 🟢 骨架屏
-- [ ] 🟢 空状态
-- [ ] 🟢 加载动画
-- [ ] 🟢 虚拟列表
-- [ ] 🟢 错误处理优化
-
----
-
-## 开发建议
-
-1. **Day 2 开发顺序**
- ```
- 创建页面 → 数据层 → 组件 → 功能 → 优化
- ```
-
-2. **最小可用版本**
- - 先实现基础列表显示
- - 再添加删除功能
- - 最后优化体验
-
-3. **并行开发**
- - log-item 组件可独立开发
- - logs store 可先完成
- - 页面布局和组件同步进行
-
-4. **测试策略**
- - 边开发边测试
- - 功能完成后集成测试
- - 最后进行性能测试
-
----
-
-**更新时间**: 2025-01-25
-**下次更新**: 完成 Day 2 开发后
diff --git a/docs/PHASE3_USER_GUIDE.md b/docs/PHASE3_USER_GUIDE.md
deleted file mode 100644
index 542c616..0000000
--- a/docs/PHASE3_USER_GUIDE.md
+++ /dev/null
@@ -1,378 +0,0 @@
-# Phase 3 功能使用指南
-
-## 📖 用户操作指南
-
-### 1. 记录抽烟
-
-#### 方式一:从首页快速记录
-
-1. 打开小程序,进入首页
-2. 点击「记录抽烟」按钮
-3. 弹出记录表单:
- - **时间**: 默认当前时间,可修改日期和时间
- - **数量**: 默认 1 支,可通过 +/- 调整或直接输入
- - **烟瘾等级**: 选择 1-5 级(默认 2 级)
- - **备注**: 选填,最多 200 字符
-4. 点击「确定」提交
-5. 提示"记录成功",首页数据自动更新
-
-#### 方式二:从历史记录页新增
-
-1. 切换到「记录」标签页
-2. 点击右下角浮动 ➕ 按钮
-3. 跳转到首页进行记录
-
-### 2. 记录想抽忍住了
-
-#### 从首页记录
-
-1. 打开小程序,进入首页
-2. 点击「想抽忍住了」按钮(绿色)
-3. 弹出记录表单:
- - **时间**: 默认当前时间,可修改
- - **备注**: 记录抵抗心得或当时的想法
- - 数量和等级不显示(自动设置为 num=0, level=2)
-4. 点击「确定」提交
-5. 提示"太棒了!"
-
-### 3. 查看历史记录
-
-1. 切换到「记录」标签页
-2. 查看所有记录,按日期分组显示
-3. 可以通过顶部标签筛选:
- - **全部**: 显示所有记录
- - **已抽烟**: 只显示抽烟记录
- - **已忍住**: 只显示忍住记录
-
-#### 记录卡片信息
-
-每条记录显示:
-- **类型图标**: 💪(忍住)或 🚬(抽烟)
-- **类型标题**: "想抽忍住了" 或 "记录抽烟"
-- **时间**: HH:mm 格式
-- **数量和等级**: 仅抽烟记录显示
-- **备注**: 如果有填写
-- **间隔时间**: 距离上一条记录的时间
-
-#### 日期分组
-
-- **今天**: 显示"今天 X月X日"
-- **昨天**: 显示"昨天 X月X日"
-- **更早**: 显示"X月X日"
-
-### 4. 编辑记录
-
-1. 进入「记录」标签页
-2. 找到要编辑的记录
-3. 点击卡片右上角的「编辑」按钮(蓝色)
-4. 弹出编辑表单,数据已预填充
-5. 修改需要更改的内容
-6. 点击「确定」保存
-7. 提示"更新成功",列表自动刷新
-
-**注意**:
-- 可以修改时间、数量、等级、备注
-- 不能改变记录类型(抽烟/忍住)
-
-### 5. 删除记录
-
-1. 进入「记录」标签页
-2. 找到要删除的记录
-3. 点击卡片右上角的「删除」按钮(红色)
-4. 弹出确认对话框:"确定要删除这条记录吗?"
-5. 点击「确定」删除
-6. 提示"删除成功",记录从列表中消失
-
-**注意**:
-- 删除操作不可恢复
-- 删除后会立即从列表中移除(乐观更新)
-- 如果删除失败,会自动恢复记录并提示错误
-
-### 6. 下拉刷新
-
-1. 进入「记录」标签页
-2. 在列表顶部向下拉动
-3. 显示刷新指示器
-4. 释放后自动刷新数据
-5. 刷新完成后回到顶部
-
-**用途**:
-- 同步最新数据
-- 查看其他设备的记录
-- 修复显示异常
-
-### 7. 上拉加载更多
-
-1. 进入「记录」标签页
-2. 滚动到列表底部
-3. 自动触发加载更多
-4. 显示"加载中..."
-5. 新数据追加到列表底部
-
-**说明**:
-- 每次加载 20 条记录
-- 没有更多时显示"没有更多了"
-- 正在加载时不会重复请求
-
----
-
-## 🎨 界面说明
-
-### 首页 (pages/index/index.vue)
-
-#### 配色
-- **背景**: 渐变(浅绿 → 白色)
-- **卡片**: 白色 + 阴影
-- **主题色**: 翡翠绿 #10B981
-- **按钮**:
- - 记录抽烟: 白色背景 + 灰色边框
- - 想抽忍住了: 绿色背景 + 白色文字
-
-#### 布局
-```
-┌─────────────────────────────┐
-│ 状态栏 │
-│ 问候语 + 头像 ⚙️ │
-│ AI 提示卡片 (可关闭) × │
-│ ┌─────────────────────┐ │
-│ │ 距上次抽烟 │ │
-│ │ 02:45:39 │ │
-│ │ ✨ 下次建议: 15:30 │ │
-│ └─────────────────────┘ │
-│ ┌──────┐ ┌──────┐ │
-│ │今日 │ │烟瘾 │ │
-│ │已抽 │ │发作 │ │
-│ └──────┘ └──────┘ │
-│ [🚬 记录抽烟] [💪 想抽忍住了] │
-└─────────────────────────────┘
-```
-
-### 历史记录页 (pages/logs/index.vue)
-
-#### 配色
-- **背景**: 渐变(浅绿 → 白色)
-- **标签栏**:
- - 未选中: 白色 + 灰色边框
- - 选中: 绿色背景 + 白色文字
-- **卡片**:
- - 白色背景
- - 绿色左边框(忍住)
- - 红色左边框(抽烟)
-
-#### 布局
-```
-┌─────────────────────────────┐
-│ 历史记录 │
-│ [全部] [已抽烟] [已忍住] │
-├─────────────────────────────┤
-│ 今天 1月25日 │
-│ ● ┌───────────────────┐ │
-│ │ │ 💪 想抽忍住了 │ │
-│ │ │ 14:30 │ │
-│ │ │ 想抽但忍住了 │ │
-│ │ │ 距上次 2小时15分 │ │
-│ │ └───────────────────┘ │
-│ │ [编辑] [删除] │
-│ ● ┌───────────────────┐ │
-│ │ 🚬 记录抽烟 │ │
-│ │ 12:15 3支 等级2 │ │
-│ │ 压力大、工作繁忙 │ │
-│ └───────────────────┘ │
-│ [编辑] [删除] │
-│ │
-│ 昨天 1月24日 │
-│ ● ┌───────────────────┐ │
-│ │ ... │ │
-│ └───────────────────┘ │
-│ │
-│ [+] │
-└─────────────────────────────┘
-```
-
-### 记录弹框 (components/smoke-record-dialog)
-
-#### 抽烟模式
-```
-┌─────────────────────────────┐
-│ 记录抽烟 × │
-├─────────────────────────────┤
-│ 时间 │
-│ [2025-01-25] [14:30] │
-│ │
-│ 数量 │
-│ [-] [1] [+] │
-│ │
-│ 烟瘾等级 │
-│ [1] [2] [3] [4] [5] │
-│ │
-│ 备注 │
-│ ┌─────────────────────┐ │
-│ │ 记录抽烟原因... │ │
-│ └─────────────────────┘ │
-├─────────────────────────────┤
-│ [取消] [确定] │
-└─────────────────────────────┘
-```
-
-#### 忍住模式
-```
-┌─────────────────────────────┐
-│ 想抽忍住了 × │
-├─────────────────────────────┤
-│ 时间 │
-│ [2025-01-25] [14:30] │
-│ │
-│ 备注 │
-│ ┌─────────────────────┐ │
-│ │ 记录抵抗心得... │ │
-│ └─────────────────────┘ │
-├─────────────────────────────┤
-│ [取消] [确定] │
-└─────────────────────────────┘
-```
-
----
-
-## 💡 使用技巧
-
-### 1. 快速记录
-
-**场景**: 刚抽完烟,想快速记录
-
-**操作**:
-1. 打开小程序
-2. 点击「记录抽烟」
-3. 直接点击「确定」(使用默认值)
-
-**时间**: < 3 秒
-
-### 2. 详细记录
-
-**场景**: 需要记录详细信息
-
-**操作**:
-1. 打开记录表单
-2. 修改时间(如果不是刚抽的)
-3. 调整数量和等级
-4. 填写备注(为什么抽、当时心情等)
-5. 提交
-
-**建议备注内容**:
-- 抽烟原因:压力大、无聊、社交、习惯
-- 当时心情:焦虑、放松、开心、郁闷
-- 触发场景:工作、休息、饭后、等人
-
-### 3. 回顾分析
-
-**查看抽烟规律**:
-1. 进入历史记录页
-2. 查看时间分布
-3. 查看间隔时间
-4. 查看备注了解触发原因
-
-**筛选特定类型**:
-1. 点击「已抽烟」查看所有抽烟记录
-2. 点击「已忍住」查看抵抗记录
-3. 对比数量,激励自己
-
-### 4. 纠正错误
-
-**场景**: 记录时间或内容错误
-
-**操作**:
-1. 进入历史记录页
-2. 找到错误记录
-3. 点击「编辑」
-4. 修改错误信息
-5. 保存
-
-### 5. 删除重复
-
-**场景**: 误操作重复记录
-
-**操作**:
-1. 进入历史记录页
-2. 找到重复记录
-3. 点击「删除」
-4. 确认删除
-
----
-
-## ⚠️ 注意事项
-
-### 数据同步
-
-- 记录会实时同步到服务器
-- 多设备登录时,数据自动同步
-- 删除后不可恢复,请谨慎操作
-
-### 时间设置
-
-- 可以记录过去的时间
-- 不能记录未来的时间
-- 建议在抽烟后立即记录,更准确
-
-### 备注内容
-
-- 最多 200 字符
-- 建议记录关键信息
-- 帮助分析抽烟规律
-
-### 网络问题
-
-- 需要网络连接才能同步
-- 网络异常时会提示错误
-- 可以下拉刷新重试
-
----
-
-## 🆘 常见问题
-
-### Q: 记录后首页数据没更新?
-
-**A**: 尝试以下方法:
-1. 下拉刷新首页
-2. 切换 Tab 重新进入
-3. 检查网络连接
-
-### Q: 删除记录后又出现了?
-
-**A**: 可能是网络问题导致删除失败:
-1. 检查网络连接
-2. 重新尝试删除
-3. 联系客服
-
-### Q: 编辑后数据没变?
-
-**A**:
-1. 检查是否点击了「确定」
-2. 查看是否有错误提示
-3. 刷新列表重试
-
-### Q: 看不到历史记录?
-
-**A**:
-1. 下拉刷新列表
-2. 检查筛选标签(是否选了「已抽烟」但没有记录)
-3. 检查网络连接
-
-### Q: 如何查看更早的记录?
-
-**A**:
-1. 滚动到列表底部
-2. 会自动加载更多
-3. 每次加载 20 条
-
----
-
-## 📞 技术支持
-
-如遇到其他问题,请通过以下方式联系:
-- 小程序内客服
-- 问题反馈
-- GitHub Issues
-
----
-
-**更新时间**: 2025-01-25
-**版本**: Phase 3 完整版
diff --git a/docs/PRD.md b/docs/PRD.md
index f43169b..1a60d7a 100644
--- a/docs/PRD.md
+++ b/docs/PRD.md
@@ -28,10 +28,10 @@
|------|------|----------|
| 问候语 | 根据时段显示(早上好/下午好等) + 用户昵称 | 本地计算 + profile |
| AI 提示卡片 | 发现的抽烟规律/建议(可关闭) | `GET /ai/advice` 缓存 |
-| 计时环 | 距上次抽烟时间(时:分:秒) | `dashboard.minutes_since_last` |
+| 计时环 | 距上次抽烟时间(时:分:秒) | `GET /next_smoke_time` 的 `last_smoke_at`(前端计时) |
| 下次建议时间 | 显示建议的下次抽烟时间点 | `GET /next_smoke_time` |
-| 今日已抽 | X / 目标数,较昨日 ±N | `dashboard.today_count` |
-| 烟瘾发作已抵抗 | 忍住次数统计 | 筛选 `level=0,num=0` 记录 |
+| 今日已抽 | X / 目标数,较昨日 ±N | `next_smoke_time.today_count` + `next_smoke_time.reduced_from_yesterday`(可为负) + `next_smoke_time.exceeded_yesterday`(标识“超出昨日”) |
+| 烟瘾发作已抵抗 | 忍住次数统计 | `next_smoke_time.resisted_count` |
| 记录抽烟按钮 | 快速记录一次抽烟 | `POST /logs` |
| 想抽忍住了按钮 | 记录成功抵抗 | `POST /logs/resisted` |
@@ -81,7 +81,7 @@
| 筛选 Tabs | 全部 / 已抽烟 / 已忍住 | 前端筛选 |
| 时间线 | 按日期分组展示 | `GET /logs` |
| 记录卡片 | 类型、时间、原因标签、间隔时间 | logs 数据 |
-| 左滑操作 | 编辑 / 删除 | `PUT/DELETE /logs/:id` |
+| 左滑操作 | 编辑 / 删除 | `POST/DELETE /logs/:id` |
| 新增按钮 | 浮动按钮快速新增 | 跳转记录流程 |
### 2.5 个人中心 (profile_&_settings)
@@ -92,11 +92,11 @@
|------|------|----------|
| 用户信息 | 头像、昵称 | 微信授权 |
| 目标展示 | 目标戒烟日期、连续天数 | profile |
-| 目标设定 | 调整每日限额与戒烟日期 | `PUT /profile` |
+| 目标设定 | 调整每日限额与戒烟日期 | `POST /profile` |
| AI 计划调整 | 个性化辅导风格设置 | profile 扩展 |
| 通知设置 | 提醒时间、频率 | 本地存储 |
| 会员解锁 | PRO 功能 / 广告解锁 | 会员系统 |
-| 基础设置 | 作息时间等 | `PUT /profile` |
+| 基础设置 | 作息时间等 | `POST /profile` |
| 隐私与数据 | 数据导出、账号注销 | 待扩展 |
---
@@ -126,7 +126,7 @@ Step 5: 作息时间 (wake_up_time, sleep_time)
↓
Step 6: 设置目标 (目标日期、每日限额)
↓
-提交 profile (PUT /profile)
+提交 profile (POST /profile)
↓
进入首页
```
@@ -186,8 +186,8 @@ Step 6: 设置目标 (目标日期、每日限额)
```
[并行请求]
├── GET /profile (用户信息,判断是否需引导)
-├── GET /dashboard (今日统计,计时器数据)
-└── GET /next_smoke_time (下次建议时间)
+├── GET /next_smoke_time (首页汇总 + 下次建议时间)
+└── GET /dashboard (看板数据,可延迟)
[延迟加载]
└── GET /ai/advice (AI提示卡片,非关键)
@@ -195,8 +195,8 @@ Step 6: 设置目标 (目标日期、每日限额)
**缓存策略**:
- profile: 登录后缓存,变更时更新
-- dashboard: 每次进入刷新,后台定时更新
-- next_smoke_time: 缓存至下次记录
+- next_smoke_time: 每次进入刷新,下一次记录后刷新
+- dashboard: 进入看板时刷新
- ai/advice: 按天缓存
### 5.2 数据预加载
diff --git a/docs/api.md b/docs/api.md
index f3b25a9..04ed0a3 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -155,7 +155,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
## 6) 更新记录
-`PUT /api/v1/smoke/logs/:id`
+`POST /api/v1/smoke/logs/:id`
请求体(字段可选,按需传):
@@ -302,7 +302,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
## 11) 补全/更新用户基础信息(Upsert)
-`PUT /api/v1/smoke/profile`
+`POST /api/v1/smoke/profile`
说明:
- 字段按需传;首次进入建议一次性补全。
@@ -348,6 +348,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
说明:
- 用于首页展示“建议的下次记录时间”。
+- 已整合首页所需汇总字段(上次抽烟时间/今日抽烟支数/今日克制次数/较昨日减少支数)。
- 如果指定日期存在 AI 给出的时间节点(`time_nodes` 不为空),则优先使用 AI 的建议;否则使用默认策略。
- 可选参数:
- `date`:计划日期(默认今天),支持 `YYYY-MM-DD` 或 `today/tomorrow`。
@@ -359,6 +360,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
默认策略(不使用 AI):
- 基础间隔:优先使用 `GET /api/v1/smoke/profile` 返回的 `baseline_interval_minutes`;若不存在则默认 `60` 分钟。
- 阶梯式延时:最近 7 天内每累计 `5` 条“忍住记录(level=0,num=0)”,在基础间隔上 `+5` 分钟(最多 `+60` 分钟)。
+- 间隔兜底:最终间隔会限制在 `5~240` 分钟之间。
- 若用户已补全作息时间,会自动规避睡眠区间:若计算出的时间落在睡眠区间,顺延到下一次起床时间。
AI 生成说明:
@@ -374,6 +376,11 @@ AI 生成说明:
"source": "default",
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:18:00+08:00",
+ "last_smoke_at": "2026-01-05T09:30:00+08:00",
+ "today_count": 3,
+ "resisted_count": 1,
+ "reduced_from_yesterday": 2,
+ "exceeded_yesterday": false,
"default": {
"last_smoke_at": "2026-01-05T09:30:00+08:00",
"next_smoke_at": "2026-01-05T10:18:00+08:00",
@@ -398,6 +405,11 @@ AI 生成说明:
"source": "ai",
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:28:00+08:00",
+ "last_smoke_at": "2026-01-05T09:30:00+08:00",
+ "today_count": 3,
+ "resisted_count": 1,
+ "reduced_from_yesterday": 2,
+ "exceeded_yesterday": false,
"time_nodes": ["10:30", "11:10", "14:00", "16:30"],
"advice": "先把这次冲动延后到10:28,期间做一次5分钟快走+喝水,压力场景用深呼吸替代。",
"default": { "algorithm": "staircase_delay_v1" },
@@ -414,3 +426,166 @@ AI 生成说明:
}
}
```
+
+字段说明(新增首页字段):
+- `last_smoke_at`:上次“实际抽烟”时间(忽略忍住记录),格式 `RFC3339`(含时区)。
+- `today_count`:今日抽烟支数(累加 `num`)。
+- `resisted_count`:今日克制次数(`level=0 && num=0`)。
+- `reduced_from_yesterday`:较昨日减少的支数(允许为负数;为负时表示“今天超出昨日”)。
+- `exceeded_yesterday`:是否超出昨日(`true` 表示今天超出昨日,前端可用作单独标识)。
+
+## 14) 获取健康与储蓄统计(合并接口)
+
+`GET /api/v1/smoke/health_savings?period=week&start=2026-01-01&end=2026-01-07`
+
+说明:
+- 合并了"肺部功能恢复"和"节省金额"两个指标,专用于统计页面展示。
+- 支持按周/月/年查询,通过 `period` 参数指定时间范围类型。
+
+参数:
+- `period`(必填):时间范围类型,可选值:
+ - `week`:周(默认本周一至本周日)
+ - `month`:月(默认本月1日至本月最后一日)
+ - `year`:年(默认本年1月1日至本年12月31日)
+- `start`(可选):起始日期(格式 `YYYY-MM-DD`),不传则根据 `period` 自动计算
+- `end`(可选):截止日期(格式 `YYYY-MM-DD`),不传则根据 `period` 自动计算
+
+**计算逻辑**:
+
+1. **肺部功能恢复百分比**:
+ - 基于用户最后一次实际抽烟时间(忽略 `level=0 && num=0` 的忍住记录)
+ - 计算无烟时长(分钟)
+ - 根据医学研究恢复时间线计算恢复百分比(详见 `docs/ALGORITHM.md`)
+ - 公式:
+ ```
+ 无烟天数 = (当前时间 - 最后抽烟时间) / (24 * 60) 分钟
+
+ 恢复百分比计算:
+ - < 14天: (天数 / 14) * 15%
+ - 14-30天: 15% + ((天数 - 14) / 16) * 15%
+ - 30-90天: 30% + ((天数 - 30) / 60) * 20%
+ - > 90天: 50% + ((天数 - 90) / 275) * 50%,最高 100%
+ ```
+
+2. **节省金额**:
+ - 基于用户在统计周期内的实际抽烟量与基线对比
+ - 计算公式:
+ ```
+ 预期总支数 = baseline_cigs_per_day * 周期天数
+ 实际总支数 = 周期内所有记录的 num 累加(排除 level=0 && num=0)
+ 节省支数 = 预期总支数 - 实际总支数
+ 节省包数 = 节省支数 / 20(假设每包20支)
+ 节省金额(分)= 节省包数 * pack_price_cent
+ ```
+ - 若实际总支数 > 预期总支数,则节省金额为 0(不显示负数)
+
+3. **目标金额**:
+ - 默认目标:`baseline_cigs_per_day * 周期天数 / 20 * pack_price_cent`(即完全戒烟节省的金额)
+ - 或使用用户设定的目标金额(如有)
+
+成功响应示例:
+
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": {
+ "period": "week",
+ "start": "2026-01-01",
+ "end": "2026-01-07",
+ "days": 7,
+ "health": {
+ "lung_recovery_percent": 40.5,
+ "smoke_free_minutes": 11520,
+ "smoke_free_days": 8,
+ "last_smoke_at": "2025-12-24T14:30:00+08:00",
+ "recovery_stage": "early", // early(0-14天) / mid(14-30天) / late(30-90天) / advanced(>90天)
+ "next_milestone": {
+ "days_until": 6,
+ "milestone": "2周 - 肺功能提升15%",
+ "percent_at_milestone": 15
+ }
+ },
+ "savings": {
+ "saved_amount_cent": 14500, // 已节省金额(分)
+ "saved_amount_yuan": 145.00, // 已节省金额(元,前端展示用)
+ "target_amount_cent": 20000, // 目标金额(分)
+ "target_amount_yuan": 200.00, // 目标金额(元)
+ "saved_cigs": 58, // 节省支数
+ "expected_cigs": 140, // 预期总支数
+ "actual_cigs": 82, // 实际总支数
+ "progress_percent": 72.5, // 完成进度百分比
+ "pack_price_cent": 2500, // 单包价格(分)
+ "cigs_per_pack": 20 // 每包支数
+ },
+ "profile": {
+ "baseline_cigs_per_day": 20,
+ "pack_price_cent": 2500,
+ "smoking_years": 8
+ },
+ "calculated_at": "2026-01-08T10:00:00+08:00"
+ }
+}
+```
+
+字段说明:
+
+**health(健康数据)**:
+- `lung_recovery_percent`:肺部功能恢复百分比(0-100)
+- `smoke_free_minutes`:无烟时长(分钟)
+- `smoke_free_days`:无烟天数(保留1位小数)
+- `last_smoke_at`:最后一次实际抽烟时间(RFC3339格式)
+- `recovery_stage`:恢复阶段标识
+- `next_milestone`:下一个里程碑信息
+
+**savings(储蓄数据)**:
+- `saved_amount_cent`:已节省金额(分,用于计算)
+- `saved_amount_yuan`:已节省金额(元,用于前端展示)
+- `target_amount_cent`:目标金额(分)
+- `target_amount_yuan`:目标金额(元)
+- `saved_cigs`:节省的支数
+- `expected_cigs`:预期总支数(基线 × 天数)
+- `actual_cigs`:实际总支数
+- `progress_percent`:完成进度百分比(saved_amount / target_amount * 100)
+- `pack_price_cent`:单包价格(分)
+- `cigs_per_pack`:每包支数(默认20)
+
+**period 参数说明**:
+
+- `period=week`(周):
+ - 默认:本周一 00:00:00 至 本周日 23:59:59
+ - 若传 `start`,则 `end = start + 6 天`
+
+- `period=month`(月):
+ - 默认:本月1日 00:00:00 至 本月最后一日 23:59:59
+ - 若传 `start`,则 `end = start 所在月的最后一日`
+
+- `period=year`(年):
+ - 默认:本年1月1日 00:00:00 至 本年12月31日 23:59:59
+ - 若传 `start`,则 `end = start 所在年的12月31日`
+
+curl 示例:
+
+```bash
+# 查询本周数据
+curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/health_savings?period=week' \
+ -H 'Authorization: Bearer wx-session-key'
+
+# 查询本月数据
+curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/health_savings?period=month' \
+ -H 'Authorization: Bearer wx-session-key'
+
+# 查询本年数据
+curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/health_savings?period=year' \
+ -H 'Authorization: Bearer wx-session-key'
+
+# 查询指定日期范围
+curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/health_savings?period=week&start=2026-01-01&end=2026-01-07' \
+ -H 'Authorization: Bearer wx-session-key'
+```
+
+**注意事项**:
+1. 若用户尚未补全 `profile`(缺少 `baseline_cigs_per_day` 或 `pack_price_cent`),相关计算字段可能为 0 或使用默认值
+2. 若用户从未抽烟(无历史记录),`last_smoke_at` 可能不存在,肺部恢复百分比按最大恢复计算
+3. 节省金额计算时,若实际支数 > 预期支数,`saved_amount_cent` 为 0(不显示负数)
+4. 时间范围计算时,使用用户所在时区(后端需根据用户配置或默认使用 UTC+8)