refactor: move update pipeline into dialog

This commit is contained in:
Qiufeng
2026-09-04 01:02:12 +08:00
parent 340d9b5245
commit a61860fcb3
2 changed files with 62 additions and 29 deletions
+43 -28
View File
@@ -273,6 +273,7 @@ export default function UpdatePage({
const [actionBusy, setActionBusy] = useState(false); const [actionBusy, setActionBusy] = useState(false);
const [reloadReady, setReloadReady] = useState(false); const [reloadReady, setReloadReady] = useState(false);
const [showNotesDialog, setShowNotesDialog] = useState(false); const [showNotesDialog, setShowNotesDialog] = useState(false);
const [showPipelineDialog, setShowPipelineDialog] = useState(false);
const [now, setNow] = useState(() => Date.now()); const [now, setNow] = useState(() => Date.now());
const announced = useRef<string | null>(null); const announced = useRef<string | null>(null);
@@ -338,6 +339,10 @@ export default function UpdatePage({
}, [isMock]); }, [isMock]);
const job = info?.job; const job = info?.job;
useEffect(() => {
if (job && activeStatuses.has(job.status)) setShowPipelineDialog(true);
}, [job?.id, job?.status]);
const applyQueuedAt = timestamp(job?.applyQueuedAt); const applyQueuedAt = timestamp(job?.applyQueuedAt);
const restartAt = const restartAt =
timestamp(job?.restartDeadline) ?? timestamp(job?.restartDeadline) ??
@@ -468,6 +473,7 @@ export default function UpdatePage({
mockTimer.current = null; mockTimer.current = null;
setActionBusy(false); setActionBusy(false);
setConfirmVersion(null); setConfirmVersion(null);
setShowPipelineDialog(true);
if (confirmAction === "download") { if (confirmAction === "download") {
handleScenarioChange("downloading_30"); handleScenarioChange("downloading_30");
notify?.("Mock:开始模拟下载,状态已流转至 [下载中]", "info"); notify?.("Mock:开始模拟下载,状态已流转至 [下载中]", "info");
@@ -496,6 +502,7 @@ export default function UpdatePage({
setConfirmVersion(null); setConfirmVersion(null);
setReloadReady(false); setReloadReady(false);
setLiveInfo((current) => (current ? { ...current, job: result.job } : current)); setLiveInfo((current) => (current ? { ...current, job: result.job } : current));
setShowPipelineDialog(true);
notify?.( notify?.(
confirmAction === "download" ? "更新包下载已开始" : "更新已开始,服务会短暂重启", confirmAction === "download" ? "更新包下载已开始" : "更新已开始,服务会短暂重启",
"info" "info"
@@ -715,11 +722,18 @@ export default function UpdatePage({
</Surface> </Surface>
</div> </div>
{/* Stepper Process Card */} {/* Stepper Process Dialog */}
<Surface className="tn-stepper-surface"> <Dialog
visible={showPipelineDialog}
header="版本升级流水线"
confirmBtn={{ content: "关闭", theme: "default" }}
cancelBtn={null}
onConfirm={() => setShowPipelineDialog(false)}
onClose={() => setShowPipelineDialog(false)}
>
<div className="tn-stepper-surface">
<div className="tn-stepper-head"> <div className="tn-stepper-head">
<div> <div>
<h3 className="tn-section-heading">版本升级流水线</h3>
<small className="tn-section-subheading"> <small className="tn-section-subheading">
标准化发布流程:版本发现 → 校验签名与清单 → 安全暂存 → 原子切换并重启 标准化发布流程:版本发现 → 校验签名与清单 → 安全暂存 → 原子切换并重启
</small> </small>
@@ -834,7 +848,8 @@ export default function UpdatePage({
<span>更新成功完成!新版本已通过内置端点健康检查,账本数据与附件完整无损。</span> <span>更新成功完成!新版本已通过内置端点健康检查,账本数据与附件完整无损。</span>
</div> </div>
)} )}
</Surface> </div>
</Dialog>
{/* Release Details Section */} {/* Release Details Section */}
{latest ? ( {latest ? (
@@ -856,32 +871,8 @@ export default function UpdatePage({
</small> </small>
)} )}
</div> </div>
<div className="tn-release-header-actions">
{notes && (
<Button
variant="outline"
size="medium"
onClick={() => setShowNotesDialog(true)}
icon={<FileCode size={15} />}
>
查看完整更新日志
</Button>
)}
</div>
</div> </div>
{/* Release Notes Preview snippet */}
{notes && (
<div className="tn-release-notes-box">
<div className="tn-release-notes-heading">
<span>更新内容概览</span>
</div>
<div className="tn-release-notes-content">
<MarkdownNotes value={notes} compact />
</div>
</div>
)}
{/* Integrity & compatibility facts grid */} {/* Integrity & compatibility facts grid */}
<div className="tn-facts-grid"> <div className="tn-facts-grid">
<div className="tn-fact-item"> <div className="tn-fact-item">
@@ -963,6 +954,30 @@ export default function UpdatePage({
</Surface> </Surface>
)} )}
{latest && notes && (
<Surface className="tn-release-notes-surface">
<div className="tn-release-notes-header">
<div>
<span className="tn-eyebrow">更新日志</span>
<h3 className="tn-section-heading">本次版本更新内容</h3>
</div>
<Button
variant="outline"
size="medium"
onClick={() => setShowNotesDialog(true)}
icon={<FileCode size={15} />}
>
查看完整日志
</Button>
</div>
<div className="tn-release-notes-box">
<div className="tn-release-notes-content">
<MarkdownNotes value={notes} compact />
</div>
</div>
</Surface>
)}
{/* Manual source warning if not systemd */} {/* Manual source warning if not systemd */}
{!info.configured && ( {!info.configured && (
<div className="tn-update-explainer"> <div className="tn-update-explainer">
+19 -1
View File
@@ -847,6 +847,17 @@ input:focus-visible, textarea:focus-visible, select:focus-visible {
margin-bottom: 16px; margin-bottom: 16px;
padding: 20px; padding: 20px;
} }
.tn-release-notes-surface {
margin-bottom: 16px;
padding: 20px;
}
.tn-release-notes-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 12px;
}
.tn-release-header { .tn-release-header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
@@ -870,7 +881,7 @@ input:focus-visible, textarea:focus-visible, select:focus-visible {
color: var(--tn-text-secondary); color: var(--tn-text-secondary);
} }
.tn-release-notes-box { .tn-release-notes-box {
margin: 16px 0; margin: 0;
padding: 12px 16px; padding: 12px 16px;
background: #f8fafc; background: #f8fafc;
border: 1px solid var(--tn-border); border: 1px solid var(--tn-border);
@@ -1064,6 +1075,13 @@ input:focus-visible, textarea:focus-visible, select:focus-visible {
.tn-release-header { .tn-release-header {
flex-direction: column; flex-direction: column;
} }
.tn-release-notes-header {
align-items: flex-start;
flex-direction: column;
}
.tn-release-notes-header .t-button {
width: 100%;
}
.tn-release-card-actions { .tn-release-card-actions {
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;