feat(perform): 演出配置页(模式切换) + 镜头可视框始终可见

P1 反馈两处修改:
- 顶部加「海选审核 / 演出配置」模式切换;演出配置=独立页,左列仅已确认事件,
  选中即内嵌白模预览(弃用原弹窗),为 P2 在此配置演出细节打底
- 修镜头框只在 dialogue 显式带 camera 时才画的 bug:改为镜头可视区域框始终可见,
  显式镜头点优先→跟随说话人→跟玩家→场景中心,框尺寸按世界单位随舞台缩放+焦点十字
- timeline.js 从弹窗固定ID重构为挂载到任意容器 Timeline.show(host,...);
  离线模型测试复跑两样张全过,重构未破坏逻辑
This commit is contained in:
2026-06-13 11:15:20 +08:00
parent dbf857769e
commit 2a3cf2c66b
4 changed files with 157 additions and 107 deletions

View File

@ -223,15 +223,33 @@ button.mini { padding:2px 8px; font-size:12px; }
.pt-choices button.locked { opacity:.55; }
.pt-q { color:#b89a5a; font-size:12px; margin:8px 0 4px; }
/* ---- 模式切换 ---- */
.mode-switch { display:flex; gap:0; border:1px solid #5a4a32; border-radius:6px; overflow:hidden; }
.mode-btn { background:#241f18; color:#9a8f7e; border:none; border-radius:0; padding:6px 14px; }
.mode-btn:hover:not(:disabled) { background:#2e2820; }
.mode-btn.active { background:#5a4a26; color:#f3dca0; }
header .who { margin-left:auto; font-size:12px; color:#9a8f7e; }
/* ---- 演出配置页 ---- */
#perform-wrap { display:flex; flex:1; min-height:0; }
#wrap.hidden, #perform-wrap.hidden { display:none; }
#perform-list-pane { width:250px; background:#19150f; border-right:1px solid #3a322a;
display:flex; flex-direction:column; flex:none; }
.perform-listhead { padding:10px 12px; font-size:12px; color:#9a8f7e; letter-spacing:1px;
border-bottom:1px solid #3a322a; background:#1f1a15; }
#perform-list { overflow:auto; flex:1; }
#perform-main { flex:1; min-width:0; overflow:auto; padding:16px 18px; }
#perform-main .empty-center { position:static; inset:auto; min-height:240px; }
/* ---- 演出预览timeline + 白模舞台)---- */
.modal.huge { width:840px; max-width:94vw; }
.tl-mapinfo { font-size:12px; color:#9a8f7e; margin-left:12px; font-weight:normal; }
#tl-stagewrap { background:#15130d; border:1px solid #3a322a; border-radius:6px; overflow:hidden; line-height:0; }
#tl-stage { width:100%; height:auto; display:block; }
#tl-controls { display:flex; align-items:center; gap:10px; margin:10px 0 6px; }
#tl-controls .tip { font-size:11.5px; color:#7a7264; }
.tl-mapinfo { font-size:12px; color:#9a8f7e; margin-bottom:8px; }
.tl-stagewrap { background:#15130d; border:1px solid #3a322a; border-radius:6px; overflow:hidden;
line-height:0; max-width:820px; }
.tl-stage { width:100%; height:auto; display:block; }
.tl-controls { display:flex; align-items:center; gap:10px; margin:10px 0 6px; max-width:820px; }
.tl-controls .tip { font-size:11.5px; color:#7a7264; }
.tl-time { font-size:13px; color:#e6c878; font-variant-numeric:tabular-nums; min-width:90px; }
#tl-tracks { position:relative; overflow-x:auto; overflow-y:hidden; max-height:34vh;
.tl-tracks { position:relative; overflow-x:auto; overflow-y:auto; max-height:32vh;
background:#19150f; border:1px solid #3a322a; border-radius:6px; padding-top:20px; }
.tl-ruler { position:relative; height:16px; border-bottom:1px solid #2a2419; }
.tl-tick { position:absolute; top:0; height:16px; border-left:1px solid #2a2419; }
@ -243,7 +261,7 @@ button.mini { padding:2px 8px; font-size:12px; }
.tl-clip { position:absolute; top:3px; height:22px; line-height:22px; padding:0 5px;
font-size:11px; color:#1a1710; border-radius:3px; overflow:hidden; white-space:nowrap;
text-overflow:ellipsis; cursor:pointer; box-sizing:border-box; box-shadow:0 1px 2px rgba(0,0,0,.4); }
.tl-clip.active { outline:2px solid #fff; outline-offset:-1px; z-index:2; }
.tl-tracks .tl-clip.active { outline:2px solid #fff; outline-offset:-1px; z-index:2; }
.tl-clip.k-dialogue { background:#7ec8e3; }
.tl-clip.k-move { background:#e6c878; }
.tl-clip.k-anim { background:#9ee37e; }