继续更新 update 门户站点界面和功能
build-winui / winui (push) Has been cancelled

This commit is contained in:
QWQLwToo
2026-06-26 20:17:34 +08:00
parent f525e5f3ba
commit 2513eb2903
68 changed files with 5586 additions and 3195 deletions
@@ -6,12 +6,39 @@ const sources = ref<any>(null);
const notices = ref<any[]>([]);
const loading = ref(false);
const error = ref("");
const loadedAt = ref("");
const requestState = ref<Record<string, "idle" | "loading" | "ready" | "error">>({
bootstrap: "idle",
releases: "idle",
sources: "idle",
notices: "idle",
});
let loaded = false;
const endpointLabels: Record<string, string> = {
"/api/client/bootstrap": "客户端启动配置",
"/api/client/releases": "发布信息",
"/api/client/sources": "接口源目录",
"/api/client/notices": "版本日志",
};
async function fetchJSON(path: string) {
const res = await fetch(path);
if (!res.ok) throw new Error(`${path} returned HTTP ${res.status}`);
return res.json();
let res: Response;
try {
res = await fetch(path, { headers: { Accept: "application/json" } });
} catch {
throw new Error(`${endpointLabels[path] || path} 暂时无法连接`);
}
if (!res.ok) throw new Error(`${endpointLabels[path] || path} 返回 HTTP ${res.status}`);
try {
return await res.json();
} catch {
throw new Error(`${endpointLabels[path] || path} 返回内容不是有效 JSON`);
}
}
function failureMessage(reason: unknown) {
return reason instanceof Error ? reason.message : String(reason || "读取失败");
}
export function usePortalState() {
@@ -26,11 +53,16 @@ export function usePortalState() {
const downloadUrl = computed(() => releases.value?.download_url || bootstrap.value?.release?.download_url || packages.value[0]?.url || "");
const appVersion = computed(() => releases.value?.app_version || bootstrap.value?.release?.app_version || latestNotice.value?.version || "未发布");
const serviceVersion = computed(() => bootstrap.value?.serviceVersion || "-");
const isReady = computed(() => loaded && !loading.value && !error.value);
const hasPartialData = computed(() => Boolean(bootstrap.value || releases.value || sources.value || notices.value.length));
const releasesEmpty = computed(() => !loading.value && packages.value.length === 0 && notices.value.length === 0);
const sourcesEmpty = computed(() => !loading.value && categories.value.length === 0);
async function load(force = false) {
if (loaded && !force) return;
loading.value = true;
error.value = "";
requestState.value = { bootstrap: "loading", releases: "loading", sources: "loading", notices: "loading" };
try {
const [bootstrapData, releaseData, sourceData, noticeData] = await Promise.allSettled([
fetchJSON("/api/client/bootstrap"),
@@ -38,15 +70,36 @@ export function usePortalState() {
fetchJSON("/api/client/sources"),
fetchJSON("/api/client/notices"),
]);
if (bootstrapData.status === "fulfilled") bootstrap.value = bootstrapData.value;
if (releaseData.status === "fulfilled") releases.value = releaseData.value;
if (sourceData.status === "fulfilled") sources.value = sourceData.value;
if (noticeData.status === "fulfilled") notices.value = noticeData.value.items || [];
if (bootstrapData.status === "fulfilled") {
bootstrap.value = bootstrapData.value;
requestState.value.bootstrap = "ready";
} else {
requestState.value.bootstrap = "error";
}
if (releaseData.status === "fulfilled") {
releases.value = releaseData.value;
requestState.value.releases = "ready";
} else {
requestState.value.releases = "error";
}
if (sourceData.status === "fulfilled") {
sources.value = sourceData.value;
requestState.value.sources = "ready";
} else {
requestState.value.sources = "error";
}
if (noticeData.status === "fulfilled") {
notices.value = noticeData.value.items || [];
requestState.value.notices = "ready";
} else {
requestState.value.notices = "error";
}
const firstFailure = [bootstrapData, releaseData, sourceData, noticeData].find((item) => item.status === "rejected") as PromiseRejectedResult | undefined;
if (firstFailure && !bootstrap.value) error.value = firstFailure.reason?.message || String(firstFailure.reason);
if (firstFailure && !hasPartialData.value) error.value = failureMessage(firstFailure.reason);
loaded = true;
loadedAt.value = new Date().toISOString();
} catch (err) {
error.value = err instanceof Error ? err.message : String(err);
error.value = failureMessage(err);
} finally {
loading.value = false;
}
@@ -59,6 +112,8 @@ export function usePortalState() {
notices,
loading,
error,
loadedAt,
requestState,
packages,
categories,
latestNotice,
@@ -68,6 +123,10 @@ export function usePortalState() {
downloadUrl,
appVersion,
serviceVersion,
isReady,
hasPartialData,
releasesEmpty,
sourcesEmpty,
load,
sourceStatus,
statusTone,