style(panel): 诊断/关于 改为扁平区块,修按钮断行与缺失的 chip 类

这两个区块各自只有单一内容,卡片外框显得厚重;按钮作为 flex 项被压窄导致
"导出诊断包(.tar.gz)" / "查看面板日志" 在按钮内断行。

- 去掉 inst-card 卡片外框,改为扁平 settings-block:标题下直接排描述/控件/操作。
- 主按钮 s-btn 固定内边距 + white-space:nowrap + flex:none,不再被压窄断行;
  次要操作(查看面板日志 / 检查更新 / 发布日志)改 btn-text 文字链接,narrow 下自然换行。
- 修复:时间范围 chip 漏了 .chip 基类(只有 .chip-toggle 无内边距/圆角),补回 'chip chip-toggle'。
- 「导出诊断包(.tar.gz)」按钮文案精简为「导出诊断包」,格式说明移到脚注。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Gloridust
2026-06-15 01:33:20 +08:00
Unverified
parent d42d401f89
commit 0811d463e8
2 changed files with 122 additions and 75 deletions
+64 -71
View File
@@ -106,32 +106,27 @@ function DiagnosticsSection() {
<div className="section-row" style={{ marginTop: 22 }}>
<span className="section-title"></span>
</div>
<div className="inst-grid">
<div className="inst-card">
<div className="inst-head">
<span className="inst-name"></span>
<div className="settings-block">
<p className="s-desc">/Docker + + + </p>
<div className="s-field">
<span className="field-label"></span>
<div className="chip-row">
{DIAG_RANGE_OPTIONS.map((r) => (
<button key={r.key} className={'chip chip-toggle' + (range === r.key ? ' on' : '')} onClick={() => setRange(r.key)}>
{r.label}
</button>
))}
</div>
<div className="inst-sub">/Docker + + + </div>
<div className="diag-range">
<span className="field-label"></span>
<div className="chip-row">
{DIAG_RANGE_OPTIONS.map((r) => (
<button key={r.key} className={'chip-toggle' + (range === r.key ? ' on' : '')} onClick={() => setRange(r.key)}>
{r.label}
</button>
))}
</div>
</div>
<div className="inst-actions">
<button className="btn btn-primary" onClick={exportBundle}>
(.tar.gz)
</button>
<a className="btn" href={api.panelLogUrl(range)} target="_blank" rel="noreferrer">
</a>
</div>
<div className="muted small ver-checked">/</div>
</div>
<div className="settings-actions">
<button className="btn btn-primary s-btn" onClick={exportBundle}>
</button>
<a className="btn-text" href={api.panelLogUrl(range)} target="_blank" rel="noreferrer">
</a>
</div>
<p className="s-foot">.tar.gz / </p>
</div>
</>
);
@@ -173,54 +168,52 @@ function AboutSection({ isAdmin }: { isAdmin: boolean }) {
<div className="section-row" style={{ marginTop: 22 }}>
<span className="section-title"></span>
</div>
<div className="inst-grid">
<div className="inst-card">
<div className="inst-head">
<span className="inst-name"> · WechatOnCloud</span>
{info?.hasUpdate ? <span className="tag tag-warn"></span> : info && !isRelease ? <span className="tag"></span> : null}
</div>
<div className="inst-sub">
<b>{info?.current ?? '…'}</b>
{info?.hasUpdate && info.latest && (
<>
{' · '} <b>{info.latest}</b>
</>
)}
{isRelease && info && !info.hasUpdate && info.latest && !info.error && <>{' · '}</>}
{!isRelease && info?.latest && !info.error && (
<>
{' · '} <b>{info.latest}</b>
</>
)}
</div>
{info?.hasUpdate && (
<div className="ver-hint">
宿 <code>docker compose pull &amp;&amp; docker compose up -d</code>
</div>
)}
<div className="inst-actions">
{isAdmin && (
<button className="btn" disabled={checking} onClick={check}>
{checking ? '检查中…' : '检查更新'}
</button>
)}
<a className="btn" href={RELEASES_URL} target="_blank" rel="noreferrer">
</a>
{info?.hasUpdate && (
<a className="btn btn-primary" href={RELEASES_URL + '/latest'} target="_blank" rel="noreferrer">
</a>
)}
</div>
{info && (
<div className="muted small ver-checked">
{info.checkedAt ? `上次检查 ${fmtDate(info.checkedAt)}` : '尚未检查'}
{info.source && ` · 来源 ${info.source}`}
{info.error && ` · ${info.error}`}
</div>
)}
<div className="settings-block">
<div className="s-title-row">
<span className="s-app"> · WechatOnCloud</span>
{info?.hasUpdate ? <span className="tag tag-warn"></span> : info && !isRelease ? <span className="tag"></span> : null}
</div>
<p className="s-line">
<b>{info?.current ?? '…'}</b>
{info?.hasUpdate && info.latest && (
<>
{' · '} <b>{info.latest}</b>
</>
)}
{isRelease && info && !info.hasUpdate && info.latest && !info.error && <>{' · '}</>}
{!isRelease && info?.latest && !info.error && (
<>
{' · '} <b>{info.latest}</b>
</>
)}
</p>
{info?.hasUpdate && (
<div className="ver-hint">
宿 <code>docker compose pull &amp;&amp; docker compose up -d</code>
</div>
)}
<div className="settings-actions">
{info?.hasUpdate && (
<a className="btn btn-primary s-btn" href={RELEASES_URL + '/latest'} target="_blank" rel="noreferrer">
</a>
)}
{isAdmin && (
<button className="btn-text" disabled={checking} onClick={check}>
{checking ? '检查中…' : '检查更新'}
</button>
)}
<a className="btn-text" href={RELEASES_URL} target="_blank" rel="noreferrer">
</a>
</div>
{info && (
<p className="s-foot">
{info.checkedAt ? `上次检查 ${fmtDate(info.checkedAt)}` : '尚未检查'}
{info.source && ` · 来源 ${info.source}`}
{info.error && ` · ${info.error}`}
</p>
)}
</div>
</>
);
+58 -4
View File
@@ -1047,14 +1047,68 @@ button {
gap: 6px;
margin-top: 4px;
}
/* 诊断包时间范围选择行 */
.diag-range {
margin-top: 12px;
/* 扁平设置区块(诊断与日志 / 关于):无卡片,直接排在分区标题下,避免单卡片的厚重感 */
.settings-block {
padding: 2px 2px 4px;
}
.diag-range .field-label {
.settings-block .s-desc {
margin: 4px 0 0;
font-size: 13px;
line-height: 1.65;
color: var(--muted);
max-width: 660px;
}
.s-field {
margin-top: 14px;
}
.s-field .field-label {
display: block;
margin: 0 2px 8px;
}
.settings-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 14px;
margin-top: 16px;
}
/* 实心主按钮:固定内边距 + 不换行(之前作为 flex 项被压窄导致按钮内文字断行) */
.settings-actions .s-btn {
height: 42px;
padding: 0 22px;
flex: none;
white-space: nowrap;
}
.settings-actions .btn-text {
white-space: nowrap;
}
.s-foot {
margin: 14px 0 0;
font-size: 12px;
line-height: 1.6;
color: var(--muted);
max-width: 660px;
}
.s-title-row {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.s-app {
font-size: 15px;
font-weight: 600;
color: var(--text);
}
.s-line {
margin: 8px 0 0;
font-size: 14px;
color: var(--muted);
}
.s-line b {
color: var(--text);
font-weight: 600;
}
.chip-row-pick {
display: flex;
}