Repository navigation
Releases: crazying-dev/forum
Releases · crazying-dev/forum
Release list
Windows V1.3.19:年制换算的公元年输入框支持公元前
Windows 客户端 V1.3.19
本次更新:年制换算的公元年输入框支持公元前
与网页端 ceNum < 0 ? ceNum + 1 : ceNum、Android ceInputToAstronomical 统一口径:公元前 M 年 = 天文纪年 1 − M,任何地方都不存在「0 年」。
- 此前在「公元年 → 无限年」输入负数(如
-100)会被直接丢进换算,得到「无限前 1704 年」并显示「公元 -100 年」,既差了一年,也没有换成公元前文案; - 现在输入
-1(公元前 1 年)→「无限前 1604 年」;输入-100→「公元前 100 年 = 无限前 1703 年」; - 输入框占位提示同步为「公元年,如 2010;公元前请填负数,如 -1」,输入 0 会提示「公元纪年没有 0 年」;
- 反方向(无限年 → 公元年)也改走同一套文案,不再出现「公元 -N 年」;
- 其余功能无变化。
校验
- 单元测试:302 passed / 0 failed
- 安装包:
forum_setup.exe(141,320,337 字节) - SHA-256:
941176604ef0ac0bb49105242500deb01221a2c2b645d4ef57aa00a9888f70e4
安装
直接运行 forum_setup.exe(仅写入 %LOCALAPPDATA%\CrForum,不需要管理员权限),已安装的旧版本会就地升级并保留本地数据。
Android V1.0.18
Android V1.0.18
修复:年制换算的公元年输入框不支持公元前
- 公元年输入框从「禁止负数」改为接受负数表示公元前:输入
-1即「公元前 1 年」,输出「公元前 1 年 = 无限前 1604 年」。 - 与网页端口径完全一致(
ceNum < 0 ? ceNum + 1 : ceNum):公元前 M 年 = 天文纪年1 − M,先归一再加换算,避免差一年。 - 输入
0仍按「公元纪年没有 0 年(公元前 1 年之后即公元 1 年)」拒绝。
重构
core/TimeFmt.kt新增ceInputToAstronomical()/ceInputToNewEra(),把「输入框年份 → 天文纪年 → 无限年」的归一收敛到核心,界面层不再自己判正负。TimeFmtTest新增 3 例(公元前换算 / 0 年拒绝 / 正数不变),单元测试共 91 例全绿。
换算示例
| 输入(公元年) | 输出 |
|---|---|
-1 |
公元前 1 年 = 无限前 1604 年 |
-100 |
公元前 100 年 = 无限前 1703 年 |
1603 |
公元前 1 年 = 无限前 1604 年 |
1604 |
公元 1604 年 = 无限元年 |
2026 |
公元 2026 年 = 无限 423 年 |
安装包
| 项 | 值 |
|---|---|
| 文件名 | forum-android-1.0.18.apk |
| 大小 | 8 168 888 字节 |
| SHA-256 | f410be372e0b5c0327d6d64a6ca8e8fc4efc5f2ee56fd56645f877616875f276 |
| 签名证书 SHA-256 | bab9ac497b3b5b4f8fe3e36fbb9fec111c08831dc6e9100889a439f019aa4668(与前版一致,可直接覆盖安装升级) |
Android V1.0.17
Android V1.0.17
修复:无限历「0 年」错显
- 无限历改为 1 起算 —— 无限元年 = 公元 1604 年(无限 N 年 = 公元 1603 + N 年)。此前公元 1603 年会错显为「无限 0 年」。
- 公元 1604 年以前显示「无限前 N 年」(无限前 1 年 = 公元 1603 年),不存在无限 0 年。
- 与网页端、Windows 端三端纪年口径完全统一。
重构:结构化换算核心
core/TimeFmt.kt新增data class NewEraDate(yearNum, isBefore)与gregorianToNewEra()/newEraToGregorian()/ceText(),把「公元年 ⇄ 无限年」双向换算收敛到单一核心(对 0 与负数直接拒绝)。wuxianYear/wuxianToCe/yearText改为委托核心,对外文案仍为「无限 N 年 / 无限前 N 年」。
新增
- 「我的 › 年制换算」页:无限年 ⇄ 公元年实时双向换算,输入 0 或负数给出明确提示。
安装包
| 项 | 值 |
|---|---|
| 文件名 | forum-android-1.0.17.apk |
| 大小 | 8 168 888 字节 |
| SHA-256 | 0d36a0626ed8e870eed4a1497c7178ae8e76fea9178cdcf5288b68b4ad399287 |
| 签名证书 SHA-256 | bab9ac497b3b5b4f8fe3e36fbb9fec111c08831dc6e9100889a439f019aa4668(与 1.0.16 相同,可直接覆盖安装升级) |
Windows V1.3.18:无限历纪年改为 1 起算(无限元年 = 公元 1604 年)
Windows 客户端 V1.3.18
本次更新:无限历纪年改为 1 起算
与网页端统一「无限元年 = 公元 1604 年」的口径。此前的换算为 公元年 − 1604,使得无限元年被显示成「无限 0 年」,与「元年」命名自相矛盾。本版改为 1 起算:
- 无限 N 年 = 公元 (1603 + N) 年 —— 公元 1604 年即「无限元年」,1605 年为「无限 2 年」;
- 公元 1604 年以前显示「无限前 N 年」= 公元 (1604 − N) 年 —— 公元 1603 年为「无限前 1 年」;
- 不存在无限 0 年:换算框输入 0 会提示,
wuxian_to_ce对 0 返回空; - 全站时间(帖子、评论、生日等)随年制显示同步更新;
- 设置页「年制换算」输入 1 直接显示为「无限元年」。
校验
- 单元测试:297 passed / 0 failed
- 安装包:
forum_setup.exe(158,186,366 字节) - SHA-256:
1a78cd3930a7ebe7f3f28bb48689131a33e4762a7a304a159b67af2710e6e672
妖精论坛 · Android 客户端 V1.0.16
妖精论坛 · Android 客户端 V1.0.16
本次更新:列表页返回后保留浏览位置
- 修复:从帖子详情退出后,列表跳回最顶端。 本工程有意不使用
navigation-compose,根节点用when (nav.current)只渲染当前页——页面一旦被压栈(进入帖子详情)就离开组合,页内remember的列表数据与LazyListState一并被丢弃,返回时列表被清空重载、滚动位置归零; - 现新增
ui/screens/FeedState.kt:FeedState/UserFeedState/SearchState分别承载首页 / 论坛 / 搜索 / 用户主页的已加载内容、分页游标与滚动状态,由根节点用remember { FeedStateStore() }持有(位于when之外,随根节点存活);返回列表页时仍取到同一实例,列表内容与滚动位置都不丢; - 配合纯函数
needReload(loadedKey, currentKey):只在内容标识(信息流 / 分类 / 搜索词 / 用户 tab)变化时才重新加载,从帖子详情返回不再触发重载; FeedParts.PostFeedList新增state: LazyListState参数;首页 / 论坛 / 搜索 / 用户主页的列表均接入保留的滚动状态;- 版本号升至
versionCode = 17/versionName = 1.0.16。
说明
- 顶部「登录 / 退出登录」切换、切换信息流或分类、切换用户主页 tab 等情形仍会正常重新加载,仅在「进入详情再返回」时保留现场;
- 新增
FeedStateTest(10 例)覆盖needReload判定与FeedStateStore的「同 key 同实例」语义,单测总数 63 → 73; - 同类目网页端的「无限年 ↔ 公元年」换算弹窗显示问题已在 Web 端单独修复(不随本安装包发布)。
| 项 | 值 |
|---|---|
| 安装包 | forum-android-1.0.16.apk(约 7.8 MB) |
| versionName | 1.0.16 |
| versionCode | 17 |
| 最低 / 目标 SDK | 24 / 36 |
| SHA-256 | 1bedfc7f3e29a616d217762a9907f846f2d17cf1eb843cf90fd041010b2cdd61 |
| 签名证书 SHA-256 | bab9ac497b3b5b4f8fe3e36fbb9fec111c08831dc6e9100889a439f019aa4668 |
妖精论坛 · Android 客户端 V1.0.15
妖精论坛 · Android 客户端 V1.0.15
本次更新:验证弹窗可见性修复 + 网页端登录 + 世界频道顺序
- 修复:人机验证组件「靠上、被遮挡、点不到」。 此前承载页 WebView 挂在
AlertDialog的槽位里,WebView 处于独立 Dialog 窗口时窗口层级与触摸命中区会错位——官方组件看着渲染出来了却点不动。现改为当前界面内的全屏遮罩层(Box+ 居中卡片 +BackHandler),与 App 内已验证可用的 Live2D WebView 走同一条渲染路径;WebView 高度由 170dp 放宽至 260dp,并在setOnTouchListener里requestDisallowInterceptTouchEvent(true)让 WebView 独占手势; - 新增手动退路「改用滑块」。 Turnstile 分支多一个按钮,点一下立刻改用服务端自研滑块重新验证,不必再等 12 秒超时;
- 新增网页端登录。 登录页新增「使用网页端登录」入口:在内置 WebView 里打开站点真实登录页
/auth?mode=login,官方 Turnstile 在真实网页里渲染,绕开内嵌承载页的一切兼容问题。登录成功后自动取出token/ID两个 HttpOnly Cookie 搬进 App 会话,随即返回;因为站点登录是fetch()提交不会跳转页面,成功判定采用定时读 Cookie(1.2 秒一次)+ 顶部「我已完成」手动重试双保险; - 修复:世界频道最新消息跑到最上面。 服务端返回的是按时间倒序的列表(最新在前),客户端此前原样渲染。现改为「早的在上、最新在下」,与聊天窗口一致,并在首次加载与发送成功后自动滚到底部。顺带修正截断口径:原来用
takeLast(100),在倒序列表上取到的是最旧的 100 条,现改为take(100); - 版本号升至
versionCode = 16/versionName = 1.0.15。
说明
- 网页端登录后的会话与网页同源(
token/ID,有效期 7 天);若在网页侧退出登录,App 会因 Cookie 失效被服务端 401 → 自动清理本地会话; - 人机验证与网页登录的 WebView 一律页面内组合渲染,不再放进 Dialog(层级 / 命中区会错位);
- 服务端如需完全关闭人机验证,可设
CAPTCHA_ENABLED=0并重启后端。
| 项 | 值 |
|---|---|
| 安装包 | forum-android-1.0.15.apk(约 7.8 MB) |
| versionName | 1.0.15 |
| versionCode | 16 |
| 最低 / 目标 SDK | 24 / 36 |
| SHA-256 | 1ca33a725c381683843956797caa206a5d7ff0d20efc7900cb110e9b78d36960 |
| 签名证书 SHA-256 | bab9ac497b3b5b4f8fe3e36fbb9fec111c08831dc6e9100889a439f019aa4668 |
妖精论坛 · Windows 客户端 V1.3.17
Windows 客户端 V1.3.17
本次更新:Turnstile 失败自动回退自研滑块
上一版将人机验证改为 Cloudflare Turnstile(内嵌 WebEngine)。实测发现部分环境(缺少 WebEngine 组件、嵌入页加载失败或超时、sitekey 未配置)下 Turnstile 无法完成验证,弹窗卡住、用户无法通过。本版加入自动回退:Turnstile 侧一旦失败,立即改用服务端下发的自研滑块挑战,人机验证不再失效。
- 嵌入页
loadFinished(ok=false)、加载异常、超时或缺少 sitekey 时,自动切换到自研滑块; - 回退请求带
?provider=slider,服务端据此直接下发滑块图片挑战(不再走 Turnstile 校验通道); - 回退只在首次触发,避免来回抖动;
- 服务端 provider 开关(
slider/turnstile/off)逻辑保持不变,未配置 Turnstile 密钥时依旧自动走滑块。
校验
- 单元测试:297 passed / 0 failed
- 安装包:
forum_setup.exe(158,128,404 字节) - SHA-256:
3cf18632e5af14af7b8012d43954de298b073ee43a7f7e44117d23026a1d7d28
Forum Windows V1.3.16
Windows 客户端 V1.3.16
本次更新:人机验证接入 Cloudflare Turnstile(内嵌 WebEngine)
此前自研的滑块拼图人机验证经实测可被低成本攻破,本版本三端统一改用 Cloudflare Turnstile,Windows 端以内嵌浏览器组件承载官方验证控件。
- 新增依赖
PyQt6-WebEngine==6.11.0,弹窗内嵌QWebEngineView加载服务端独立验证页/captcha-embed,Cloudflare 官方控件在窗口内直接渲染; - 验证结果经页面
document.title(captcha:<kind>:<payload>)回传,无需 QWebChannel(实测 3000 字符标题不截断); - 服务端 provider 开关(
slider/turnstile/off)自动适配:未配置 Turnstile 密钥、或本机缺少 WebEngine 组件时,自动回退到原自研滑块,功能不会失效; - Turnstile token 一次性有效(300 秒),拿到即提交,不再走两步式
/verify; - 隐私政策同步升级 v2.1:新增 Cloudflare(
challenges.cloudflare.com)第三方披露与「境外传输提示」; - 安装包体积因内嵌浏览器而增大(约 151 MB)。
校验
- 单元测试:296 passed / 0 failed
- 安装包:
forum_setup.exe(158,184,750 字节) - SHA-256:
7ca8c0d2e2c6762f4d565cdca4fe8450f3645992fb7edfd4199bcd0fd7c63984
Windows 客户端 V1.3.15
Windows 客户端 V1.3.15
本次更新:三端人机验证(滑块拼图)
服务端为 11 个敏感接口加上了 @captcha_required,客户端需先完成滑块拼图验证再提交业务请求。本版本完成 Windows 客户端接入。
- 新增滑块拼图验证弹窗:纯
QPainter绘制背景 + 可拖动拼图块 + 滑块轨道,零第三方 SDK,不引入任何外部域名; - 接入 10 处敏感流程:
- 登录、注册
- 发送注册验证码、找回密码发码 / 重置密码
- 修改密码(发码)
- 更换绑定邮箱(当前邮箱 / 新邮箱发码)
- 注销账号(发码 / 提交注销)
- 两步式校验:
/api/captcha/challenge→ 拖动 →/api/captcha/verify→ 把同一个一次性 token 随业务请求提交;token 用后即焚、绑定 IP、5 分钟过期、容差 ±6px; - 服务端以
CAPTCHA_ENABLED=0关闭人机验证时,客户端自动跳过弹窗; - 说明:
POST /api/user/password、POST /api/user/email(终止步骤)不加弹窗,只对它们的「发送验证码」步骤加。
校验
- 单元测试:281 passed / 0 failed(新增
tests/test_captcha.py10 例) - 安装包:
forum_setup.exe(48,592,036 字节) - SHA-256:
23d0a2fcd96662bbc9a0b3febef7ec23affe8cc2c031337f1e54011678acb9ee
妖精论坛 · Android 客户端 V1.0.14
妖精论坛 · Android 客户端 V1.0.14
本次更新:验证失败自动回退 + 滑块窄屏修复
- 新增兜底:Turnstile 失败自动回退自研滑块。 当 Cloudflare 组件加载不出来时(网络不可达 / 内嵌页报错 / 12 秒内没有渲染完成),弹窗会自动改用服务端自研滑块重试一次(
/api/captcha/challenge?provider=slider),不再让用户卡在「正在加载验证」; - 修复:自研滑块拼图块图片挤压变形。 此前拼图块按固定尺寸绘制,当舞台实际可用宽度小于图片原始宽度时会被横向压扁,缺口永远对不齐、验证无法通过。现改为按实际可用宽度等比缩放(
BoxWithConstraints+scale = renderW / stageW),背景、拼图块、滑道手柄三者同尺; - 版本号升至
versionCode = 15/versionName = 1.0.14。
说明
- 回退只发生一次,避免网络持续异常时无限重试;
?provider=slider是「本次请求显式要滑块」,与全局CAPTCHA_PROVIDER无关——即便服务端已启用 Turnstile,回退请求也能正常拿到滑块图;- 服务端如需完全关闭人机验证,可设
CAPTCHA_ENABLED=0并重启后端。
| 项 | 值 |
|---|---|
| 安装包 | forum-android-1.0.14.apk(约 7.8 MB) |
| versionName | 1.0.14 |
| versionCode | 15 |
| 最低 / 目标 SDK | 24 / 36 |
| SHA-256 | 0f525d22ea662261c367584f98679ff41654b3d8545a31fdd988cf367a029e05 |
| 签名证书 SHA-256 | bab9ac497b3b5b4f8fe3e36fbb9fec111c08831dc6e9100889a439f019aa4668 |