feat: 优化版本卡片交互与自动更新安装逻辑

- 为自动更新安装函数添加静默安装与安装后自动重启参数
- 重构VersionCard组件,新增设置页模式,支持整卡点击跳转更新页并显示查看更新提示
- 修复更新页面主按钮的禁用逻辑,仅在检查或安装中时禁用按钮
- 更新通用设置主页与关于页的VersionCard调用参数
This commit is contained in:
2026-08-31 02:46:12 +08:00
parent 8fc6fcaf05
commit fa44d41d44
6 changed files with 43 additions and 67 deletions
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -557,7 +557,8 @@ class UpdateService {
} catch { } catch {
/* ignore */ /* ignore */
} }
autoUpdater.quitAndInstall(); // 静默安装(/S)+ 安装完成后自动重启(--force-run
autoUpdater.quitAndInstall(true, true);
} }
/** 获取系统下载临时目录(用于清理提示,暂未启用) */ /** 获取系统下载临时目录(用于清理提示,暂未启用) */
+34 -60
View File
@@ -3,11 +3,10 @@ import { VERSION } from "@/lib/version";
import { BUILD_COMMIT, BUILD_ID } from "@/lib/buildInfo"; import { BUILD_COMMIT, BUILD_ID } from "@/lib/buildInfo";
import { useUpdateStore } from "@/stores/updateStore"; import { useUpdateStore } from "@/stores/updateStore";
import { useRouteStore } from "@/stores/routeStore"; import { useRouteStore } from "@/stores/routeStore";
import { relaunchApp } from "@/api/update";
import Silk from "@/components/silk/Silk"; import Silk from "@/components/silk/Silk";
import { Button } from "@heroui/react";
import clsx from "clsx"; import clsx from "clsx";
import { type ReactNode, Suspense } from "react"; import { ChevronRight } from "lucide-react";
import { Suspense } from "react";
const modeColors: Record<string, string> = { const modeColors: Record<string, string> = {
dev: "#F59E0B", dev: "#F59E0B",
@@ -34,8 +33,13 @@ interface VersionCardProps {
overrideMode?: string | null; overrideMode?: string | null;
overrideState?: UpdateState | null; overrideState?: UpdateState | null;
simple?: boolean; simple?: boolean;
/** OOBE 模式:不显示 Silk 动画,按钮仅展示样式不做实际操作 */ /** OOBE 模式:仅展示样式,不显示「查看更新」入口 */
oobe?: boolean; oobe?: boolean;
/**
* 设置页模式(设置主页 / 关于页):整卡可点击跳转更新页,
* 并显示「查看更新」小字提示;其他页面为 false
*/
isSettingPage?: boolean;
} }
export function VersionCard({ export function VersionCard({
@@ -44,39 +48,33 @@ export function VersionCard({
overrideState, overrideState,
simple = false, simple = false,
oobe = false, oobe = false,
isSettingPage = false,
}: VersionCardProps) { }: VersionCardProps) {
const color = modeColors[overrideMode ?? BUILD_MODE] ?? modeColors.run; const color = modeColors[overrideMode ?? BUILD_MODE] ?? modeColors.run;
const gradient = modeGradients[overrideMode ?? BUILD_MODE] ?? modeGradients.run; const gradient = modeGradients[overrideMode ?? BUILD_MODE] ?? modeGradients.run;
const label = modeLabels[overrideMode ?? BUILD_MODE] ?? modeLabels.run; const label = modeLabels[overrideMode ?? BUILD_MODE] ?? modeLabels.run;
const { checking, downloading, installed, update, check, install } = useUpdateStore(); const { update, installed } = useUpdateStore();
// 检查更新按钮:除 OOBE 与更新日志页本身外,点击跳转到更新日志页
const current = useRouteStore((s) => s.current); const current = useRouteStore((s) => s.current);
const navigate = useRouteStore((s) => s.navigate); const navigate = useRouteStore((s) => s.navigate);
const isOnUpdatePage = current === "update";
const handleCheck = () => {
if (isOnUpdatePage) {
check();
} else {
navigate("update");
}
};
const effectiveState: UpdateState = overrideState ?? (installed ? "installed" : update ? "hasUpdate" : "latest"); const effectiveState: UpdateState = overrideState ?? (installed ? "installed" : update ? "hasUpdate" : "latest");
const Btn = (props: React.ComponentProps<typeof Button>) => ( // 设置页:整卡可点击,跳转检查更新页面(更新日志页自身不触发)
<Button const clickable = isSettingPage && !oobe && current !== "update";
size="sm" const handleCardClick = () => {
variant="ghost" if (clickable) navigate("update");
className="text-white/90 hover:text-white hover:bg-white/10 border border-white/20" };
{...props}
/>
);
return ( return (
<div <div
className={clsx("relative overflow-hidden rounded-xl border border-white/10 min-h-[200px]", className)} className={clsx(
"relative overflow-hidden rounded-xl border border-white/10 min-h-[200px]",
clickable && "cursor-pointer hover:scale-[1.01] active:scale-[0.99] transition-transform",
className,
)}
onClick={handleCardClick}
// 共享元素过渡:路由切换时(startViewTransition),新旧页面中同名 view-transition-name // 共享元素过渡:路由切换时(startViewTransition),新旧页面中同名 view-transition-name
// 的元素会从上一个位置平滑移动/形变到当前页面的位置 // 的元素会从上一个位置平滑移动/形变到当前页面的位置
style={{ viewTransitionName: "version-card" } as React.CSSProperties} style={{ viewTransitionName: "version-card" } as React.CSSProperties}
@@ -93,7 +91,7 @@ export function VersionCard({
</Suspense> </Suspense>
)} )}
{/* 内容(移除颜色遮罩层,保留底部渐变与 Silk 动画渲染) */} {/* 内容 */}
<div className="relative z-10 flex flex-col items-center justify-center px-6 py-10 gap-4"> <div className="relative z-10 flex flex-col items-center justify-center px-6 py-10 gap-4">
<span className="text-[11px] font-bold tracking-wider text-white/70">{label}</span> <span className="text-[11px] font-bold tracking-wider text-white/70">{label}</span>
<img <img
@@ -113,43 +111,19 @@ export function VersionCard({
</p> </p>
)} )}
{/* 更新日志页内不显示任何按钮(更新操作由页面底部遮罩负责 */} {/* 更新状态提示(仅信息,不提供按钮;下载/安装操作在更新页底部完成 */}
{!isOnUpdatePage && ( {effectiveState !== "latest" && (
<> <p className="text-[12px] text-white/80">
{/* OOBE 模式:仅显示查看亮点按钮 */} {effectiveState === "hasUpdate" ? "有新的版本可用" : "更新已下载"}
{oobe ? ( </p>
<div className="flex items-center gap-2 mt-1">
<Btn></Btn>
</div>
) : (
<div className="flex items-center gap-2 mt-1">
{effectiveState === "latest" && (
<>
<Btn onPress={handleCheck} isDisabled={checking}>
{checking ? "检查中..." : "检查更新"}
</Btn>
<Btn></Btn>
</>
)}
{effectiveState === "hasUpdate" && (
<>
<span className="text-[12px] text-white/80 mr-1"></span>
<Btn onPress={install} isDisabled={downloading}>
{downloading ? "下载中..." : "下载更新"}
</Btn>
</>
)}
{effectiveState === "installed" && (
<>
<span className="text-[12px] text-white/80 mr-1"></span>
<Btn onPress={relaunchApp}></Btn>
</>
)}
</div>
)} )}
</>
{/* 设置页:整卡可点击跳转更新页,显示入口小字 */}
{clickable && (
<span className="inline-flex items-center gap-0.5 text-[11px] text-white/60 transition-colors group-hover:text-white">
<ChevronRight className="w-3 h-3" />
</span>
)} )}
</div> </div>
</div> </div>
+2 -1
View File
@@ -103,7 +103,8 @@ export function AboutSetting() {
<PageHeader title="关于" desc="查看版本信息、更新状态与项目相关链接" /> <PageHeader title="关于" desc="查看版本信息、更新状态与项目相关链接" />
<div className="space-y-6"> <div className="space-y-6">
<VersionCard /> {/* 设置页:整卡可点击跳转更新页,显示「查看更新」 */}
<VersionCard isSettingPage />
<div> <div>
<SectionTitle></SectionTitle> <SectionTitle></SectionTitle>
+2 -2
View File
@@ -56,8 +56,8 @@ export function HomeSetting({ onNavigate }: HomeSettingProps) {
<PageHeader title="主页" desc="版本信息与常用设置的快捷入口" /> <PageHeader title="主页" desc="版本信息与常用设置的快捷入口" />
<div className="space-y-6"> <div className="space-y-6">
{/* 与"关于"页使用相同的版本卡片 */} {/* 与"关于"页使用相同的版本卡片;设置页整卡可点击跳转更新页 */}
<VersionCard /> <VersionCard isSettingPage />
<div> <div>
<SectionTitle></SectionTitle> <SectionTitle></SectionTitle>
+2 -2
View File
@@ -50,7 +50,7 @@ function formatMB(bytes?: number): string {
/** /**
* 更新日志(独立页面,不走设置 layout): * 更新日志(独立页面,不走设置 layout):
* - 顶栏由路由切换为「返回 + 更新日志」(routeStore 的 titleInBar * - 顶栏由路由切换为「返回 + 更新日志」(routeStore 的 titleInBar
* - 顶部 VersionCard此页面不显示按钮更新操作由底部遮罩负责) * - 顶部 VersionCard按钮更新操作由页面底部遮罩负责)
* - 发布说明:默认当前版本;检测到可用更新后自动切到最新版本 * - 发布说明:默认当前版本;检测到可用更新后自动切到最新版本
* - 底部遮罩:检查更新 → 下载(进度条 + 暂停/继续/取消)→ 安装更新 * - 底部遮罩:检查更新 → 下载(进度条 + 暂停/继续/取消)→ 安装更新
* - 下载/安装进度由主进程写入 Koring.ymlupdate 段) * - 下载/安装进度由主进程写入 Koring.ymlupdate 段)
@@ -276,7 +276,7 @@ export function UpdatePage() {
variant="primary" variant="primary"
fullWidth fullWidth
style={BUTTON_STYLE} style={BUTTON_STYLE}
isDisabled={st === "checking" || st === "installing" || st === "not-available"} isDisabled={st === "checking" || st === "installing"}
onPress={primaryAction} onPress={primaryAction}
> >
{st === "checking" && ( {st === "checking" && (