77 lines
5.0 KiB
C#
77 lines
5.0 KiB
C#
namespace Ananta.Server.App.Admin;
|
||
|
||
/// <summary>
|
||
/// Presentation only: 简易 / 详细 两档显示模式,从捐赠端 7k-v0.6 的
|
||
/// Ananta.App/Admin/AdminViewModeParts.cs 移植过来。
|
||
///
|
||
/// 设计原则(照搬捐赠端注释):<b>Hide prose only</b> —— 只藏散文,
|
||
/// 控件 / 标签 / 实时结果 / 报错一律保留。所以规则里带两层守卫:
|
||
/// ① :not(:has(控件…)) 段落里万一嵌了按钮就不会被藏;
|
||
/// ② :not([role=status]) 带 ARIA live 的「加载中 / 加载失败」状态行必须留着,
|
||
/// 否则简易模式下报错会被一起藏掉(规则 249:每次点击都必须有回显)。
|
||
///
|
||
/// 三个片段分别进 <style>、顶栏、<script>,JS 自举,不需要额外接线。
|
||
/// 默认简易(body 初始就带 gm-simple),**不持久化**:每次打开都回简易。
|
||
/// </summary>
|
||
internal static class AdminViewModeParts
|
||
{
|
||
internal const string Css = """
|
||
/* ---- 简易 / 详细 显示模式 ---- */
|
||
.gm-view-mode{display:flex;align-items:center;gap:7px;white-space:nowrap}
|
||
.gm-view-mode .lbl{font-size:11.5px;color:var(--txt-3)}
|
||
.gm-view-switch{position:relative;display:block;width:44px;height:24px;margin:0;cursor:pointer;flex:0 0 auto}
|
||
.gm-view-switch input[type=checkbox]{position:absolute;inset:0;width:100%;height:100%;opacity:0;margin:0;cursor:pointer;z-index:1}
|
||
.gm-view-track{display:block;height:24px;box-sizing:border-box;border-radius:18px;
|
||
background:#1a212b;border:1px solid var(--line);pointer-events:none;transition:background .15s,border-color .15s}
|
||
.gm-view-track:before{content:'';position:absolute;left:3px;top:3px;width:18px;height:18px;border-radius:50%;
|
||
background:var(--txt-3);transition:transform .15s,background .15s}
|
||
.gm-view-switch input:checked+.gm-view-track{background:var(--acc);border-color:var(--acc)}
|
||
.gm-view-switch input:checked+.gm-view-track:before{transform:translateX(20px);background:#fff}
|
||
.gm-view-switch input:focus-visible+.gm-view-track{outline:2px solid var(--acc);outline-offset:3px}
|
||
/* 当前档位的文字高亮 */
|
||
body.gm-simple #gmSimpleLabel,body:not(.gm-simple) #gmDetailedLabel{color:var(--acc);font-weight:600}
|
||
/* 只藏散文。控件 / 标签 / 实时结果 / 报错一律保留。
|
||
⛑ :is(...) 与 :not(...) 之间【不能换行/newline】——CSS 里换行 = 后代组合器,
|
||
会变成「藏段落里的 <b>/<code>」而不是「藏段落」,散文一个都藏不掉(踩过)。
|
||
:has 守卫也顺带保护「以后有人在说明段落里加按钮」的情况。 */
|
||
body.gm-simple :is(.sec p, .hint, details.help, .gm-detail-only):not(:has(input,select,textarea,button,a,[role=button],[role=switch],[role=status],[aria-live],[tabindex])):not([role=status]):not([aria-live]){display:none!important}
|
||
/* 空的输出黑窗(占位文字 "> 就绪 — 等待操作")在简易模式下也收起来。
|
||
⛑ 只藏【空】的:一旦 JS 往里写了结果,:empty 不成立,窗口立刻回来
|
||
—— 规则 249「每次点击都必须有回显」不能破。 */
|
||
body.gm-simple pre:empty{display:none!important}
|
||
/* 调参说明文字:车流 / 人流两张卡是 JS 动态渲染的(renderTraffic / renderCrowd /
|
||
renderCrowdTypes),第三列那串中文没有 class ⇒ 上面的 :is() 命中不了,单独靠 .gm-tip 收。
|
||
⛑ 以后新增的动态说明一律套 class="gm-tip",简易模式自动跟随。
|
||
地铁图的图例 / 副标题(MetroCardParts 的 .mm-*)同理。 */
|
||
body.gm-simple :is(.gm-tip,.mm-sub,.mm-legend,.mm-dir){display:none!important}
|
||
@media(prefers-reduced-motion:reduce){.gm-view-track:before{transition:none}}
|
||
""";
|
||
|
||
internal const string Card = """
|
||
<div class="gm-view-mode" aria-label="页面显示模式">
|
||
<span class="lbl" id="gmSimpleLabel">简易</span>
|
||
<label class="gm-view-switch"><input id="gmDetailedMode" type="checkbox" role="switch"
|
||
aria-label="详细模式" autocomplete="off"><span class="gm-view-track" aria-hidden="true"></span></label>
|
||
<span class="lbl" id="gmDetailedLabel">详细</span>
|
||
</div>
|
||
""";
|
||
|
||
internal const string Script = """
|
||
(()=>{
|
||
const sw=document.getElementById('gmDetailedMode');
|
||
if(!sw) return;
|
||
function apply(){
|
||
const simple=!sw.checked;
|
||
document.body.classList.toggle('gm-simple',simple);
|
||
// 简易 = 最少装饰:侧栏跟着收起(详细则展开)
|
||
document.body.classList.toggle('collapsed',simple);
|
||
}
|
||
// 每次打开(含 bfcache 前进/后退)都回简易;不记住上次的偏好
|
||
function reset(){ sw.checked=false; apply(); }
|
||
sw.addEventListener('change',apply);
|
||
window.addEventListener('pageshow',reset);
|
||
reset();
|
||
})();
|
||
""";
|
||
}
|