mirror of
https://github.com/dream-pep/koring-launcher.git
synced 2026-09-12 05:45:18 +08:00
feat: 新增版本更新日志页面并调整初始化引导流程
- 新增 AboutVersion 组件,支持拉取 GitHub Release 日志并按提交类型分类展示 - 为 OOBE 和 UPvP 流程新增 about-version 页面,调整原版本页的跳转逻辑,先展示更新日志再进入后续步骤 - 注册新的路由配置,更新 README 与 DEV.md 文档说明新功能
This commit is contained in:
@@ -32,12 +32,14 @@ import { OobeAgreement } from "./pages/oobe/step-agreement";
|
||||
import { OobeLogin } from "./pages/oobe/step-login";
|
||||
import { OobeWelcome } from "./pages/oobe/step-welcome";
|
||||
import { OobeVersion } from "./pages/oobe/step-version";
|
||||
import { OobeAboutVersion } from "./pages/oobe/about-version";
|
||||
import { OobeBetaTest } from "./pages/oobe/step-beta-test";
|
||||
import { OobeFinish } from "./pages/oobe/step-finish";
|
||||
import { OobeLegal } from "./pages/oobe/step-legal";
|
||||
import { OobeAboutInfo } from "./pages/oobe/about-info";
|
||||
import { UpvpComplete } from "./pages/upvp/step-complete";
|
||||
import { UpvpVersion } from "./pages/upvp/step-version";
|
||||
import { UpvpAboutVersion } from "./pages/upvp/about-version";
|
||||
import { UpvpCheck } from "./pages/upvp/step-check";
|
||||
import { UpvpBetaTest } from "./pages/upvp/step-beta-test";
|
||||
import { UpvpFinish } from "./pages/upvp/step-finish";
|
||||
@@ -59,6 +61,7 @@ const pageMap = {
|
||||
"oobe/login": OobeLogin,
|
||||
"oobe/welcome": OobeWelcome,
|
||||
"oobe/version": OobeVersion,
|
||||
"oobe/about-version": OobeAboutVersion,
|
||||
"oobe/beta-test": OobeBetaTest,
|
||||
"oobe/finish": OobeFinish,
|
||||
"oobe/about-info": OobeAboutInfo,
|
||||
@@ -66,6 +69,7 @@ const pageMap = {
|
||||
upvp: UpvpComplete,
|
||||
"upvp/complete": UpvpComplete,
|
||||
"upvp/version": UpvpVersion,
|
||||
"upvp/about-version": UpvpAboutVersion,
|
||||
"upvp/check": UpvpCheck,
|
||||
"upvp/beta-test": UpvpBetaTest,
|
||||
"upvp/finish": UpvpFinish,
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// AboutVersion:展示当前版本的更新内容。
|
||||
// 数据源:getReleaseNotes()(GitHub release-notes.md,主进程自动切加速源,回退最新版)。
|
||||
// 不直接渲染 Markdown —— 解析后按提交类型(新增/修复/优化/重构/文档/其他)分组,
|
||||
// 每组配图标,用卡片展示。
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Sparkles, Bug, Gauge, RefreshCw, FileText, Wrench, ExternalLink, GitCommitHorizontal } from "lucide-react";
|
||||
import { getReleaseNotes, type ReleaseNotesResult } from "@/api/update";
|
||||
import { VERSION } from "@/lib/version";
|
||||
import { parseReleaseNotes, type ChangeType, type VersionChange } from "./parse";
|
||||
|
||||
const GITHUB_RELEASES = "https://github.com/dream-pep/koring-launcher/releases";
|
||||
|
||||
const CATEGORY_ORDER: ChangeType[] = ["feat", "fix", "perf", "refactor", "docs", "other"];
|
||||
|
||||
const CATEGORY_META: Record<ChangeType, { label: string; icon: React.ComponentType<{ className?: string }>; iconCls: string; dotCls: string }> = {
|
||||
feat: { label: "新增功能", icon: Sparkles, iconCls: "text-sky-600 dark:text-sky-400 bg-sky-500/10", dotCls: "bg-sky-500" },
|
||||
fix: { label: "修复", icon: Bug, iconCls: "text-red-600 dark:text-red-400 bg-red-500/10", dotCls: "bg-red-500" },
|
||||
perf: { label: "性能优化", icon: Gauge, iconCls: "text-emerald-600 dark:text-emerald-400 bg-emerald-500/10", dotCls: "bg-emerald-500" },
|
||||
refactor: { label: "重构", icon: RefreshCw, iconCls: "text-violet-600 dark:text-violet-400 bg-violet-500/10", dotCls: "bg-violet-500" },
|
||||
docs: { label: "文档", icon: FileText, iconCls: "text-amber-600 dark:text-amber-400 bg-amber-500/10", dotCls: "bg-amber-500" },
|
||||
other: { label: "其他", icon: Wrench, iconCls: "text-foreground/60 bg-foreground/[0.06]", dotCls: "bg-foreground/40" },
|
||||
};
|
||||
|
||||
/** 一条变更(含 commit 标)+ 短分隔条 */
|
||||
function ChangeItem({ change }: { change: VersionChange }) {
|
||||
return (
|
||||
<div className="flex items-start gap-2.5 px-4 py-2.5 first:pt-3 last:pb-3">
|
||||
{change.commit && (
|
||||
<span className="inline-flex items-center gap-1 shrink-0 mt-[3px] font-mono text-[10px] px-1.5 py-0.5 rounded bg-foreground/[0.05] dark:bg-white/[0.05] text-muted-foreground/80">
|
||||
<GitCommitHorizontal className="w-3 h-3" />
|
||||
{change.commit}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-[13px] font-medium text-foreground leading-snug">{change.title}</p>
|
||||
{change.description && (
|
||||
<p className="text-[12px] text-muted-foreground/80 leading-relaxed mt-0.5">{change.description}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** 一个分类卡片:图标头部 + 该类型的变更列表 */
|
||||
function CategoryCard({ type, items }: { type: ChangeType; items: VersionChange[] }) {
|
||||
const meta = CATEGORY_META[type];
|
||||
const Icon = meta.icon;
|
||||
return (
|
||||
<div className="rounded-xl overflow-hidden border border-black/[0.06] dark:border-white/[0.07] bg-white/85 dark:bg-black/45 backdrop-blur-[12px]">
|
||||
<div className="flex items-center gap-2 px-4 py-2.5 border-b border-black/[0.05] dark:border-white/[0.06]">
|
||||
<span className={`flex items-center justify-center w-6 h-6 rounded-md ${meta.iconCls}`}>
|
||||
<Icon className="w-3.5 h-3.5" />
|
||||
</span>
|
||||
<span className="text-[13px] font-semibold text-foreground">{meta.label}</span>
|
||||
<span className="text-[11px] text-muted-foreground/60 ml-auto tabular-nums">{items.length} 项</span>
|
||||
</div>
|
||||
<div className="divide-y divide-black/[0.04] dark:divide-white/[0.05]">
|
||||
{items.map((c, i) => (
|
||||
<ChangeItem key={`${c.commit ?? ""}-${i}`} change={c} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EmptyCard({ text }: { text: string }) {
|
||||
return (
|
||||
<div className="rounded-xl border border-black/[0.06] dark:border-white/[0.07] bg-white/85 dark:bg-black/45 backdrop-blur-[12px] px-5 py-10 text-center">
|
||||
<p className="text-[13px] text-muted-foreground">{text}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function AboutVersion({ className }: { className?: string }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [result, setResult] = useState<ReleaseNotesResult | null>(null);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const r = await getReleaseNotes();
|
||||
setResult(r);
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : String(e));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
}, [load]);
|
||||
|
||||
const parsed = result ? parseReleaseNotes(result.notes, result.version, result.tag) : null;
|
||||
|
||||
const grouped = parsed
|
||||
? CATEGORY_ORDER.map((t) => ({ type: t, items: parsed.changes.filter((c) => c.type === t) })).filter(
|
||||
(g) => g.items.length > 0,
|
||||
)
|
||||
: [];
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{/* 头部:版本 + 来源 */}
|
||||
<div className="flex items-center justify-between mb-2 px-1">
|
||||
<span className="text-[12px] text-muted-foreground/80">
|
||||
{parsed ? (
|
||||
<>
|
||||
版本 v{parsed.version}
|
||||
{result?.isLatest && parsed.version !== VERSION && (
|
||||
<span className="ml-2 opacity-70">(当前版本暂无说明,展示最新版本内容)</span>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>版本 v{VERSION}</>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="space-y-2">
|
||||
{[0, 1, 2].map((i) => (
|
||||
<div key={i} className="h-[76px] rounded-xl bg-white/50 dark:bg-white/[0.04] animate-pulse" />
|
||||
))}
|
||||
</div>
|
||||
) : error ? (
|
||||
<EmptyCard text="获取此版本的更新内容失败" />
|
||||
) : !result || !parsed ? (
|
||||
<EmptyCard text="未能获取到发布说明(GitHub 与加速源均不可用,或该版本尚未发布)" />
|
||||
) : (
|
||||
<div className="space-y-2.5">
|
||||
{parsed.noCommits && parsed.changes.length === 0 ? (
|
||||
<EmptyCard text="此版本暂无变更记录" />
|
||||
) : grouped.length === 0 ? (
|
||||
<EmptyCard text="此版本暂无变更记录" />
|
||||
) : (
|
||||
grouped.map((g) => <CategoryCard key={g.type} type={g.type} items={g.items} />)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 底部操作 */}
|
||||
<div className="flex items-center gap-2 mt-3 px-1">
|
||||
{error && (
|
||||
<>
|
||||
<p className="text-[11px] text-destructive/80 flex-1 truncate">{error}</p>
|
||||
<button
|
||||
onClick={load}
|
||||
className="text-[12px] font-medium text-primary hover:underline shrink-0"
|
||||
>
|
||||
重试
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
onClick={() => window.electronAPI?.openExternal(GITHUB_RELEASES)}
|
||||
className="inline-flex items-center gap-0.5 text-[12px] text-muted-foreground hover:text-foreground transition-colors ml-auto shrink-0"
|
||||
>
|
||||
查看 GitHub Releases
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// 版本发布说明(release-notes.md / GitHub Release body)解析器。
|
||||
// 目标:不渲染原始 Markdown,把每条变更提取出来并按提交类型(conventional commit)分类。
|
||||
//
|
||||
// 受控格式约定(与 CI release 模板对齐):
|
||||
// # Koring Launcher Releases x
|
||||
// ## 版本信息
|
||||
// 当前版本 x
|
||||
// ...
|
||||
// ## 更新了什么内容
|
||||
// <details>
|
||||
// <summary>·Commit abc1234</summary>
|
||||
//
|
||||
// fix(updater): 标题
|
||||
//
|
||||
// 详细说明…
|
||||
// </details>
|
||||
// 或:· 无提交记录
|
||||
|
||||
export type ChangeType = "feat" | "fix" | "perf" | "refactor" | "docs" | "other";
|
||||
|
||||
export interface VersionChange {
|
||||
/** commit 短 hash(无则省略) */
|
||||
commit?: string;
|
||||
type: ChangeType;
|
||||
/** 去除 type(scope): 前缀后的标题 */
|
||||
title: string;
|
||||
/** 详细说明(纯文本,已剥离 md 记号) */
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface ParsedRelease {
|
||||
version: string;
|
||||
tag: string;
|
||||
/** notes 中含「无提交记录」 */
|
||||
noCommits: boolean;
|
||||
changes: VersionChange[];
|
||||
}
|
||||
|
||||
/** conventional commit type → 业务分类(大小写不敏感) */
|
||||
const TYPE_ALIAS: Record<string, ChangeType> = {
|
||||
feat: "feat",
|
||||
feature: "feat",
|
||||
add: "feat",
|
||||
fix: "fix",
|
||||
bugfix: "fix",
|
||||
perf: "perf",
|
||||
optimize: "perf",
|
||||
performance: "perf",
|
||||
improve: "perf",
|
||||
refactor: "refactor",
|
||||
docs: "docs",
|
||||
doc: "docs",
|
||||
chore: "other",
|
||||
ci: "other",
|
||||
build: "other",
|
||||
style: "other",
|
||||
test: "other",
|
||||
revert: "other",
|
||||
};
|
||||
|
||||
/** 去掉行内的常见 markdown 记号,得到纯文本 */
|
||||
function stripInlineMarkdown(text: string): string {
|
||||
return text
|
||||
.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1") // 链接 [t](url) → t
|
||||
.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1") // 图片  → t
|
||||
.replace(/\*\*([^*]+)\*\*/g, "$1")
|
||||
.replace(/\*([^*]+)\*/g, "$1")
|
||||
.replace(/`([^`]+)`/g, "$1")
|
||||
.replace(/__([^_]+)__/g, "$1")
|
||||
.replace(/[_~]+/g, "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
/** 解析 conventional commit 首行:type(scope): subject */
|
||||
function parseCommitTitle(line: string): { type: ChangeType; title: string } {
|
||||
const m = line.trim().match(/^([a-zA-Z][\w-]*)(?:\(([^)]*)\))?!?:\s*(.*)$/);
|
||||
if (!m) {
|
||||
return { type: "other", title: stripInlineMarkdown(line) };
|
||||
}
|
||||
const rawType = m[1].toLowerCase();
|
||||
const subject = stripInlineMarkdown(m[3] || m[2] || line);
|
||||
return { type: TYPE_ALIAS[rawType] ?? "other", title: subject };
|
||||
}
|
||||
|
||||
/** 提取一个 <details> 块中的 summary sha 与正文 */
|
||||
function splitDetailsBlock(block: string): { commit?: string; content: string } {
|
||||
const summary = block.match(/<summary>\s*[·•-]?\s*Commit\s*([0-9a-fA-F]{4,40})?/i);
|
||||
const content = block
|
||||
.replace(/<summary>[\s\S]*?<\/summary>/i, "")
|
||||
.replace(/<\/?details>/gi, "")
|
||||
.trim();
|
||||
return { commit: summary?.[1]?.slice(0, 7), content };
|
||||
}
|
||||
|
||||
/** 把一段文本按行解析为一条变更 */
|
||||
function parseChangeLines(text: string): VersionChange {
|
||||
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
|
||||
const head = lines[0] || "";
|
||||
const { type, title } = parseCommitTitle(head);
|
||||
const rest = lines.slice(1);
|
||||
// 剩余行通常为换行后的说明;合并(保留相对短行),剥离剩余 md 记号
|
||||
const description = rest.length > 0 ? stripInlineMarkdown(rest.join(" ")) : undefined;
|
||||
return { type, title, description: description || undefined };
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析发布说明 notes 为结构化变更列表。
|
||||
* 优先切分 <details> 块(受控格式);无 details 时按「更新了什么内容」节下的行兜底。
|
||||
*/
|
||||
export function parseReleaseNotes(notes: string, version: string, tag: string): ParsedRelease {
|
||||
const noCommits = /无提交记录|no commits?/i.test(notes);
|
||||
|
||||
// 定位「更新了什么内容」节(找不到则用整篇)
|
||||
const sectionIdx = notes.search(/^##\s*更新了什么内容/m);
|
||||
const body = sectionIdx >= 0 ? notes.slice(sectionIdx) : notes;
|
||||
|
||||
const changes: VersionChange[] = [];
|
||||
|
||||
// 1) <details> 块切分(受控格式)
|
||||
const detailRe = /<details[^>]*>([\s\S]*?)<\/details>/gi;
|
||||
let match: RegExpExecArray | null;
|
||||
let detailsFound = false;
|
||||
while ((match = detailRe.exec(body)) !== null) {
|
||||
detailsFound = true;
|
||||
const { commit, content } = splitDetailsBlock(match[1]);
|
||||
if (!content) continue;
|
||||
const change = parseChangeLines(content);
|
||||
if (commit) change.commit = commit;
|
||||
changes.push(change);
|
||||
}
|
||||
|
||||
// 2) 兜底:无 <details> 时按行扫描「· Commit / - 」开头的条目
|
||||
if (!detailsFound) {
|
||||
const lines = body
|
||||
.split("\n")
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => l && !/^#/.test(l));
|
||||
let current: VersionChange | null = null;
|
||||
for (const line of lines) {
|
||||
const entry = line.match(/^[·•\-]\s*(?:Commit\s*)?([0-9a-fA-F]{7,40})?\s*(.*)$/i);
|
||||
if (entry) {
|
||||
const { type, title } = parseCommitTitle(entry[2] || entry[1] || line);
|
||||
current = { type, title };
|
||||
if (entry[1]) current.commit = entry[1].slice(0, 7);
|
||||
changes.push(current);
|
||||
} else if (current) {
|
||||
// 说明行并入上一条
|
||||
const desc = stripInlineMarkdown(line);
|
||||
if (desc) current.description = current.description ? `${current.description} ${desc}` : desc;
|
||||
} else {
|
||||
// 游离正文行(版本信息等)跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { version, tag, noCommits, changes };
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useRouteStore } from "@/stores/routeStore";
|
||||
import { BUILD_MODE } from "@/lib/mode";
|
||||
import { VERSION } from "@/lib/version";
|
||||
import { OobeLayout } from "./layout";
|
||||
import { NextButton } from "./next-button";
|
||||
import { AboutVersion } from "@/components/about-version";
|
||||
|
||||
/** 版本卡片之后:关于此版本(展示当前版本更新内容,引用 AboutVersion 组件) */
|
||||
export function OobeAboutVersion() {
|
||||
const navigate = useRouteStore((s) => s.navigate);
|
||||
|
||||
const isTestBuild = BUILD_MODE === "dev" || BUILD_MODE === "beta";
|
||||
// 与原本 step-version 的分流一致:测试版需先同意 Beta 测试协议
|
||||
const nextRoute = isTestBuild ? "oobe/beta-test" : "oobe/finish";
|
||||
|
||||
return (
|
||||
<OobeLayout>
|
||||
<div className="w-full max-w-lg flex flex-col items-center px-6">
|
||||
<h2 className="text-lg font-bold text-foreground mb-0.5">关于此版本</h2>
|
||||
<p className="text-[12px] text-muted-foreground mb-4">当前版本 v{VERSION} 的更新内容</p>
|
||||
|
||||
{/* 内容滚动区:限高避免遮挡底部下一步按钮 */}
|
||||
<div className="w-full max-h-[58vh] overflow-y-auto scroll-area pr-1 -mr-1 min-h-[140px]">
|
||||
<AboutVersion />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NextButton onClick={() => navigate(nextRoute)} />
|
||||
</OobeLayout>
|
||||
);
|
||||
}
|
||||
@@ -10,9 +10,9 @@ export function OobeVersion() {
|
||||
const isTestBuild = BUILD_MODE === "dev" || BUILD_MODE === "beta";
|
||||
|
||||
// 到达本页前已依次经过 协议(agreement) → 法律(legal) → 欢迎(welcome),
|
||||
// 因此正式版下一步直接结束;测试版需先同意 Beta 测试协议。
|
||||
// 先进入「关于此版本」查看当前版本更新内容,再按构建类型结束或进入 Beta 测试协议。
|
||||
// (不要跳回 agreement——那会形成 agreement → legal → welcome → version → agreement 死循环)
|
||||
const nextRoute = isTestBuild ? "oobe/beta-test" : "oobe/finish";
|
||||
const nextRoute = "oobe/about-version";
|
||||
|
||||
return (
|
||||
<OobeLayout>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useRouteStore } from "@/stores/routeStore";
|
||||
import { VERSION } from "@/lib/version";
|
||||
import { UpvpLayout } from "./layout";
|
||||
import { NextButton } from "./next-button";
|
||||
import { AboutVersion } from "@/components/about-version";
|
||||
|
||||
/** 版本卡片之后:关于此版本(展示当前版本更新内容,引用 AboutVersion 组件) */
|
||||
export function UpvpAboutVersion() {
|
||||
const navigate = useRouteStore((s) => s.navigate);
|
||||
|
||||
return (
|
||||
<UpvpLayout>
|
||||
<div className="w-full max-w-lg flex flex-col items-center px-6">
|
||||
<h2 className="text-lg font-bold text-foreground mb-0.5">关于此版本</h2>
|
||||
<p className="text-[12px] text-muted-foreground mb-4">当前版本 v{VERSION} 的更新内容</p>
|
||||
|
||||
{/* 内容滚动区:限高避免遮挡底部下一步按钮 */}
|
||||
<div className="w-full max-h-[58vh] overflow-y-auto scroll-area pr-1 -mr-1 min-h-[140px]">
|
||||
<AboutVersion />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NextButton onClick={() => navigate("upvp/check")} />
|
||||
</UpvpLayout>
|
||||
);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export function UpvpVersion() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<NextButton onClick={() => navigate("upvp/check")} />
|
||||
<NextButton onClick={() => navigate("upvp/about-version")} />
|
||||
</UpvpLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export type RouteKey =
|
||||
| "oobe/language"
|
||||
| "oobe/agreement"
|
||||
| "oobe/version"
|
||||
| "oobe/about-version"
|
||||
| "oobe/beta-test"
|
||||
| "oobe/login"
|
||||
| "oobe/welcome"
|
||||
@@ -23,6 +24,7 @@ export type RouteKey =
|
||||
| "upvp"
|
||||
| "upvp/complete"
|
||||
| "upvp/version"
|
||||
| "upvp/about-version"
|
||||
| "upvp/check"
|
||||
| "upvp/beta-test"
|
||||
| "upvp/finish"
|
||||
@@ -65,6 +67,7 @@ export const allRoutes: RouteItem[] = [
|
||||
{ key: "oobe/language", label: "语言设置", path: "/oobe/language", hidden: true },
|
||||
{ key: "oobe/agreement", label: "同意协议", path: "/oobe/agreement", hidden: true },
|
||||
{ key: "oobe/version", label: "当前版本", path: "/oobe/version", hidden: true },
|
||||
{ key: "oobe/about-version", label: "关于此版本", path: "/oobe/about-version", hidden: true },
|
||||
{ key: "oobe/beta-test", label: "测试协议", path: "/oobe/beta-test", hidden: true },
|
||||
{ key: "oobe/login", label: "登录", path: "/oobe/login", hidden: true },
|
||||
{ key: "oobe/welcome", label: "欢迎", path: "/oobe/welcome", hidden: true },
|
||||
@@ -74,6 +77,7 @@ export const allRoutes: RouteItem[] = [
|
||||
{ key: "upvp", label: "更新引导", path: "/upvp", hidden: true },
|
||||
{ key: "upvp/complete", label: "更新已完成", path: "/upvp/complete", hidden: true },
|
||||
{ key: "upvp/version", label: "当前版本", path: "/upvp/version", hidden: true },
|
||||
{ key: "upvp/about-version", label: "关于此版本", path: "/upvp/about-version", hidden: true },
|
||||
{ key: "upvp/check", label: "检查版本", path: "/upvp/check", hidden: true },
|
||||
{ key: "upvp/beta-test", label: "测试协议", path: "/upvp/beta-test", hidden: true },
|
||||
{ key: "upvp/finish", label: "完成", path: "/upvp/finish", hidden: true },
|
||||
|
||||
Reference in New Issue
Block a user