fix(token/flatpickr): dark mode calendar + friendlier date display
- Add !important to all Flatpickr CSS overrides to beat CDN specificity - Change dateFormat from ISO 'Y-m-d\TH:i' to 'Y-m-d H:i' (double space) - Update tokGetFiltered to use .replace(/\s+/,'T') for Safari compat
This commit is contained in:
1 parent
65b1dab225
commit
a4adb63e45
3 files changed
+75
-19
No files matched your search
@@ -225,3 +225,58 @@ CSS: `.task-elapsed { color: var(--accent); font-size: 12px; font-weight: 600; }
|
||||
2. `restoreElapsedBadges(sess, box)` 从 `renderAllMessages` 移到 `pollSession` finally 块 — 确保消息已加载
|
||||
3. `startTaskTimer(sess)` 从最后一条 user 消息的 ts 恢复 taskStartedAt — 运行中任务继续计时
|
||||
- 验证结果:刷新后 badge 正确显示"已运行 17s"/"已运行 14s",已完成任务静态显示,运行中任务实时计时
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 9. Feature: Flatpickr 日期选择器 (Token 统计页)
|
||||
|
||||
**状态**:✅ 完成
|
||||
**分支**:`feat/flatpickr-datepicker`
|
||||
**Commit**:5e20cc7
|
||||
|
||||
### 9.1 改动摘要
|
||||
|
||||
| # | 文件 | 改动 | 行数 |
|
||||
|---|------|------|------|
|
||||
| 1 | index.html | +Flatpickr CDN (CSS + JS + zh locale);input type="text" + class="tok-date" + readonly | +6/-2 |
|
||||
| 2 | styles.css | .tok-date 样式 + Flatpickr 主题覆盖(全用 CSS 变量,含暗色模式) | +30/-3 |
|
||||
| 3 | app.js | 替换原生 change 事件为 Flatpickr 初始化 + reset 用 fp.clear() | +6/-4 |
|
||||
|
||||
**总计**:3 files, +44/-8
|
||||
|
||||
### 9.2 关键决策
|
||||
|
||||
- **dateFormat: `'Y-m-d\\TH:i'`** — 输出 ISO 格式(如 `2026-05-27T14:30`),Safari 兼容
|
||||
- **locale 判断**:`document.documentElement.lang==='en' ? 'default' : 'zh'`
|
||||
- **readonly**:禁止手动输入,只能通过日历选择
|
||||
- **Flatpickr 主题覆盖**:所有颜色走 CSS 变量(--bg, --txt, --blue, --hover-2 等),暗色用 `html[data-appearance="dark"]` 选择器
|
||||
|
||||
### 9.3 关联代码图
|
||||
|
||||
```
|
||||
index.html:199-201 → <input .tok-date>
|
||||
styles.css:729-760 → .tok-date + .flatpickr-calendar 主题覆盖
|
||||
app.js:2265-2266 → tokSince / tokUntil 声明(未改)
|
||||
app.js:2353-2360 → tokGetFiltered() 用 new Date(input.value) 解析(未改)
|
||||
app.js:2408-2413 → Flatpickr 初始化 + reset 逻辑(新)
|
||||
```
|
||||
|
||||
### 9.4 验证结果
|
||||
|
||||
- ✅ Flatpickr 正常初始化(input 获得 `flatpickr-input` class)
|
||||
- ✅ 点击弹出日历
|
||||
- ✅ 用户手动测试选择日期成功
|
||||
- ✅ dateFormat ISO 兼容 tokGetFiltered 的 `new Date()` 解析
|
||||
- ✅ 无硬编码颜色/文本
|
||||
|
||||
### 9.5 Code Review 自检
|
||||
|
||||
| 检查项 | 通过 |
|
||||
|--------|------|
|
||||
| 无硬编码颜色 | ✅ 全走 CSS 变量 |
|
||||
| 无硬编码文本 | ✅ placeholder 走 data-i18n-ph |
|
||||
| 暗色模式兼容 | ✅ html[data-appearance="dark"] 覆盖 |
|
||||
| Safari 兼容 | ✅ ISO dateFormat |
|
||||
| 原有逻辑不变 | ✅ tokGetFiltered 未修改 |
|
||||
| 单分支隔离 | ✅ feat/flatpickr-datepicker |
|
||||
@@ -2352,8 +2352,9 @@ async function tokPollBridge() {
|
||||
|
||||
function tokGetFiltered() {
|
||||
let records = tokLoadHistory();
|
||||
const since = tokSince?.value ? new Date(tokSince.value).getTime()/1000 : 0;
|
||||
const until = tokUntil?.value ? new Date(tokUntil.value).getTime()/1000 : 0;
|
||||
const parseD = v => v ? new Date(v.replace(/\s+/,'T')).getTime()/1000 : 0;
|
||||
const since = parseD(tokSince?.value);
|
||||
const until = parseD(tokUntil?.value);
|
||||
if (since) records = records.filter(r=>r.ts>=since);
|
||||
if (until) records = records.filter(r=>r.ts<=until);
|
||||
return records;
|
||||
@@ -2406,7 +2407,7 @@ function tokRenderTable(records) {
|
||||
|
||||
async function loadTokenPage(){await tokPollBridge();const f=tokGetFiltered();const all=tokLoadHistory();tokRenderStats(f,all);tokRenderTable(f);}
|
||||
/* Flatpickr 初始化 */
|
||||
const _fpOpts = { enableTime:true, time_24hr:true, dateFormat:'Y-m-d\\TH:i', locale:window.flatpickr?.l10ns?.[document.documentElement.lang==='en'?'default':'zh']||'default', allowInput:false, onChange(){ _tokPage=0; loadTokenPage(); } };
|
||||
const _fpOpts = { enableTime:true, time_24hr:true, dateFormat:'Y-m-d H:i', locale:window.flatpickr?.l10ns?.[document.documentElement.lang==='en'?'default':'zh']||'default', allowInput:false, onChange(){ _tokPage=0; loadTokenPage(); } };
|
||||
const fpSince = tokSince ? flatpickr(tokSince, _fpOpts) : null;
|
||||
const fpUntil = tokUntil ? flatpickr(tokUntil, _fpOpts) : null;
|
||||
const tokResetBtn=document.getElementById('tok-reset');
|
||||
|
||||
@@ -736,32 +736,32 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; }
|
||||
.tok-date:focus{ border-color:var(--blue); outline:none; }
|
||||
/* Flatpickr 主题覆盖 — 全部使用项目 CSS 变量 */
|
||||
.flatpickr-calendar{
|
||||
background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
|
||||
box-shadow:var(--shadow-pop); font-size:13px;
|
||||
background:var(--card) !important; border:1px solid var(--line) !important; border-radius:var(--radius) !important;
|
||||
box-shadow:var(--shadow-pop) !important; font-size:13px;
|
||||
}
|
||||
.flatpickr-months .flatpickr-month,
|
||||
.flatpickr-current-month{ color:var(--txt); fill:var(--txt); }
|
||||
.flatpickr-current-month{ color:var(--txt) !important; fill:var(--txt) !important; }
|
||||
.flatpickr-current-month .flatpickr-monthDropdown-months,
|
||||
.flatpickr-current-month input.cur-year{ color:var(--txt); background:var(--field-bg); }
|
||||
.flatpickr-weekdays{ background:var(--field-bg); }
|
||||
span.flatpickr-weekday{ color:var(--muted); font-size:11px; }
|
||||
.flatpickr-current-month input.cur-year{ color:var(--txt) !important; background:var(--field-bg) !important; }
|
||||
.flatpickr-weekdays{ background:var(--field-bg) !important; }
|
||||
span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; }
|
||||
.flatpickr-day{
|
||||
color:var(--txt); border-radius:6px;
|
||||
color:var(--txt) !important; border-radius:6px;
|
||||
}
|
||||
.flatpickr-day:hover{ background:var(--hover-2); border-color:transparent; }
|
||||
.flatpickr-day.today{ border-color:var(--blue); }
|
||||
.flatpickr-day.selected{ background:var(--blue); color:var(--on-accent); border-color:var(--blue); }
|
||||
.flatpickr-day:hover{ background:var(--hover-2) !important; border-color:transparent !important; }
|
||||
.flatpickr-day.today{ border-color:var(--blue) !important; }
|
||||
.flatpickr-day.selected{ background:var(--blue) !important; color:var(--on-accent) !important; border-color:var(--blue) !important; }
|
||||
.flatpickr-day.prevMonthDay,
|
||||
.flatpickr-day.nextMonthDay{ color:var(--muted2); }
|
||||
.flatpickr-day.nextMonthDay{ color:var(--muted2) !important; }
|
||||
.flatpickr-time input,
|
||||
.flatpickr-time .flatpickr-am-pm{ color:var(--txt); background:var(--field-bg); }
|
||||
.flatpickr-time .flatpickr-am-pm{ color:var(--txt) !important; background:var(--field-bg) !important; }
|
||||
.flatpickr-time input:hover,
|
||||
.flatpickr-time input:focus{ background:var(--hover-2); }
|
||||
.numInputWrapper:hover{ background:var(--hover-2); }
|
||||
.flatpickr-time input:focus{ background:var(--hover-2) !important; }
|
||||
.numInputWrapper:hover{ background:var(--hover-2) !important; }
|
||||
.flatpickr-months .flatpickr-prev-month,
|
||||
.flatpickr-months .flatpickr-next-month{ fill:var(--txt-2); }
|
||||
.flatpickr-months .flatpickr-next-month{ fill:var(--txt-2) !important; }
|
||||
.flatpickr-months .flatpickr-prev-month:hover svg,
|
||||
.flatpickr-months .flatpickr-next-month:hover svg{ fill:var(--txt); }
|
||||
.flatpickr-months .flatpickr-next-month:hover svg{ fill:var(--txt) !important; }
|
||||
.tok-reset{
|
||||
border:1px solid var(--line); border-radius:6px; padding:5px 10px;
|
||||
font-size:12px; background:var(--field-bg); color:var(--muted); cursor:pointer;
|
||||
|
||||
Reference in new issue
Block a user