行程逻辑重构:计划/实际双轨、状态只属于计划、开始与完成记录真实时间 #48

Open
opened 2026-11-05 01:09:07 +00:00 by laoyang · 0 comments
Owner

行程逻辑重构:计划/实际双轨、状态只属于计划行程、开始/完成记录真实时间

用户完整需求(2026-11-05)

用户可以添加一个计划行程,也可以添加一个实际行程。实际行程是没有状态的,实际行程就是实际行程,没有所谓的状态。实际行程指的是已经发生的事情,它没有什么状态了,只有计划行程有状态。

添加计划行程时,刚开始添加的时候,它的状态就是"计划中"。当我开始执行这个计划时,就会有一个按钮说"开始执行"。但是这个计划的时间和真正开始的时间有可能有差别。比如,我计划今天 8:00 到上午 10:00 开车去一个公园,但我可能出门晚了,在 8:10 或者 8:30 才开始点击"开始"按钮。这时候就要记录住 8:30 这个时间,因为 8:30 会成为实际行程的开始时间。也就是说,原来计划的时间和现在真正开始的时间都要记录。

一旦开始,这个行程的状态就变成"进行中"。等到走完了、结束了,比如我 8:30 开始走,10:30 结束了,这时候我点"完成"。这时候这个内容或者计划行程就变成一个实际行程。一个实际行程没有再没有状态了,因为实际已经发生完了,它再有状态就没有意义了。

但如果这个计划我没有去做…我可以直接对这个计划行程点击一个按钮,然后它就变成了"取消"或者"删除"。那么这个行程就单独列在下面,作为删除的行程。因为到最后整个旅程结束之后,我们最终看到的是实际行程。既然已经没去做,但这个数据我们又不删它,而是把它单独放在下面,形成一个列表,用来存放未执行的计划、要删除的计划。

所以这样的话,计划行程右上角就不是两个按钮了,而是至少四个按钮:一个是"开始",一个是"完成",一个是"编辑",一个是"删除"。所谓的删除,指的是我直接把这个计划给删掉了。在删除前面还应该有一个按钮,这个按钮是取消,指的就是不去了,但这个事情我并不把它删掉。从数据库当中,它仍然是存在的,只不过我改变计划,把它取消了,不再去了。

所以取消和删除是不一样的。

核心模型(重构后)

两个独立的维度

维度 取值 含义
stage(阶段) plan / actual / skipped 这段行程属于哪条时间线
status(状态) 仅 plan 有意义 planned / ongoing;done → 转成 actual

状态流转(只发生在计划行程上)

                    ┌──────────────────────────────────┐
                    │  stage=plan, status=planned       │  ← 新建计划行程
                    │  右上角:开始 / 完成 / 编辑 / 删除  │
                    └───────┬──────────────┬───────────┘
                            │              │
              点「开始」     │              │  点「取消」
                 ↓          │              ↓
    ┌────────────────────┐  │    ┌──────────────────────┐
    │ stage=plan          │  │    │ stage=skipped         │
    │ status=ongoing      │  │    │ status=cancelled      │
    │ actual_started_at=  │  │    │ 列入「未成行」列表      │
    │   点击瞬间的真实时间  │  │    │ 数据保留(不删)        │
    └────────┬───────────┘  │    └──────────────────────┘
             │              │
    点「完成」│              │  点「删除」
             ↓              ↓
  ┌──────────────────────┐  ┌──────────────────┐
  │ stage=actual          │  │ 软删除            │
  │ status=done           │  │ deleted_at 置位    │
  │ actual_ended_at=真实结束│  │ 彻底不再显示       │
  │ ⭐ 状态对实际行程无意义  │  └──────────────────┘
  │    界面不再显示状态     │
  └──────────────────────┘

关键语义区分

动作 语义 数据库 界面
完成 计划做完了 → 转成实际行程 stage=actual,记录 actual_ended_at 进「实际行程」分组
取消 不去了 → 保留数据但标记未成行 stage=skipped,status=cancelled 进「未成行」分组(列表底部)
删除 彻底不要了 deleted_at 置位 不显示

新增数据字段

计划时间和实际时间要同时保留:

字段 含义
starts_at / ends_at 计划的开始/结束(已有)
actual_started_at 点「开始」时的真实时间(新增)
actual_ended_at 点「完成」时的真实时间(新增)

⇒ 详情页可对比"计划 8:00–10:00 / 实际 8:30–10:30"。

界面改动

计划行程卡片(右上角四个按钮)

开始 完成 编辑 删除(+ 原有的取消,共 5 个)

用户原话:"至少四个按钮:一个是开始,一个是完成,一个是编辑,一个是删除…在删除前面还应该有一个按钮,这个按钮是取消"

实际行程卡片

不显示任何状态,只保留 编辑 删除。

分组顺序

实际行程
  → 展开显示(旅程结束时最终要看的就是这些)

计划行程
  → 展开显示(还没开始的)

未成行 / 已取消
  → 折叠,放最下面(用户明确要求"单独列在下面")

验收

  • 新建计划行程 → stage=plan, status=planned
  • 新建实际行程 → stage=actual,无 status 概念
  • 点「开始」→ status=ongoing + 记录 actual_started_at 真实时刻
  • 点「完成」→ stage=actual + 记录 actual_ended_at,状态不再显示
  • 点「取消」→ stage=skipped,数据保留,列在底部「未成行」组
  • 点「删除」→ 软删除,彻底不显示
  • 取消 ≠ 删除(前者保留数据,后者软删)
  • 计划行程卡片右上角有 开始/完成/编辑/取消/删除
  • 实际行程卡片不显示任何状态
  • 详情页能同时看到计划时间和实际时间
  • 鸿蒙端与网页端行为一致

为什么单独建单

推翻并取代 #47 里「状态由动作驱动」的那部分设计:#47 仍允许多种状态互转且没区分计划/实际两条线,本单按用户新说明重定义——实际行程无状态、完成即转实际、取消与删除是两件事、新增真实开始/结束时间字段

