Files
simba-rmic-2026/desktop/src/styles/console.css
T
sloray 896b21fe44
构建客户端 / 检查(类型 + 单元测试) (push) Canceled after 0s
构建客户端 / Linux x64(deb + AppImage) (push) Canceled after 0s
构建客户端 / Windows x64(NSIS 安装包) (push) Canceled after 0s
构建客户端 / macOS 通用(.app + .dmg) (push) Canceled after 0s
feat(client): RMIC::2026 界面重做、可计算的版本机制与固件版本联动
- feat(client): 界面换成墨黑蓝底 + 单支红的矩形语言,切角全部去掉,仅装甲条保留平行四边形
- feat(client): 自托管 HarmonyOS Sans SC 与 JetBrains Mono,中文与拉丁数字逐字回退
- feat(client): 新增启动序列、首启门、用户端 HUD、裁判端控制台、设置抽屉与固件维护页
- feat(client): 裁判端中缝与下方控制台可拖,鼠标落在哪一路下方就看哪一路
- feat(client): 设置抽屉常驻实时预览,与画面共用同一份准星绘制代码
- feat(client): 动效改用 Material 3 的缓动曲线与时长,逐条替换掉自造的贝塞尔
- feat(version): 版本号与 CHANGELOG 由 scripts/version.mjs 从 git 历史算出,不再手写
- feat(firmware): Hello 报文携带语义化版本、构建号与自报协议号,负载向后兼容
- feat(client): 固件版本显示在绑定列表与裁判端每一格;协议不匹配时给出具体原因
- feat(firmware): 固件包版本与客户端同源,都从 version.json 读
- fix(client): getCurrentWindow() 在没有 Tauri 注入时同步抛异常,浏览器预览整棵树被卸载
- fix(client): 启动序列的淡出 effect 清掉了自己刚设的 setTimeout,界面永远停在启动页
- fix(client): 设置抽屉左侧导航的锚点没挂到 section 上,且用错了坐标系
- fix(protocol): Hello 改用宽松帧头解析,让协议不匹配的板子能被解释而不是静默消失
- fix(build): Windows 上 bindgen 加载不了 libclang 的同目录依赖,构建脚本补上搜索路径
- fix(build): esp-idf-sys 在长路径下拒绝构建,固件构建改用短的目标目录
- build(client): 队标图标,含光学尺寸分级与手工拼的多尺寸 ICO
- build(ci): 守门 job 增加版本一致性检查,产物名改为 rmic-2026-*
- docs: 补充界面语言、版本机制与协议通告布局的说明
2026-10-19 02:40:08 +08:00

574 lines
10 KiB
CSS

