wangwangit
|
df5ee5b241
|
fix: 修复编辑订阅不生成支付记录及测试通知不写入历史的问题
- updateSubscription: 当订阅有金额但缺少 initial 支付记录时自动补建
- testSingleSubscriptionNotification: 传递 env/subId 使通知日志正常写入
- .gitignore: 排除 AI 工具目录和环境变量文件
|
2026-05-27 20:35:18 +08:00 |
|
wangwangit
|
549dabdcf1
|
fix(#171,#166): 分类下拉框从 API 加载 + 前端日期时区修复
- #171: initCustomDropdown 支持输入过滤,打开模态框时从
GET /api/categories 加载已保存分类并与默认选项合并
- #166: 前端日期处理改用时区感知函数(createLocalCalendarDate、
getTodayDateStringInTimezone),修复凌晨创建订阅日期偏移
|
2026-05-27 10:39:14 +08:00 |
|
wangwangit
|
77ff034be5
|
fix(#166): 订阅创建/更新/续订使用用户配置时区解析日期
- time.js: 新增 parseDateInputInTimezone、addCalendarPeriodInTimezone 等
时区感知日期工具函数
- subscriptions.js: createSubscription/updateSubscription/manualRenewSubscription
使用 config.TIMEZONE 解析前端传入的日期字符串,修复北京时间凌晨
0-8 点创建订阅日期偏移一天的问题
|
2026-05-27 10:38:06 +08:00 |
|
wangwangit
|
1cb8c9ed00
|
feat(ui): 管理页底部显示版本号
- 从 GET /api/version 获取版本号
- 显示在页面底部
- Issue #168
|
2026-05-26 23:41:31 +08:00 |
|
wangwangit
|
5c1a02b9fd
|
feat(ui): 分类下拉框支持从 API 加载 + 输入过滤
- 打开模态框时从 GET /api/categories 加载已保存分类
- 合并硬编码默认分类(去重,保存的排前面)
- 输入时实时过滤下拉选项
- Issue #171 前端部分
|
2026-05-26 23:40:29 +08:00 |
|
wangwangit
|
a25c817c8f
|
feat(api): 新增版本号端点 + 分类管理 + 下次提醒时间 API
- GET /api/version 返回当前版本号 (3.0.0)
- GET/POST /api/categories 管理分类列表
- GET /api/subscriptions/:id/next-reminder 返回下次提醒时间
- Issue #168 #170 #171
|
2026-05-26 23:25:34 +08:00 |
|
wangwangit
|
83c40d7e43
|
feat(reminder): 新增 getNextFireTime 计算规则下次触发时间
- 支持 before_expiry / on_expiry / after_expiry 三种规则类型
- 纯函数设计,便于单元测试
- Issue #170
|
2026-05-26 23:25:22 +08:00 |
|
wangwangit
|
31c44f7325
|
fix(bark): 修复自定义 Bark 服务器 URL 认证失败
- 从 URL 提取 Basic Auth 凭证并添加 Authorization header
- 清理 URL 中的凭证信息后再发请求
- 支持 URL 编码的特殊字符(如 p%40ss)
- Issue #169
|
2026-05-26 23:25:12 +08:00 |
|
wangwangit
|
823bcc6f00
|
fix(timezone): 修复创建/更新/续订订阅时忽略用户时区的 bug
- 改用 getNowInTimezone(config.TIMEZONE) 替代 getCurrentTimeInTimezone('UTC')
- 用 getTimezoneMidnightTimestamp 做跨日判断
- 修复 #166: 北京用户凌晨创建订阅默认日期变前一天
- 创建/更新订阅时自动保存分类到分类列表
|
2026-05-26 23:25:07 +08:00 |
|
wangwangit
|
d9833eca3c
|
feat(categories): 新增分类标签持久化存储模块
- KV 存储分类列表(去重 + 排序)
- 新增 getCategories / addCategory 函数
- Issue #171
|
2026-05-26 23:24:57 +08:00 |
|
wangwangit
|
6e1b506c8a
|
polish: 默认时区 Asia/Shanghai + 清理代码与文档中的版本号字眼
时区默认值:
- DEFAULT_CONFIG.TIMEZONE: 'UTC' → 'Asia/Shanghai'
- 配置页时区下拉用 <optgroup> 把中国标准时间钉到"🇨🇳 推荐"分组
- 未知时区 fallback 也改 Asia/Shanghai
去除版本号字眼(45 文件):
- 全部 "维护人:v3 重构 (2026-05)" 文件头注释删除
- 文件描述里的 "(v3 重写)" "(v3 新增)" 等去掉
- @deprecated v2 兼容 → @deprecated 旧版兼容函数
- 注释里的 "v2/v3" 替换为中性表述("早期版本""旧调度器""既有客户端"等)
- src/api/handlers/v3-routes.js → src/api/handlers/extras.js
- tests/api/v3-routes.test.js → tests/api/extras-routes.test.js
- 函数名 handleV3Routes → handleExtraRoutes
- README / MIGRATION / ARCHITECTURE 整体重写:
- README 去掉 "v3 关键改进里程碑" 段,改写为标准产品功能介绍
- MIGRATION 重写为通用"升级指南",用"旧版本"代替 v2
- ARCHITECTURE 模块图与流程描述去掉所有 v3 标签
- package.json description 去掉 v3
- wrangler.toml / wrangler.dev.toml 注释里 v3 去掉
故意保留的(持久化的 KV 数据兼容性标识):
- schema_version 字符串值 'v3'
- migrate:subscriptions_v3 / reminder_rules_v3 / scheduler_logs_v3 step ID
- subscriptions_v2_backup KV key
- 文档对这些标识有显式说明:"是 KV 内部数据兼容性标记,与产品版本号无关"
171 测试全绿;lint 干净;wrangler dry-run 571 KiB / gzip 119 KiB。
|
2026-05-24 20:04:16 +08:00 |
|
wangwangit
|
bbcad369af
|
fix(ui): 通知历史页布局与其他后台页面对齐
我之前的版本用了一个简化的 nav,跟 admin/config/dashboard 三个页面完全不
匹配——没 logo 没汉堡菜单没实时时钟,body 也没用统一的 `bg-gray-100
min-h-screen` 容器,导致用户从订阅列表点"通知历史"就跳到一个长得不像
同一个产品的页面。
重写 src/views/notifyLogsPage.html:
- 复用与 admin/config/dashboard 完全相同的导航结构:
- 左侧:fa-calendar-check 图标 + "订阅管理系统" 标题 + 实时时钟
- 右侧:5 个导航链接(仪表盘/订阅列表/通知历史/系统配置/退出)
- 移动端:汉堡按钮 + 同一份折叠菜单
- "通知历史" 链接 active 高亮 (indigo-600 + border-b-2)
- 复用 `bg-gray-100 min-h-screen` body 与 `max-w-7xl mx-auto px-4` 主容器
- 复用 stat-card / btn-primary 风格的统一组件类
- 复用 ${themeResources} 注入暗色主题
- 增加:移动端菜单 JS / 实时时钟 JS / formatTimezoneDisplay
(与其他页面一致的实现)
- 筛选条改为下拉选择订阅(subId 选项从 /api/subscriptions 动态填充,
不再让用户手敲 ID)
171 测试全绿;wrangler dry-run 570 KiB。
dev 环境实测确认:/admin/notify-logs 与 /admin/* 其它三页 nav 标记数
(logo×1 hamburger×4 clock×3)完全一致。
|
2026-05-24 19:24:25 +08:00 |
|
wangwangit
|
a1fe2dcbf4
|
fix(scheduler): NOTIFICATION_HOURS 通配符 "*" 被 padStart 误处理为 "0*"
本地 wrangler dev 测试时发现:用户配置 "*" 后,inWindow 始终判定 false,
反而比 v2 不能用。
根因:v3 scheduler 对配置数组无脑 padStart(2,'0'),把 '*' 变成 '0*'。
修复 src/services/scheduler.js:normalize 时仅对纯数字 padStart;
'*' / 'ALL' 保持原样。
测试 tests/services/scheduler.test.js:新增 "场景5:通配符不应被 padStart"
确保回归。
171 测试全绿。
发现自我们 @ 2026-05-24 19:11 在本地 dev 环境实测中。
|
2026-05-24 19:13:06 +08:00 |
|
wangwangit
|
868263a1c7
|
fix: 货币显示一致性 + 仪表盘读新调度日志(Task 12)
修复 #160:v2 在 4 个文件里重复定义 currencySymbols;JPY 与 CNY 同
符号 ¥ 易混淆。
- 新建 src/core/currency-format.js:CURRENCY_SYMBOLS 单一来源 +
formatAmount(amount, currency) helper,JPY 改前缀为 'JP¥' 区分
- src/services/notify/reminder.js 与 src/api/handlers/subscriptions.js
改用 formatAmount,删除两份重复定义
仪表盘 (#149):
- src/api/handlers/dashboard.js 重写,scheduler_status / status_history
改从 scheduler-logs.repo.getRecent(10) 取
- 兼容老前端字段(lastRunAt / shouldNotifyThisHour 等)做扁平转换
- 时区从 config.TIMEZONE 读取(不再硬编码 UTC)
- 响应增加顶层 timezone 字段
170 测试全绿;wrangler dry-run 560 KiB / gzip 118 KiB。
Refs Task 12 of refactor/v3-product-grade plan.
|
2026-05-24 18:31:05 +08:00 |
|
wangwangit
|
8518045408
|
feat(ui): 通知历史页 + 时区感知配置页(Task 11)
新增 src/views/notifyLogsPage.html:
- /admin/notify-logs 路由(admin.js 登记)
- 顶部筛选:subId / channel / status / 最近 N 小时
- 概览卡片:总记录 / 成功 / 失败 / 最近发送
- 调度执行预览(最近 10 次 sched_log,可折叠)
- 主表格:时间(用户 TZ)/ 订阅名 / 规则 ID / 渠道 / 状态徽章 / 详情展开
- 失败行红底,成功行绿底;详情含 raw 响应与通知正文展开
src/views/configPage.html:
- 通知时段标签从"(UTC)"改为"(按你的时区)",动态显示具体 TZ 名
- 改原灰色提示为黄色"v3 时区语义变更"提示,明确升级行为
- 新增实时预览 div:显示当前用户 TZ 的小时/分钟、是否在通知时段
- TZ select / hours input 的 change/input 事件即时刷新,30s 兜底重算
src/views/{adminPage,dashboardPage,configPage}.html:
顶部导航与移动菜单加 "通知历史" 链接(fa-history 图标)
src/views/pages.js + src/api/admin.js:
注册 notifyLogsPage 模板 + 路由 /admin/notify-logs
170 测试全绿;wrangler dry-run 559 KiB / gzip 117 KiB。
Refs Task 11 of refactor/v3-product-grade plan.
|
2026-05-24 18:28:48 +08:00 |
|
wangwangit
|
3397d34c15
|
feat(ui): 订阅表单加入多提醒规则编辑器(Task 10)
adminPage.html:
- 替换原"提醒提前量"单行输入为"提醒规则"区块
- 顶部按钮:[应用预设(7/3/1/0)] [添加规则]
- 每行:启用复选框、类型(到期前/到期当天/到期后)、数值、单位(天/小时)
- after_expiry 类型展开:每 N 小时重复,直到 [续费/手动确认/不停止]
- 隐藏原 reminderUnit/reminderValue 作为 v2 兜底字段保留
- validateForm 不再强制 reminderValue(已隐藏)
JS 模块(位于 </script> 之前):
- ReminderRulesEditor (setRules / setPresets / getRules / clear)
- 新增订阅 → 自动渲染 4 条预设
- 编辑订阅 → 轮询监听 subscriptionId 字段变化,拉取 /api/.../reminders 渲染
- 全局 fetch 劫持:POST/PUT 订阅时自动附加 reminderRules 到 body
- 编辑模式 (PUT) 完成后调用 PUT /api/subscriptions/:id/reminders 同步替换规则
后端:
- v3-routes.js 新增 PUT /api/subscriptions/:id/reminders 整体替换接口
170 条测试全绿;wrangler dry-run 540 KiB / gzip 113 KiB。
Refs Task 10 of refactor/v3-product-grade plan.
|
2026-05-24 18:24:17 +08:00 |
|
wangwangit
|
b6ab5ed944
|
feat(api): 提醒规则 / 通知日志 / 调度日志新 API + 创建订阅联动
src/api/handlers/v3-routes.js(新):
GET /api/subscriptions/:id/reminders 列表
POST /api/subscriptions/:id/reminders 新增(body 传 preset:true 一键应用预设)
PUT /api/subscriptions/:id/reminders/:ruleId 更新
DELETE /api/subscriptions/:id/reminders/:ruleId 删除
GET /api/notification-logs?subId=&channel=&status=&since=&until=&limit=
GET /api/scheduler-logs?limit=N
挂载点:在 router.js 鉴权之后、subscriptions handler 之前匹配。
按 v2 错误结构返回 { success, message };405/404/400 状态码与 v2 一致。
POST /api/subscriptions 扩展:
- 不传 reminderRules → 自动应用 4 条智能预设(7/3/1/0 天)
- 传入数组 → 按数组替换(每条经 normalizeRule 校验)
- 写入失败不影响订阅本体创建,错误打 console.error
测试 tests/api/v3-routes.test.js 12 条覆盖:
- 4 类 reminder CRUD(含 preset=true / 不存在 → 404)
- notification-logs 过滤 subId / status
- scheduler-logs 列表
- 创建订阅自动写预设 vs 自定义规则
- 鉴权失败路径
总计 170 条测试全绿;lint 干净;wrangler dry-run 484 KiB。
Refs Task 8 of refactor/v3-product-grade plan.
|
2026-05-24 18:16:22 +08:00 |
|
wangwangit
|
a10c212989
|
refactor(api): 引入 Hono 应用作为路由外壳
src/app.js 新建 Hono 应用:
- 全局中间件:ensureMigrations(首次访问透明迁移)、onError 兜底
- 路由:GET /、GET /admin、ALL /admin/*、ALL /api/*、/debug、兜底
- path/method/response shape 与 v2 严格 1:1 兼容(前端零修改)
src/index.js 简化为 { fetch: app.fetch, scheduled }
策略说明:
- Hono 现阶段当"路由外壳"用,请求转发给现有 handler
- 后续 Task 可逐 handler 改成 Hono 原生写法(c.json/c.req.json 等)
- 这样既拿到中间件 / 错误兜底好处,又不破坏既有行为
vitest.config.js 增加 assetsInclude: ['**/*.html']
让 vite 在测试中能解析 src/views/*.html 文本 import(与生产 wrangler text loader 行为一致)
测试 tests/api/routes-compat.test.js 8 条覆盖:
- GET / 未登录 → 登录页 HTML
- GET /admin 未登录 → 重定向
- GET /api/subscriptions 未登录 → 401 标准错误体
- POST /api/login 错误 body / 正确凭据
- GET /debug 未登录 → 401
- GET /api/未知 → 404 标准错误体
- 兜底路径 → 登录页
总计 158 条测试全绿;wrangler dry-run 476 KiB / gzip 101 KiB。
Refs Task 7 of refactor/v3-product-grade plan.
|
2026-05-24 18:14:07 +08:00 |
|
wangwangit
|
0bb7e7670d
|
refactor(scheduler): v3 重写 - TZ 感知 + 多规则 + 结构化日志(修复 #91/#52/#166)
src/services/notify/reminder-engine.js(新):
- 纯函数 shouldFire(rule, ctx)
- 三种 rule type 显式分支(before_expiry / on_expiry / after_expiry)
- 24 条表驱动单测覆盖各种边界
src/services/scheduler.js(重写):
1. 时区基准统一:通过 getNowInTimezone(config.TIMEZONE) 取用户 TZ 下
hourString,与 NOTIFICATION_HOURS 比对(修复 #91 / #52 根因——
v2 把 UTC 小时当作"用户本地小时")
2. 多提醒规则:从 reminders.repo 加载每订阅的规则数组,逐条调
reminder-engine.shouldFire;老订阅没有规则时现场用
legacyFieldToRule 转一条
3. 去重粒度:dedup key = notify_dedupe:{subId}:{ruleId}:{ymdh-local}
不再让一条订阅的多规则相互打架
4. 结构化日志:
- 每次执行写 sched_log:{iso}(含命中/去重/发送/续订统计 + 候选明细)
- 每条通知发送(成功/失败)写 notify_log(dispatch.js 自动落库)
5. 用户日历"剩余天数"基于 getDaysBetween(now, expiry, tz),
修复 #166 跨日界场景
测试 tests/services/scheduler.test.js 7 条覆盖:
- 场景 1:UTC 0点 + 北京 8 点 + 配置 [08] → 发送
- 场景 2:同上配 [00] → 跳过 inWindow=false
- 场景 3:4 条规则订阅(7/3/1/0),距 3 天 → 仅命中 value=3
- 场景 4:同 sub+rule+ymdh 重复调用 → 去重 dedupedCount=1
- 自动续订:cycle 模式补齐 + auto 支付记录
- 写 sched_log
- 成功发送时写 notify_log
总计 150 条测试全绿;wrangler dry-run 415 KiB / gzip 86 KiB。
Refs Task 6 of refactor/v3-product-grade plan.
|
2026-05-24 18:11:47 +08:00 |
|
wangwangit
|
8ca9b07ae1
|
refactor(notify): 9 渠道统一适配器接口 + 修复 #81
新增 src/services/notify/channel.js:定义 Channel 接口
{ name, validateConfig, send, test }
+ ok/fail/escapeMarkdownV2/stripMarkdown/errorMessage 工具函数
每个渠道(telegram/notifyx/webhook/wechat/email/bark/gotify/serverchan/pushplus)
重写为:
- 暴露统一的 xxxChannel 对象(4 个方法)
- 保留 sendXxxNotification(...) 函数作为 v2 兼容 wrapper
修复 #81:Telegram MarkdownV2 转义现在覆盖 \(\)~`\>#+-=|{}.! 等 13 个字符;
失败时仍然降级纯文本兜底。
新增 src/services/notify/dispatch.js:
- dispatch(payload, config, options) Promise.allSettled 并发分发
- 部分渠道失败不影响整体,每条渠道结果独立返回
- 带 env+subId 时同步把成功/失败结果写 notify_log
- testChannel(name, config) 给配置页"测试发送"按钮用
services/notify/index.js 改为 dispatch 的薄壳,保留旧签名。
测试 tests/services/notify/channels.test.js 共 34 条:
- escapeMarkdownV2 14 字符表驱动
- Telegram 含下划线名 / 降级兜底 / API 拒绝 / 网络异常
- 8 个其它渠道各 happy + 配置缺失
- Bark 自定义 URL 与标准 URL 分支
- Webhook 模板替换 + 模板格式错误退回默认
- dispatch 部分失败 + 写日志
- testChannel 未知/已知渠道
- 9 渠道注册表完整性
总计 119 条测试全绿;lint 干净;wrangler dry-run 413 KiB。
Refs Task 5 of refactor/v3-product-grade plan.
|
2026-05-24 18:08:14 +08:00 |
|
wangwangit
|
b9de410f6f
|
feat(observability): 三类可观测性仓库 + 迁移扩展
新增三个 KV 仓库(v3 通知/调度可观测性数据底座):
1. src/data/reminders.repo.js
- reminder_rules:{subId} 数组,支持 CRUD + 智能预设(4 条:到期前 7/3/1/当天)
- legacyFieldToRule 把 v2 的 reminderUnit/reminderValue 单点提醒
转成 1 条等价 before_expiry 规则
- normalizeRule 修复非法字段,repeatInterval 仅 after_expiry 类型保留
2. src/data/notification-logs.repo.js
- notify_log:{ymdh}:{subId}:{ruleId}:{channel}:{rand}, TTL 30 天
- writeLog / query(subId/channel/status/since/until/limit 过滤)
- 时间倒序,KV.list 拉全后排序
3. src/data/scheduler-logs.repo.js
- sched_log:{isoUtc}, TTL 30 天
- writeLog / getRecent(按时间倒序)
迁移扩展:MIGRATION_STEPS 追加两个 step
- reminder_rules_v3:为现有订阅生成默认提醒规则
- scheduler_logs_v3:v2 的 scheduler_status_history 转换到新表
调试页新增链接:/debug?export=sched_logs&limit=50 直接下载 JSON
测试:
- tests/data/reminders.test.js (13)
- tests/data/notification-logs.test.js (8)
- tests/data/scheduler-logs.test.js (4)
- 共 85 条测试全绿;lint 干净
Refs Task 4 of refactor/v3-product-grade plan.
|
2026-05-24 18:03:01 +08:00 |
|
wangwangit
|
dac8e7dc1d
|
refactor(data): 订阅仓库改为 KV 多 Key + 自动迁移
把 v2 的单 Key subscriptions JSON 数组改造为:
sub_index = JSON 数组 [id1, id2, ...]
sub:{id} = 单订阅完整数据
schema_version = 'v3'
migrate:{step} = 'done' 标记
migration_lock = 60s TTL 锁
subscriptions_v2_backup = 旧数据 7 天 TTL 备份
新增:
- src/data/subscriptions.repo.js:低层 KV 仓库(listIds/listAll/getById/save/saveMany/deleteById/replaceAll)
- src/data/migrate.js:迁移编排器,可累加 step;带内存缓存避免重复检查;
幂等 + 锁保护
- 在 src/index.js 入口(fetch + scheduled)开头调用 ensureMigrations
- src/data/subscriptions.js 改造为调用新 repo,单条 CRUD 不再触碰整数组
- src/services/scheduler.js 自动续订写入改用 subRepo.saveMany
测试:
- tests/data/migrate.test.js 16 条用例覆盖 repo CRUD、迁移幂等、锁、损坏 JSON 兜底
- 共 58 条测试全绿;wrangler dry-run 401 KiB
老用户升级:第一次 fetch / scheduled 触发后透明完成迁移;旧数据 7 天可回滚。
Refs Task 3 of refactor/v3-product-grade plan.
|
2026-05-24 17:59:06 +08:00 |
|
wangwangit
|
f6bce4b7b3
|
refactor(time): 重写时区核心模块为单一真相源
修复 #91 / #52 / #166 类时区相关问题的根因:旧 getCurrentTimeInTimezone
只返回 new Date(),被调用方误以为是"用户本地时间对象"。
变化点:
- 新增 getNowInTimezone(tz, now?) 返回 {utc, parts, hourString, isoLocal}
强制业务代码显式选择需要 UTC 时刻还是用户 TZ 字段
- 新增 getTimezoneHourString(date, tz) 调度器通知时段判断专用
- 新增 getDaysBetween(from, to, tz) 基于用户 TZ 各自零点的整天数差,
修复"凌晨 0–8 点创建订阅默认日期变前一天"的 #166
- formatLocalDate 替代 formatTimeInTimezone(保留旧名作 alias)
- 旧 API(getCurrentTimeInTimezone / convertUTCToTimezone)保留为兼容
wrapper,加显眼注释说明其语义陷阱
- 全文 JSDoc 标注 + 中文用途说明,启用 // @ts-check
- 40 条单测覆盖:UTC/北京/纽约 DST、跨日界、#166 边界、非法时区兜底
附带:/debug 页新增"时区诊断"区块,直观展示 UTC vs 用户 TZ 当前小时、
通知时段是否命中——这是用户自助排查"为什么没收到通知"的入口
Refs Task 2 of refactor/v3-product-grade plan.
|
2026-05-24 17:53:29 +08:00 |
|
wangwangit
|
e2fc130f99
|
fix: XSS 风险修复
- showToast 改用 textContent 设置消息内容,防止 HTML 注入
- createHoverText 对所有用户输入进行 escapeHtml 转义
- 续订/支付历史/编辑支付模态框中的 subscription.name 和
payment.note 使用 escapeHtml 转义
- debug 页面 adminUsername 转义
- 添加全局 escapeHtml 工具函数
|
2026-05-19 12:06:21 +08:00 |
|
wangwangit
|
b76e047050
|
feat: 搜索筛选体验优化
- 搜索框添加一键清空按钮(X 图标,有内容时显示)
- 筛选结果为空时显示'清除筛选条件'重置链接
- 重置链接一键清空搜索关键词和所有筛选器
|
2026-05-19 12:03:49 +08:00 |
|
wangwangit
|
4f91427881
|
feat: Dashboard 刷新优化
- 添加手动刷新按钮(带 loading 状态)
- visibilitychange 暂停/恢复自动轮询,节省后台资源
- 页面重新可见时立即刷新数据
- 加载失败时显示重试按钮
|
2026-05-19 12:02:56 +08:00 |
|
wangwangit
|
7454d78be0
|
feat: 模态框交互优化 - ESC关闭、背景锁定滚动、动画
- ESC 键关闭所有模态框(主模态框 + 动态模态框)
- 所有动态模态框(续订、支付历史、编辑支付)打开时锁定背景滚动
- 关闭时恢复背景滚动
- 主模态框添加淡入/缩放动画
|
2026-05-19 12:01:48 +08:00 |
|
wangwangit
|
edc7be9e90
|
feat: 操作反馈优化 - 按钮 loading 状态、停用确认
- 编辑按钮点击后显示 spinner,加载完成/失败后恢复
- 停用订阅前添加确认提示,避免误操作
|
2026-05-19 11:59:08 +08:00 |
|
wangwangit
|
d36f8b94fe
|
feat: 登录暴力破解防护 + Cookie Secure 标志
- 基于 IP 的登录失败计数(KV TTL 自动过期)
- 连续 5 次失败后锁定 5 分钟
- 失败时提示剩余尝试次数
- 登录成功后清除失败计数
- 添加 request.json() 的 try-catch 防止解析错误
- Cookie 添加 Secure 标志(login + logout)
|
2026-05-19 11:57:53 +08:00 |
|
wangwangit
|
bfa4d52772
|
feat: 配置页保存体验优化
- 添加悬浮保存栏:表单有变更时底部显示保存按钮
- 添加 beforeunload 提示:有未保存更改时离开页面会提示
- 加载失败时禁用整个表单,防止误提交覆盖已有配置
- 保存成功后自动隐藏悬浮栏
- 支持 dark mode
|
2026-05-19 11:57:13 +08:00 |
|
wangwangit
|
384f3aaab2
|
feat: Toast 优化 - 错误延长显示、可关闭、堆叠限制
- 错误类 toast 延长到 6 秒,警告 4.5 秒,成功 3 秒
- 添加关闭按钮,用户可手动 dismiss
- 最多同时显示 5 个 toast,超出自动移除最早的
- toast-container 改为 flex 布局支持正确堆叠
- 同步更新 adminPage 和 configPage
|
2026-05-19 11:55:43 +08:00 |
|
wangwangit
|
008df6e5c5
|
feat: 统一 apiFetch wrapper,401 自动跳转登录页
- adminPage/configPage/dashboardPage 添加 apiFetch 封装
- 所有 API 调用替换为 apiFetch,401 时提示并跳转登录页
- theme-resources.js 中兼容性检测 apiFetch 可用性
解决认证过期后用户看到'未知错误'而非跳转登录的问题
|
2026-05-19 11:54:08 +08:00 |
|
wangwangit
|
61af3b332f
|
fix(#169): 兼容 Bark 自定义服务器 URL 格式
支持 bark-worker 等自定义服务器的完整 URL 格式
(如 https://user:pass@server/deviceKey/)。
当 BARK_SERVER 路径不为空时,直接 POST 到该 URL;
否则走标准 Bark API (serverUrl + /push + device_key)。
|
2026-05-19 11:19:34 +08:00 |
|
wangwangit
|
e1112bb114
|
fix(#166): 修复订阅列表到期时间显示的时区一致性
- diffMs/diffHours 改为基于用户时区计算,而非直接用 UTC 时间戳差值
- 状态判断增加 diffMs < 0 条件,到期日当天过午夜也显示'已过期'
原因:expiryDate 存储为 UTC 午夜,直接用 getTime() 差值会导致
UTC+8 用户在到期日当天凌晨看到'约7小时后到期'而非'已过期'
|
2026-05-19 11:18:40 +08:00 |
|
wangwangit
|
55ff9cd067
|
fix: 修复 deletePaymentRecord 中排序比较变量引用错误
sortedByPeriodEnd 排序中 dateB 错误引用了 a.periodEnd,
应为 b.periodEnd。此 bug 导致删除支付记录后到期日期回退不正确。
|
2026-05-19 11:16:25 +08:00 |
|
wangwangit
|
d5452336b6
|
fix(#166): 调度器使用用户配置时区计算到期天数和通知时段
- todayMidnight 改为基于 config.TIMEZONE 计算
- currentHour 改为使用 getTimezoneDateParts 获取时区对应小时
- NOTIFICATION_HOURS 现在按用户配置时区解释
原因:之前硬编码 UTC,导致 UTC+8 用户设置'到期当天提醒'时,
在北京时间 0:00(UTC 16:00)触发时 daysDiff 仍为 1 而非 0
|
2026-05-19 11:15:42 +08:00 |
|
wangwangit
|
06d952b492
|
fix(#166): 修复前端默认日期使用UTC而非本地时间的问题
- 添加订阅时默认开始日期改用本地日期
- 续订表单默认付款日期改用本地日期
- 编辑支付记录时日期显示改用本地日期
- 自动计算到期日期改用本地日期格式化
原因:toISOString() 返回 UTC 时间,UTC+8 用户在 0:00-8:00
之间会得到前一天的日期
|
2026-05-19 11:14:03 +08:00 |
|
wangwangit001
|
a2e0d1c28d
|
fix: redirect authenticated users from home
|
2026-04-24 11:31:05 +08:00 |
|
wangwangit001
|
5214f76c55
|
fix: preserve zero amount and payment currency
|
2026-04-24 11:14:32 +08:00 |
|
wangwangit001
|
cc97cc97c9
|
feat: add serverchan and pushplus notifiers
|
2026-04-23 12:04:44 +08:00 |
|
wangwangit
|
805a47e417
|
fix(security/ui): do not expose secrets; show configured flags + explicit clear
|
2026-03-05 19:40:47 +08:00 |
|
wangwangit
|
4f4fc5af1f
|
feat(notify): add gotify notifier + config UI
|
2026-03-05 15:29:53 +08:00 |
|
wangwangit
|
a095213162
|
fix(security): mask config secrets, protect /debug, use crypto RNG
|
2026-03-05 15:05:34 +08:00 |
|
Squarelan
|
0c92c1d99a
|
修复adminPage.html时区文案生成逻辑
|
2026-03-02 21:01:59 +08:00 |
|
wangwangit
|
a1638dedc0
|
fix: harden telegram notifications with markdown escaping and plaintext fallback
|
2026-02-27 18:59:46 +08:00 |
|
wangwangit
|
bd5b5227c4
|
release: v2 modular refactor and docs cleanup
|
2026-02-27 15:29:43 +08:00 |
|