Files

77 lines
5.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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:每次点击都必须有回显)。
///
/// 三个片段分别进 &lt;style&gt;、顶栏、&lt;script&gt;,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();
})();
""";
}