/* 控制台:装甲板表、录制与回放、队伍名。
*
* 这些是"低头看"的东西,所以它们可以密、可以有刻度和线——画面那一层不可以。
*/
/* ───────────────────────────────────────────────────── 装甲板列表 */
.armor {
display: flex;
flex-direction: column;
min-width: 0;
}
/* 七列的宽度是固定的,除了最后一列(槽位)用剩余空间。定宽的意义在于:血量从 100 变成
7 时,后面的列不许挪位——那样每掉一次血整张表都会抖一下。 */
.armor__head,
.armor__row {
display: grid;
/* 地址列按内容吃掉自己的宽度,剩下的全给"槽位"——否则长窗口下中间会空出一大片,
而真正需要横向余量的槽位说明被挤成一截。 */
grid-template-columns:
46px 118px minmax(110px, max-content) 118px
132px 104px minmax(96px, 1fr);
gap: var(--s2);
align-items: center;
padding: 0 var(--s2);
}
.armor__head {
height: 22px;
border-bottom: 1px solid var(--line-2);
}
.armor__col {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.armor__head .armor__col {
font-family: var(--font-mono);
font-size: var(--fs-9);
letter-spacing: var(--track-wide);
color: var(--ink-4);
}
.armor__rows {
display: flex;
flex-direction: column;
}
.armor__row {
height: 26px;
border-bottom: 1px solid var(--line);
font-size: var(--fs-11);
transition: background-color var(--d-2) var(--e-out);
}
.armor__row:hover {
background: var(--panel-2);
}
.armor__row.is-offline {
opacity: 0.45;
}
.armor__row.is-unassigned .armor__slot {
color: var(--ink-4);
}
/* 四条上报的位图。它一眼回答"这块板子是不是只在报一条"。 */
.armor__plates {
display: inline-flex;
gap: 2px;
align-items: center;
}
.armor__plate {
width: 6px;
height: 10px;
background: var(--line-2);
transition: background-color var(--d-2) var(--e-out);
}
.armor__plate.is-on {
background: var(--ink-2);
}
.armor__id {
color: var(--ink);
letter-spacing: var(--track-tight);
}
.armor__addr {
color: var(--ink-3);
font-size: var(--fs-10);
}
.armor__team-bit {
margin-left: 6px;
padding: 0 4px;
border: 1px solid currentColor;
font-size: var(--fs-9);
opacity: 0.6;
}
.armor__col--hp {
display: flex;
align-items: center;
gap: var(--s2);
}
.armor__hp {
flex: none;
min-width: 26px;
color: var(--ink);
font-size: var(--fs-12);
}
.armor__hp.is-dead {
color: var(--error);
}
.armor__hp-track {
flex: 1;
min-width: 0;
height: 3px;
background: var(--line-2);
overflow: hidden;
}
.armor__hp-fill {
display: block;
height: 100%;
transition: width var(--d-3) var(--e-out);
}
.armor__silence {
display: inline-flex;
align-items: center;
gap: 5px;
font-family: var(--font-mono);
font-size: var(--fs-10);
}
.armor__silence.is-good {
color: var(--ink-2);
}
.armor__silence.is-warn {
color: var(--warn);
}
.armor__silence.is-bad {
color: var(--error);
}
.armor__slot {
color: var(--ink-2);
font-size: var(--fs-10);
}
.armor__empty {
padding: var(--s4) var(--s2);
max-width: 620px;
color: var(--ink-3);
font-size: var(--fs-11);
line-height: 1.8;
}
.armor__empty kbd {
padding: 0 4px;
border: 1px solid var(--line-3);
color: var(--ink-2);
font-size: var(--fs-10);
}
/* ───────────────────────────────────────────────────── 帧率读数行 */
.statsline {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
font-size: var(--fs-10);
color: var(--ink-2);
white-space: nowrap;
overflow: hidden;
}
.statsline.is-offline {
color: var(--warn);
}
.statsline--empty {
color: var(--ink-4);
}
.statsline__status {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.statsline__sep {
width: 1px;
height: 9px;
background: var(--line-2);
flex: none;
}
.statsline__nums {
color: var(--ink-3);
font-size: var(--fs-10);
}
/* ───────────────────────────────────────────────────────── 队名 */
/* 静止时它是一条读数:一个队色方块 + 一个看着像文本的值。
点进去才展开边框、键位提示与字数。两格画面下面不该永远趴着两个表单控件。 */
.tname {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 0 1 auto;
padding: 2px 4px 2px 0;
border: 1px solid transparent;
transition: border-color var(--d-2) var(--e-out);
}
.tname.is-editing {
border-color: var(--line-3);
background: var(--deep);
}
.tname.is-disabled {
opacity: 0.5;
}
.tname__label {
flex: none;
width: 16px;
height: 16px;
display: inline-flex;
align-items: center;
justify-content: center;
font-family: var(--font-mono);
font-size: var(--fs-10);
font-weight: 700;
border: 1px solid currentColor;
line-height: 1;
}
.tname__input {
flex: 1;
min-width: 60px;
max-width: 150px;
padding: 1px 2px;
background: transparent;
border: none;
border-bottom: 1px dashed var(--line-2);
color: var(--ink);
font-size: var(--fs-12);
outline: none;
transition: border-color var(--d-2) var(--e-out);
}
.tname__input:hover:not(:disabled) {
border-bottom-color: var(--line-3);
}
.tname.is-editing .tname__input {
border-bottom: 1px solid var(--primary);
}
.tname__input::placeholder {
color: var(--ink-4);
}
/* 提示只在编辑时出现:平时它会把这一行撑宽,而这一行要装帧率。 */
.tname__hint {
display: none;
align-items: center;
gap: var(--s2);
flex: none;
}
.tname.is-editing .tname__hint {
display: flex;
}
.tname__keys {
font-size: var(--fs-9);
color: var(--ink-4);
letter-spacing: var(--track-tight);
}
.tname__keys kbd {
padding: 0 3px;
margin-right: 1px;
border: 1px solid var(--line-2);
color: var(--ink-3);
font-size: var(--fs-9);
}
.tname__count {
font-size: var(--fs-9);
color: var(--ink-4);
}
/* ─────────────────────────────────────────────────── 录制与回放 */
.media {
display: flex;
flex-direction: column;
gap: var(--s2);
min-width: 0;
}
.media__actions {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--s2);
}
.media__rec-glyph {
width: 7px;
height: 7px;
background: currentColor;
}
.media__divider {
width: 1px;
height: 16px;
background: var(--line-2);
margin: 0 var(--s1);
}
.media__cam {
font-size: var(--fs-9);
color: var(--ink-3);
}
.media__spacer {
flex: 1;
}
/* —— 录制中的横条 —— */
.media__strips {
display: flex;
flex-direction: column;
gap: 3px;
}
.strip {
display: flex;
align-items: center;
gap: var(--s2);
padding: 4px var(--s2);
background: rgba(255, 84, 73, 0.08);
border: 1px solid var(--error-line);
border-left-width: 2px;
font-size: var(--fs-11);
}
.strip__pulse {
width: 6px;
height: 6px;
background: var(--error);
animation: rec-blink 1.1s steps(2, start) infinite;
}
.strip__label {
color: var(--error);
}
.strip__cam {
color: var(--ink);
font-size: var(--fs-10);
}
.strip__stats {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--ink-2);
font-size: var(--fs-10);
}
.strip__dot {
width: 2px;
height: 2px;
background: var(--ink-4);
}
.strip__warn {
color: var(--warn);
font-size: var(--fs-10);
}
.strip__error {
color: var(--error);
font-size: var(--fs-10);
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.strip > .btn {
margin-left: auto;
height: 22px;
}
/* —— 文件列表 —— */
.media__list {
display: flex;
flex-direction: column;
min-width: 0;
}
.media__head,
.media__row {
display: grid;
grid-template-columns: 52px minmax(0, 1fr) 88px 116px;
gap: var(--s2);
align-items: center;
padding: 0 var(--s2);
}
.media__head {
height: 22px;
border-bottom: 1px solid var(--line-2);
}
.media__head .media__col {
font-family: var(--font-mono);
font-size: var(--fs-9);
letter-spacing: var(--track-wide);
color: var(--ink-4);
}
.media__row {
height: 26px;
border-bottom: 1px solid var(--line);
font-size: var(--fs-11);
transition: background-color var(--d-2) var(--e-out);
}
.media__row:hover {
background: var(--panel-2);
}
.media__col {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.media__col--size {
color: var(--ink-3);
font-size: var(--fs-10);
text-align: right;
}
.media__col--acts {
display: flex;
justify-content: flex-end;
gap: 2px;
}
.media__col--acts .btn {
height: 20px;
padding: 0 6px;
font-size: var(--fs-10);
}
.media__kind {
display: inline-block;
padding: 1px 5px;
border: 1px solid var(--line-3);
font-family: var(--font-mono);
font-size: var(--fs-9);
letter-spacing: var(--track);
color: var(--ink-3);
}
.media__kind--video {
color: var(--ink);
border-color: var(--line-3);
}
.media__kind--image {
color: var(--ink-2);
}
.media__name {
color: var(--ink);
font-family: var(--font-mono);
font-size: var(--fs-10);
}
.media__empty {
padding: var(--s4) var(--s2);
color: var(--ink-3);
font-size: var(--fs-11);
}
/* —— 播放器 —— */
.playback {
margin-top: var(--s1);
border: 1px solid var(--line-2);
background: #000;
}
.playback__head {
display: flex;
align-items: center;
gap: var(--s2);
padding: 4px var(--s2);
background: var(--panel-2);
border-bottom: 1px solid var(--line-2);
}
.playback__label {
color: var(--primary);
}
.playback__name {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: var(--fs-10);
color: var(--ink-2);
}
.playback__spacer {
flex: 1;
}
.playback__head .btn {
height: 20px;
}
.playback__video {
display: block;
width: 100%;
max-height: 300px;
background: #000;
}
.playback__fallback {
display: flex;
flex-direction: column;
gap: var(--s3);
align-items: flex-start;
padding: var(--s3);
background: var(--panel);
}
.playback__warn {
color: var(--warn);
font-size: var(--fs-11);
line-height: 1.7;
}