chore(release): 1.1.36 - 应用内流式直连下载、透明化直链与排队卡死彻底修复
TallyNote release / linux-x64 (push) Successful in 6m21s

This commit is contained in:
Qiufeng
2026-09-04 16:51:43 +08:00
parent c791dc4915
commit 2accca9a22
14 changed files with 15603 additions and 45 deletions
+43 -18
View File
@@ -1,3 +1,4 @@
import { BeamLoading, BeamBar } from "../../components/BeamLoading";
import { useState, useEffect, useRef, useMemo, type ReactNode } from "react";
import {
RefreshCw,
@@ -48,6 +49,8 @@ export interface UpdateJob {
version: string;
platform: string;
assetName?: string | null;
assetUrl?: string | null;
releaseUrl?: string | null;
sizeBytes?: number | null;
downloadedBytes?: number | null;
downloadStartedAt?: number | string | null;
@@ -73,6 +76,8 @@ export interface LatestRelease {
releaseNotes?: string;
body?: string;
releaseUrl?: string;
metadataUrl?: string;
assetUrl?: string;
compatible: boolean;
integrityReady: boolean;
assetName: string;
@@ -609,8 +614,7 @@ export default function UpdatePage({
{loading && !info ? (
<Surface className="tn-update-loading-surface">
<RefreshCw size={24} className="tn-spin text-primary" />
<p>正在读取系统更新服务状态…</p>
<BeamLoading text="正在读取系统更新服务状态…" />
</Surface>
) : !info ? (
<Surface className="tn-empty-surface">
@@ -662,7 +666,7 @@ export default function UpdatePage({
{info.checkedAt ? dateText(info.checkedAt, timezone) : "未检查"}
</div>
<div className="tn-metric-foot">
<small>数据源: 官方发布渠道</small>
<small>源: git.awaioi.com (HTTPS)</small>
</div>
</Surface>
</div>
@@ -709,10 +713,32 @@ export default function UpdatePage({
</div>
<div className="tn-ascii-info-item">
<span className="tn-ascii-info-label">下载策略:</span>
<span className="tn-ascii-info-val">后台静默传输</span>
<span className="tn-ascii-info-val">应用内流式直连 (零调度等待)</span>
</div>
</div>
<div style={{ marginTop: 14, padding: "10px 14px", background: "var(--tn-navy-50)", border: "1px solid var(--tn-navy-100)", borderRadius: 6, display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 8, fontSize: "12.5px" }}>
<div style={{ display: "flex", flexDirection: "column", gap: 2, minWidth: 260, flex: 1 }}>
<span style={{ color: "var(--tn-navy-800)", fontWeight: 500 }}>
安装包下载直链 ({latest.assetName || "发布包"}):
</span>
<code style={{ fontSize: "11.5px", color: "var(--tn-navy-600)", wordBreak: "break-all" }}>
{latest.assetUrl || `https://git.awaioi.com/awaioi/TallyNote/releases/download/v${latest.version}/${latest.assetName || `tallynote-${latest.version}-linux-x64-glibc.tar.gz`}`}
</code>
</div>
<Button
size="small"
variant="outline"
onClick={() => {
const url = latest.assetUrl || `https://git.awaioi.com/awaioi/TallyNote/releases/download/v${latest.version}/${latest.assetName || `tallynote-${latest.version}-linux-x64-glibc.tar.gz`}`;
navigator.clipboard.writeText(url);
notify?.("已复制安装包下载直链", "success");
}}
>
复制直链
</Button>
</div>
<div className="tn-ascii-release-actions">
{canDownload && (
<Button
@@ -852,7 +878,10 @@ export default function UpdatePage({
{/* 场景 A: 实时下载中态 (Exact ASCII) */}
{job?.status === "downloading" && (
<div className="tn-modal-card-box">
<div className="tn-modal-card-title">正在从官方发布渠道下载更新包...</div>
<div className="tn-modal-card-title">正在从官方源直接流式拉取更新包...</div>
<div style={{ fontSize: "12px", color: "var(--tn-navy-600)", margin: "-4px 0 12px 0", wordBreak: "break-all" }}>
请求地址: <code>{job.assetUrl || latest?.assetUrl || `https://git.awaioi.com/awaioi/TallyNote/releases/download/v${latest?.version || job.version}/${job.assetName || "release.tar.gz"}`}</code>
</div>
<div
className="tn-progress-stream"
role="progressbar"
@@ -877,7 +906,7 @@ export default function UpdatePage({
</div>
<div className="tn-modal-info-note">
[i] 更新包在后台独立下载,数据经 TLS 加密传输,不影响当前系统的正常记账与导出操作。
[i] 更新包由应用进程直接流式拉取并自动比对 SHA-256 校验和,0 秒秒级启动,无需等待外部系统守护进程调度。
</div>
<div className="tn-modal-actions-bar">
@@ -888,22 +917,18 @@ export default function UpdatePage({
</div>
)}
{/* 场景 B: 任务调度中 (queued) (Exact ASCII) */}
{/* 场景 B: 建立连接中 (queued) (Exact ASCII) */}
{job?.status === "queued" && (
<div className="tn-modal-card-box">
<div className="tn-modal-card-title">
<RefreshCw size={15} className="tn-spin" style={{ display: "inline-block", marginRight: 8, verticalAlign: "middle" }} />
正在等待后台系统守护进程认领任务...
<div style={{ marginBottom: 12 }}><BeamBar width={160} /></div>正在建立与官方 Git 仓库的流式传输连接...
</div>
<div style={{ fontSize: "13.5px", color: "var(--tn-navy-900)", marginBottom: 8 }}>
已等待: <strong>{queuedSeconds} 秒</strong> (超过 20 秒未响应将自动超时释放,避免系统死锁)
<div style={{ fontSize: "12px", color: "var(--tn-navy-600)", margin: "4px 0 14px 0", wordBreak: "break-all" }}>
目标地址: <code>{job.assetUrl || latest?.assetUrl || "https://git.awaioi.com"}</code>
</div>
<p className="text-secondary" style={{ fontSize: "13px", margin: "0 0 16px 0", lineHeight: 1.6 }}>
若长时间未开始,通常为后台守护服务未激活,您可以点击下方按钮立即取消排队。
</p>
<div className="tn-modal-actions-bar">
<Button theme="primary" variant="outline" onClick={() => void cancelJob()} loading={cancelling} disabled={cancelling}>
主动取消排队
<Button variant="outline" onClick={() => void cancelJob()} loading={cancelling} disabled={cancelling}>
取消
</Button>
</div>
</div>
@@ -941,8 +966,8 @@ export default function UpdatePage({
{/* 场景 D: 数据快照备份中或服务重启中 (backing_up / applying) (Exact ASCII) */}
{(job?.status === "backing_up" || job?.status === "applying") && (
<div className="tn-modal-card-box">
<div className="tn-modal-card-title" style={{ display: "flex", alignItems: "center", gap: 8 }}>
<RefreshCw size={18} className="tn-spin" />
<div className="tn-modal-card-title">
<div style={{ marginBottom: 12 }}><BeamBar width={180} /></div>
服务正在平滑重启并执行健康检查...
</div>
<div style={{ fontSize: "14px", color: "var(--tn-navy-900)", margin: "10px 0 8px" }}>