feat: 增加时区选择(自动检测,回退墨尔本)
顶栏新增时区选择器:加载时自动检测用户所在时区(Intl.DateTimeFormat), 检测不到则默认澳大利亚墨尔本。选定时区作为新建事件的默认 tzid 与下载 ICS 的 X-WR-TIMEZONE,不做时间换算(应用内部为 wall-clock 字符串)。 - 新增 src/lib/timezone.js(detect/list/validate/默认值) - useCalendar 持 state.timezone、setTimezone、addEvent 传 tzid、serialize 注入 X-WR-TIMEZONE - HeaderBar 顶栏下拉选择器 + i18n 文案 - 新增 test/timezone.test.js(15 项),全量 57 项通过 - README 简述功能,细节移至 docs/timezone.md
This commit is contained in:
49
docs/timezone.md
Normal file
49
docs/timezone.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 时区选择
|
||||
|
||||
timeTableFix 顶栏提供时区选择器。加载时自动检测用户所在时区,检测不到则默认 **澳大利亚墨尔本(`Australia/Melbourne`)**。
|
||||
|
||||
## 检测逻辑
|
||||
|
||||
`src/lib/timezone.js` 的 `detectTimezone()`:
|
||||
|
||||
1. 读取 `new Intl.DateTimeFormat().resolvedOptions().timeZone`(浏览器/Node 标准 API)。
|
||||
2. 若抛错、返回空串或格式不合法,回退 `DEFAULT_TIMEZONE`(`Australia/Melbourne`)。
|
||||
|
||||
非安全上下文(无 `https`)或极旧环境可能拿不到时区,此时一律回退墨尔本。
|
||||
|
||||
## 下拉列表来源
|
||||
|
||||
`listTimezones()` = 精选常用 IANA 时区(`COMMON_TIMEZONES`,含墨尔本/上海/UTC 等)∪ 运行时 `Intl.supportedValuesOf('timeZone')`(若可用),去重后排序,`UTC` 置顶。旧浏览器不支持 `supportedValuesOf` 时静默降级为仅精选列表,保证下拉始终可用、无外部依赖。
|
||||
|
||||
## 作用范围(设计要点)
|
||||
|
||||
应用内部所有日期/时间均为 **wall-clock 字符串**(`YYYY-MM-DD` + `HH:MM`,见 `date.js`),**不做任何时区换算**。时区仅是一个挂在事件上的 IANA 标识(`tzid`),在 ICS 序列化/反序列化时作为 `DTSTART`/`DTEND` 的 `TZID` 参数读写。
|
||||
|
||||
因此选定时区的作用是**日历级默认值/标签**,而非时间换算层:
|
||||
|
||||
| 行为 | 是否受选定时区影响 |
|
||||
|---|---|
|
||||
| 新建事件(「新增日程」)的 `tzid` | ✅ 使用选定时区 |
|
||||
| 下载 ICS 的 `X-WR-TIMEZONE` | ✅ 写入选定时区 |
|
||||
| 已导入事件的 `tzid` | ❌ 保留原始 TZID,不覆盖、不换算 |
|
||||
| 日期/时间数值(编辑、预览、整理) | ❌ 始终 wall-clock,不换算 |
|
||||
| 间隔去重(`organize.js`) | ❌ 不读 `tzid`,不受影响 |
|
||||
|
||||
### 为何不换算
|
||||
|
||||
- 应用面向「整理/编辑日程文本」而非「跨时区会议调度」,wall-clock 直观且无歧义。
|
||||
- `organize.js` 按 `[summary, location, 开始时间, 时长]` 合并重复,引入换算会改变合并键、破坏既有 round-trip 测试。
|
||||
- 已导入事件保留原 TZID 保证 `parse(serialize(parse(x)))` 等价(见 `ical-io.test.js` round-trip 用例)。
|
||||
|
||||
## 实现位置
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `src/lib/timezone.js` | 新增:检测/列表/校验/默认值 |
|
||||
| `src/composables/useCalendar.js` | `state.timezone`(初始 `detectTimezone()`)、`setTimezone()`、`addEvent` 传入 tzid、`serialize` 注入 `X-WR-TIMEZONE` |
|
||||
| `src/components/HeaderBar.vue` | 顶栏 `<select>` 选择器 |
|
||||
| `src/i18n/locales/{zh-CN,en}.js` | `header.timezone` 文案 |
|
||||
|
||||
## 嵌入 mainPage
|
||||
|
||||
时区状态属于 timeTableFix 自有单例 store,嵌入 mainPage 时随子模块独立运作,不与父项目共享。语言切换仍经 `:locale` prop 桥接(与时区无关)。
|
||||
Reference in New Issue
Block a user