Skip to content

绵中融媒体智汇导播系统 v1.6.3

Latest

Choose a tag to compare

@github-actions github-actions released this 04 Oct 06:11
· 1 commit to main since this release

1.6.3

界面文案正式化,并删掉多余的解释

上一轮只做到「正式」,把大量解释性文字原样留在了页面上——它们在讲实现、讲理由、
讲安慰,而管理员只想知道「这个页面能干什么、我现在能不能操作」。

  • 角色权限页的两段「受保护规则为什么受保护」整段收进折叠区,理由原文一字不丢,
    但默认不占版面(页面上只留「N 条须知 点击展开」)。
  • 无权限提示原本在解释「侧边栏已按权限隐藏入口,此处再次校验用于阻止直接输入地址
    访问」——这是我们的实现细节,用户只需要知道自己被拦了。
  • 个人中心删掉「本平台不提供头像上传功能,也不托管头像文件」这类回答没人问的
    问题,以及「当前设备的登录状态会自动延续,不会被强制退出」这句安慰。
  • 系统监控删掉「每次刷新都会实际执行一次查询,而非仅检查进程是否存活」——纯实现
    说明;改成「每次刷新实际执行一次查询以确认连接可用」。

更新时能看到更新详情

「检查更新」原本只告诉你有新版本,点下去之前无从判断这次改了什么。现在展示该版本
的发布正文——也就是 CHANGELOG 里的那一节加上部署说明。

后端的更新检查早就把 Release 正文取回来了(fetchLatest 解的是同一个结构),
只是没有往外送,现在补上 release_notes 字段。发布流水线那边同样补了一步:从
CHANGELOG.md 抽出本次版本的那一节,拼到 Release 正文最前面——原来正文是写死的
部署说明,不含「这次改了什么」。

正文是 Markdown,且来自 UPDATE_API_BASE 指向的更新源(可以配成镜像),也就是
这段文本由镜像站运营者决定而不是由本项目决定。所以前端不用现成的 Markdown 库,
而是先把整段文本转义、再套一小撮白名单标记:转义发生在最前面,后续每一步只在自己的
产物里加标签,因此不存在「某条规则忘了转义」这种漏法。全仓库此前没有一处
{@html},这里不该是第一个。链接只放行 http/https/mailto,且协议比较会去掉内嵌
空白并忽略大小写(java\tscript: 与 JaVaScRiPt: 都挡得住)。

页面切换有过渡了

用 SvelteKit 的 onNavigate 接上 View Transitions API,140ms 交叉淡入。

形状选纯交叉淡入而不是带位移:侧边栏是 fixed、顶栏是 sticky 都铺满视口,而 root
快照与视口等大——任何位移都会在视口边缘露出一条已更新的真实 DOM,同时把侧边栏整条
拖走,读起来就是一次「整页滑动」。前后两张快照里侧边栏与顶栏几乎逐像素相同,交叉淡入
后看不出差别,等于免费得到「外壳不动、内容在换」。

顺带修掉一个不查就会踩的问题:::view-transition-group(root) 的 UA 默认时长是
250ms,而整棵伪元素树(含 startViewTransition().finished)的存活取最长动画。不改
的话淡入 140ms 结束、整屏快照还要在屏幕上多压 110ms,下面的入场动画全被推迟(实测
finished 从 334ms 降到 187.7ms)。这个 group 动画本来只是旧新几何对齐的 transform
插值,root 前后尺寸一致,是个空动作。

命中「减少动态效果」时连 startViewTransition 都不进——只把时长设成 0 并不等价:
一次同文档过渡要抓两遍整屏快照,跑一遍就是实打实的开销。

进系统监控页时压制该页自己的入场动画,否则整屏淡入落在一片 Spinner 上、卡片再叠一次
淡入,看起来是闪一下而不是淡两次。

刷新频率按代价拆分

全局状态(在线人数、断线)15 秒 → 1 秒:只读内存无 IO,常驻约 0.17% 单核。
运行指标 10 秒 → 3 秒:每次要递归遍历 3 个目录并真实执行一次 SELECT 1;1 秒一轮
就是常驻遍历文件系统,且随 storage/logs 增长而变贵。

运行时间改为本地每秒推进、零网络成本。锚点用客户端收到响应的那一刻而不是后端
返回的 collected_at——后者是服务器时刻,与客户端 Date.now() 相减会把两台机器的
时钟偏差算进去。每次轮询重新锚定,定时器降频与网络延迟都不会累积成漂移。

页头现在明确显示自动刷新的状态、倒计时、上次刷新多久前,并可暂停;数值只在真的变了
时提示(比较显示文本而非后端字段,41891088384 → 41891099136 不算变化)。


部署

下载 backend-linux-amd64.tar.gz:

tar -xzf backend-linux-amd64.tar.gz
cd backend-linux-amd64
cp .env.example .env      # 必填 JWT_SECRET 与 APP_KEY
vi .env
./smart-mzcmc migrate      # 建表,幂等
chmod +x start.sh && ./start.sh

完整步骤见包内 DEPLOY.md;反向代理配置见 docs/operation-manual.md。

初始化

从 1.4.0 起,全新部署走网页向导:打开
http://<服务器IP>:3000/admin/setup,填系统名称、监听地址与管理员
账号,点提交即可。向导会写好 .env、跑完迁移、建好管理员。

此前的方式是把 POST /api/auth/register 暴露在开放端口上、抢注一个
管理员。现在 SetupGate 中间件会在初始化完成前拦下除 /api/setup/*
与 /api/health 外的所有接口并返回 503,所以那条路已经堵上了。

已经初始化过的部署不受影响,向导会直接返回「已完成」。

首次初始化时请确认 .env 可写(向导需要写回配置),否则会返回
「当前进程无法写入 .env」。

本次构建的来源

组件 ref
后端 v1.6.3
admin main
docs main
director main
interviewer main

客户端仓库若有同名 tag 则按 tag 构建,否则回退 main(见上表)。

客户端地址配置

配好反向代理后,各端填同一个域名即可,无需带端口:

端 文件 是否需重新编译
管理后台 无需配置(默认同源) 否
解说端 / 包装端 exe 同目录 config.json 否
采访端 public/interviewer/config.json 否
导播端 lib/config.dart 是(但 APK 已内置本次配置)

启用 HTTPS 后,所有 ws:// 必须改成 wss://,
否则浏览器按混合内容拦截且不报错。

Full Changelog: v1.6.2...v1.6.3