# 行程逻辑重构:计划/实际双轨、状态只属于计划行程、开始/完成记录真实时间 ## 用户完整需求(2026-11-05) > 用户可以添加一个计划行程,也可以添加一个实际行程。**实际行程是没有状态的**,实际行程就是实际行程,没有所谓的状态。实际行程指的是已经发生的事情,它没有什么状态了,**只有计划行程有状态**。 > > 添加计划行程时,刚开始添加的时候,它的状态就是"计划中"。当我开始执行这个计划时,就会有一个按钮说"开始执行"。但是这个计划的时间和真正开始的时间有可能有差别。比如,我计划今天 8:00 到上午 10:00 开车去一个公园,但我可能出门晚了,在 8:10 或者 8:30 才开始点击"开始"按钮。这时候就要**记录住 8:30 这个时间**,因为 8:30 会成为实际行程的开始时间。也就是说,**原来计划的时间和现在真正开始的时间都要记录**。 > > 一旦开始,这个行程的状态就变成"进行中"。等到走完了、结束了,比如我 8:30 开始走,10:30 结束了,这时候我点"完成"。这时候这个内容或者计划行程就**变成一个实际行程**。一个实际行程没有再没有状态了,因为实际已经发生完了,它再有状态就没有意义了。 > > 但如果这个计划我没有去做…我可以直接对这个计划行程点击一个按钮,然后它就变成了"取消"或者"删除"。那么这个行程就**单独列在下面**,作为删除的行程。因为到最后整个旅程结束之后,我们最终看到的是实际行程。既然已经没去做,但这个数据我们又不删它,而是把它单独放在下面,形成一个列表,用来存放未执行的计划、要删除的计划。 > > 所以这样的话,计划行程右上角就**不是两个按钮了,而是至少四个按钮**:一个是"开始",一个是"完成",一个是"编辑",一个是"删除"。所谓的删除,指的是我直接把这个计划给删掉了。在删除前面还应该有一个按钮,这个按钮是**取消**,指的就是不去了,但这个事情我并不把它删掉。从数据库当中,它仍然是存在的,只不过我改变计划,把它取消了,不再去了。 > > 所以**取消和删除是不一样的**。 ## 核心模型(重构后) ### 两个独立的维度 | 维度 | 取值 | 含义 | |---|---|---| | **stage**(阶段) | `plan` / `actual` / `skipped` | 这段行程属于哪条时间线 | | **status**(状态) | 仅 `plan` 有意义 | `planned` / `ongoing`;`done` → 转成 `actual` | ### 状态流转(只发生在计划行程上) ``` ┌──────────────────────────────────┐ │ stage=plan, status=planned │ ← 新建计划行程 │ 右上角:开始 / 完成 / 编辑 / 删除 │ └───────┬──────────────┬───────────┘ │ │ 点「开始」 │ │ 点「取消」 ↓ │ ↓ ┌────────────────────┐ │ ┌──────────────────────┐ │ stage=plan │ │ │ stage=skipped │ │ status=ongoing │ │ │ status=cancelled │ │ actual_started_at= │ │ │ 列入「未成行」列表 │ │ 点击瞬间的真实时间 │ │ │ 数据保留(不删) │ └────────┬───────────┘ │ └──────────────────────┘ │ │ 点「完成」│ │ 点「删除」 ↓ ↓ ┌──────────────────────┐ ┌──────────────────┐ │ stage=actual │ │ 软删除 │ │ status=done │ │ deleted_at 置位 │ │ actual_ended_at=真实结束│ │ 彻底不再显示 │ │ ⭐ 状态对实际行程无意义 │ └──────────────────┘ │ 界面不再显示状态 │ └──────────────────────┘ ``` ### 关键语义区分 | 动作 | 语义 | 数据库 | 界面 | |---|---|---|---| | **完成** | 计划做完了 → 转成实际行程 | `stage=actual`,记录 `actual_ended_at` | 进「实际行程」分组 | | **取消** | 不去了 → 保留数据但标记未成行 | `stage=skipped`,`status=cancelled` | 进「未成行」分组(列表底部) | | **删除** | 彻底不要了 | `deleted_at` 置位 | 不显示 | ## 新增数据字段 计划时间和实际时间要**同时保留**: | 字段 | 含义 | |---|---| | `starts_at` / `ends_at` | **计划**的开始/结束(已有) | | `actual_started_at` | 点「开始」时的**真实**时间(新增) | | `actual_ended_at` | 点「完成」时的**真实**时间(新增) | ⇒ 详情页可对比"计划 8:00–10:00 / 实际 8:30–10:30"。 ## 界面改动 ### 计划行程卡片(右上角四个按钮) `开始` `完成` `编辑` `删除`(+ 原有的取消,共 5 个) > 用户原话:"至少四个按钮:一个是开始,一个是完成,一个是编辑,一个是删除…在删除前面还应该有一个按钮,这个按钮是取消" ### 实际行程卡片 **不显示任何状态**,只保留 `编辑` `删除`。 ### 分组顺序 ``` 实际行程 → 展开显示(旅程结束时最终要看的就是这些) 计划行程 → 展开显示(还没开始的) 未成行 / 已取消 → 折叠,放最下面(用户明确要求"单独列在下面") ``` ## 验收 - [ ] 新建计划行程 → `stage=plan`, `status=planned` - [ ] 新建实际行程 → `stage=actual`,**无 status 概念** - [ ] 点「开始」→ `status=ongoing` + 记录 `actual_started_at` 真实时刻 - [ ] 点「完成」→ `stage=actual` + 记录 `actual_ended_at`,**状态不再显示** - [ ] 点「取消」→ `stage=skipped`,数据保留,列在底部「未成行」组 - [ ] 点「删除」→ 软删除,彻底不显示 - [ ] 取消 ≠ 删除(前者保留数据,后者软删) - [ ] 计划行程卡片右上角有 开始/完成/编辑/取消/删除 - [ ] 实际行程卡片不显示任何状态 - [ ] 详情页能同时看到计划时间和实际时间 - [ ] 鸿蒙端与网页端行为一致 --- ### 为什么单独建单 推翻并取代 #47 里「状态由动作驱动」的那部分设计:#47 仍允许多种状态互转且没区分计划/实际两条线,本单按用户新说明重定义——实际行程无状态、完成即转实际、取消与删除是两件事、新增真实开始/结束时间字段
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/FamilyBook#48