- M3 认证/权限/审计/限流 + 全部 REST 接口 - M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制) - M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配) - M6 WebSocket 实时同步中心 - M7 xlsx 导出 + 赛事包 zip + 备份 - 规则包 YAML 导入导出(差异预览) - 字体 vendor 子集化(4 套 x2 字重) - 集成:realtime/export/rules 接入 main+httpapi;backup 子命令 - 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
4.2 KiB
vendor/fonts —— 本地字体(离线部署,禁止 CDN)
现场部署无外网,所有中文字体必须随仓库分发、从本目录本地加载。本目录只放子集化后的 woff2, 原始大字体(每套 8–12 MB)不入库。
字体清单
| id | 显示名 | font-family | 字重 | 单套合计 |
|---|---|---|---|---|
noto-sans |
Noto Sans SC | Noto Sans SC |
400 / 700 | 2.72 MB |
noto-serif |
Noto Serif SC | Noto Serif SC |
400 / 700 | 3.71 MB |
misans |
MiSans | MiSans |
400 / 700 | 1.76 MB |
source-han-sans |
思源黑体 Source Han Sans CN | Source Han Sans CN |
400 / 700 | 2.72 MB |
合计 8 个 woff2、10.91 MB。逐文件体积与 sha256 见 manifest.json,
每个文件均 ≤ 4 MB / 套的目标(最大为 Noto Serif SC 的 3.71 MB)。
来源与授权
| 字体 | 来源 | 授权 |
|---|---|---|
| Noto Sans SC | Google Noto(~/Fonts/noto-sans/sc) |
SIL Open Font License 1.1 |
| Noto Serif SC | Google Noto(~/Fonts/noto-serif/sc/SubsetOTF/SC) |
SIL Open Font License 1.1 |
| MiSans | 小米(~/Fonts/MiSans/ttf) |
MiSans 字体知识产权许可协议 |
| 思源黑体 Source Han Sans CN | Adobe(~/Fonts/思源黑体) |
SIL Open Font License 1.1 |
授权说明:本项目为内部赛事使用,不对外公开发布,字体授权不构成障碍 (见
devdocs/06-大屏端设计.md9.1、devdocs/07-管理面板设计.md9)。 若将来对外分发,需逐字体复核许可:Noto / 思源黑体为 OFL,可自由分发; MiSans 为厂商许可,公开分发前必须另行确认。OFL 字体保留其原始版权声明, 本目录未附 LICENSE 副本,需要时从~/Fonts/<字体目录>/LICENSE取回。
子集化命令
依赖 fonttools + brotli(生成 woff2 必需):
pip install fonttools brotli
# 系统 Python 受 PEP 668 保护时,用带系统包的虚拟环境:
python3 -m venv --system-site-packages ~/.tmp/fontenv
~/.tmp/fontenv/bin/pip install brotli
PYTHON=~/.tmp/fontenv/bin/python vendor/fonts/tools/subset-fonts.sh
脚本会:生成字符集 → 逐字体跑 fontTools.subset → 重新生成 manifest.json。
子集字符集:ASCII 可打印字符 + GB2312 全部合法码位(一级 3755 + 二级 3008 汉字, 含全角标点、希腊/俄文、全角数字)+ 常用中文标点与数字符号,共 7553 字符。
子集化参数:
python -m fontTools.subset <源字体> \
--flavor=woff2 \
--layout-features='kern,liga,clig,calt,ccmp,locl,mark,mkmk' \
--name-IDs='*' --name-languages='*' \
--recommended-glyphs --drop-tables+=DSIG \
--text="$(字符集)" --output-file=<id>-<weight>.woff2
去掉 CJK 竖排(vert/vrt2)等用不到的 OpenType 特性以压体积;保留 kern/liga 等排版特性。
如何使用
web/src/shared/styles/fonts.css 为每套字体写好 @font-face(font-display: swap)
与 --font-<id> 变量。在全局样式入口加一行即可生效:
@import './fonts.css';
CSS 里的 url() 是相对 web/src/shared/styles/ 的 ../../../../vendor/fonts/...。
Vite 构建时会把这些 woff2 作为资源打进产物(输出到 server/internal/webui/assets/),
运行时不再依赖仓库外的路径。
如何新增字体
- 把源字体(
.otf/.ttf)放到~/Fonts/<目录>/(不要直接复制进仓库)。 - 在
tools/fonts.conf追加一行:id|显示名|font-family|分类|授权|来源说明|Regular 源文件|Bold 源文件。 - 重跑
PYTHON=... vendor/fonts/tools/subset-fonts.sh,它会生成<id>-regular.woff2、<id>-bold.woff2并更新manifest.json。 - 在
web/src/shared/styles/fonts.css补对应@font-face和--font-<id>变量。 - 检查单套合计 ≤ 4 MB;超了就精简字符集或换更轻的字重。
已知限制
- MiSans 缺
・(U+30FB,日文片假名中点,GB2312 内含),其余 7552 个字符齐全; 中文场景无影响。其余三套字符集全覆盖。 - 只做 Regular + Bold 两档;如需 Medium/Light,按上节流程加字重(需扩展
fonts.conf的字段格式)。 - 字体文件已子集化,不要用原始
~/Fonts大字体覆盖本目录文件。