feat: enhance platform management and synchronization in ArticleEditor and PublishArticle components

This commit is contained in:
2026-04-06 15:41:49 +08:00
parent fe124b0ba4
commit 08ace0a9e0
7 changed files with 209 additions and 88 deletions
@@ -9,11 +9,15 @@ import type {
PublisherPublishResponse,
PublisherPublishTaskResult,
} from "@geo/shared-types";
import { computed, h, ref, watch } from "vue";
import { computed, h, ref, watch, watchEffect } from "vue";
import { useI18n } from "vue-i18n";
import { articlesApi, getApiBaseURL, mediaApi } from "@/lib/api";
import { formatError } from "@/lib/errors";
import {
normalizePublishPlatformId,
normalizePublishPlatformIds,
} from "@/lib/publish-platforms";
import { publishWithPublisherPlugin } from "@/lib/publisher-plugin";
import { loadPublisherRuntimeState } from "@/lib/publisher-runtime";
@@ -39,6 +43,7 @@ const pluginVersion = ref<string | undefined>();
const pluginInstallationId = ref<number | null>(null);
const localPlatforms = ref<PublisherLocalPlatformState[]>([]);
const fileList = ref<any[]>([]);
const selectionHydrated = ref(false);
function handleBeforeUpload(file: File) {
const url = URL.createObjectURL(file);
@@ -84,27 +89,63 @@ watch(
fileList.value = [];
pluginInstallationId.value = null;
localPlatforms.value = [];
selectionHydrated.value = false;
return;
}
selectionHydrated.value = false;
await refreshRuntime();
},
{ immediate: true },
);
watchEffect(() => {
if (!props.open || selectionHydrated.value) {
return;
}
if (
detailQuery.isPending.value ||
accountsQuery.isPending.value ||
platformsQuery.isPending.value ||
runtimeLoading.value
) {
return;
}
const selectedPlatforms = new Set(normalizePublishPlatformIds(detailQuery.data.value?.platforms ?? []));
selectedAccountIds.value = accountCards.value
.filter((account) => account.accountId && account.selectable && selectedPlatforms.has(account.platformId))
.map((account) => account.accountId as number);
selectionHydrated.value = true;
});
const localPlatformMap = computed(() => {
return new Map(localPlatforms.value.map((item) => [item.platform_id, item]));
return new Map(localPlatforms.value.map((item) => [normalizePublishPlatformId(item.platform_id), item]));
});
const accountGroups = computed(() => {
const groups = new Map<string, PlatformAccount[]>();
for (const account of accountsQuery.data.value ?? []) {
const platformId = normalizePublishPlatformId(account.platform_id);
const list = groups.get(platformId) ?? [];
list.push(account);
groups.set(platformId, list);
}
return groups;
});
const platformNameMap = computed(() => {
return new Map((platformsQuery.data.value ?? []).map((platform) => [platform.platform_id, platform.name]));
return new Map(
(platformsQuery.data.value ?? []).map((platform) => [normalizePublishPlatformId(platform.platform_id), platform.name]),
);
});
const accountCards = computed(() => {
const accountMap = new Map((accountsQuery.data.value ?? []).map((account) => [account.platform_id, account]));
return (platformsQuery.data.value ?? []).map((platform) => {
const account = accountMap.get(platform.platform_id) ?? null;
const local = localPlatformMap.value.get(platform.platform_id);
const platformId = normalizePublishPlatformId(platform.platform_id);
const accounts = accountGroups.value.get(platformId) ?? [];
const account = accounts[0] ?? null;
const local = localPlatformMap.value.get(platformId);
const localConnected = Boolean(local?.connected);
const uidMatches = account
? localConnected && (!local?.platform_uid || local.platform_uid === account.platform_uid)
@@ -112,9 +153,9 @@ const accountCards = computed(() => {
const selectable = Boolean(account && account.status === "active" && uidMatches && pluginInstalled.value);
return {
key: account?.id ?? platform.platform_id,
key: account?.id ?? platformId,
accountId: account?.id ?? null,
platformId: platform.platform_id,
platformId,
platformName: platform.name,
platformShortName: platform.short_name,
platformAccentColor: platform.accent_color,