2.3.0:手表界面精简 + 播放器 + 鼠标重做

手表端
- 功能页从 10 个杂项精简到 7 个(屏幕/鼠标/媒体/文件/电脑/语音/电源)
- 删掉:游戏封锁、待办、掷骰子、抽奖、壁纸、显示器开关、定时关机、
  剪贴板历史、性能/磁盘/电量、文件夹浏览、教室限制等
- 改成显式列按钮,不再把电脑端所有功能组无脑铺到表盘
- 远程鼠标控制重做:滑动区 + 左键/滚轮/右键三按钮
  滚轮点按=中键、上下滑=滚动
- 新增视频/音乐播放器(手表本地播放):进度拖动、左右滑快进退10秒、
  点画面播放暂停、上一/下一、播完自动下一首

电脑端
- 新增 kill_all(结束所有进程),白名单保护系统关键进程和自身
- 新增 media_list / media_pull(播放器数据源)
  安全边界:只允许媒体目录,用 relative_to 判断,防同前缀兄弟目录绕过

中转站
- known_devices 从 ID 集合改成「设备ID -> 配对码」映射
- 修复:管理员改码后关机超过 6 小时,改码会被超时清理冲掉
- 老格式 state 文件平滑升级
This commit is contained in:
xmz7891
2026-10-18 11:39:14 +08:00
parent 1d368979aa
commit 2061f9525f
50 changed files with 13812 additions and 584 deletions
+120
View File
@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
r'''配置 Halo:控制台路径改到 /houtai。
== 为什么环境变量没生效 ==
我第一版用了 `HALO_CONSOLE_PATH=/houtai`(按 Spring Boot 的
relaxed binding 习惯猜的),但容器起来后 `/console` 还是 302,
`/houtai` 是 404 —— **说明这个变量名不对**。
从容器里看到真正的线索:
SPRING_CONFIG_LOCATION=optional:classpath:/;optional:file:/root/.halo2/
也就是说 Halo 会去读 **`/root/.halo2/application.yaml`**
(宿主机上就是 `/opt/halo/data/application.yaml`)。
**用配置文件比猜环境变量可靠得多** —— 而且配置项写错了
Halo 会在日志里报"不认识的属性",比静默忽略好。
== Halo 的配置长什么样 ==
Halo 2.x 用 Spring Boot 的 `@ConfigurationProperties`,
前缀是 `halo`,所以键是 `halo.console-path`。
== 要配的几项 ==
* `halo.console-path: /houtai` —— 用户要求
* `halo.external-url` —— 生成文章链接用,设成域名
* `halo.work-dir` —— 数据目录(容器里是 /root/.halo2)
**其余不写** —— 写了反而容易覆盖掉默认值,将来升级出问题。
'''
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "_build"))
from lssh import run, upload # noqa: E402
CONFIG = """# ======================================================================
# Halo 配置
# ======================================================================
#
# 这个文件放在宿主机的 /opt/halo/data/ ,容器里看到的是
# /root/.halo2/application.yaml(Halo 的 SPRING_CONFIG_LOCATION
# 就指着那儿)。
#
# ⚠ 为什么不靠环境变量:
# 我第一版用了 HALO_CONSOLE_PATH,结果没生效(/console 还是默认的)。
# Halo 的配置项是 Spring Boot 的 ConfigurationProperties,
# **写配置文件最可靠** —— 而且写错了它会在日志里报
# "unknown property",比静默忽略强。
halo:
# 数据目录(容器内路径)
work-dir: /root/.halo2
# 对外地址。Halo 用它生成文章永久链接、站点地图、RSS 里的链接。
# 设成域名之后,就算你从 IP:3001 进来,页面里的链接也是域名,一致。
external-url: https://xxmxxs.top
# ★ 控制台路径 —— 用户要求 "xxmxxs.top/houtai 是管理博客的后台"
#
# 默认是 /console。改掉之后:
# * 老路径 /console 不再响应(相当于顺手藏了一下后台入口)
# * 新入口是 https://xxmxxs.top/houtai
console-path: /houtai
"""
def main() -> int:
print("=" * 62)
print(" 配置 Halo:控制台路径 -> /houtai")
print("=" * 62)
print()
tmp = ROOT / "_build" / "_halo_application.yaml"
tmp.write_text(CONFIG, encoding="utf-8", newline="\n")
upload(str(tmp), "/tmp/halo-application.yaml")
tmp.unlink(missing_ok=True)
out = run(r'''
echo "==== 1. 放配置文件 ===="
sudo mv /tmp/halo-application.yaml /opt/halo/data/application.yaml
sudo chown 1000:1000 /opt/halo/data/application.yaml 2>/dev/null || true
sudo ls -la /opt/halo/data/ | sed 's/^/ /'
echo
echo "==== 2. 重启容器让它读到配置 ===="
sudo docker restart halo >/dev/null 2>&1
echo " 重启了,等它起来(最多 90 秒)…"
for i in $(seq 1 45); do
sleep 2
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://127.0.0.1:3001/actuator/health 2>/dev/null)
if [ "$code" = "200" ]; then echo " 第 $((i*2)) 秒:健康检查 200 ✓"; break; fi
done
echo
echo "==== 3. 复核控制台路径 ===="
printf " %-30s %s\n" "/houtai(新,应该 200/302)" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 8 http://127.0.0.1:3001/houtai)"
printf " %-30s %s\n" "/console(旧,应该 404)" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 8 http://127.0.0.1:3001/console)"
printf " %-30s %s\n" "/(首页)" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 8 http://127.0.0.1:3001/)"
echo
echo "==== 4. 配置有没有被拒绝(日志里找 unknown property)===="
sudo docker logs halo 2>&1 | grep -iE "unknown|not.*recogniz|invalid.*propert|console-path|configuration" | head -10 | sed 's/^/ /' || echo " (没有报错)"
echo
echo "==== 5. 内存现状 ===="
sudo docker stats --no-stream --format ' {{.Name}} 内存 {{.MemUsage}}' halo 2>/dev/null
free -m | sed 's/^/ /'
''', timeout=600, quiet=True)
print(out[1] if isinstance(out, tuple) else out)
return 0
if __name__ == "__main__":
sys.exit(main())