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
+35 -10
View File
@@ -10,9 +10,12 @@ import { MilkdownProvider } from "@milkdown/vue";
import ArticleEditorCanvas from "@/components/ArticleEditorCanvas.vue";
import PublishArticleModal from "@/components/PublishArticleModal.vue";
import PublishPlatformSelector from "@/components/PublishPlatformSelector.vue";
import { articlesApi } from "@/lib/api";
import { articlesApi, mediaApi } from "@/lib/api";
import { formatError } from "@/lib/errors";
import { getBoundPublishPlatforms } from "@/lib/publish-platforms";
import {
buildPublishPlatformOptions,
normalizePublishPlatformIds,
} from "@/lib/publish-platforms";
const route = useRoute();
const router = useRouter();
@@ -24,7 +27,6 @@ const title = ref("");
const markdown = ref("");
const initialTitle = ref("");
const initialMarkdown = ref("");
const boundPublishPlatforms = getBoundPublishPlatforms();
const publishPlatforms = ref<string[]>([]);
const initialPublishPlatforms = ref<string[]>([]);
const coverEnabled = ref(true);
@@ -38,6 +40,24 @@ const detailQuery = useQuery({
queryFn: () => articlesApi.detail(articleId.value),
});
const platformsQuery = useQuery({
queryKey: ["media", "platforms", "article-editor"],
queryFn: () => mediaApi.platforms(),
});
const accountsQuery = useQuery({
queryKey: ["media", "platform-accounts", "article-editor"],
queryFn: () => mediaApi.accounts(),
});
const publishPlatformOptions = computed(() =>
buildPublishPlatformOptions(platformsQuery.data.value ?? [], accountsQuery.data.value),
);
const publishPlatformsLoading = computed(
() => platformsQuery.isPending.value || accountsQuery.isPending.value,
);
watch(
() => detailQuery.data.value,
(detail) => {
@@ -52,7 +72,7 @@ watch(
markdown.value = nextMarkdown;
initialTitle.value = nextTitle;
initialMarkdown.value = nextMarkdown;
publishPlatforms.value = [...(detail.platforms ?? [])];
publishPlatforms.value = normalizePublishPlatformIds(detail.platforms ?? []);
initialPublishPlatforms.value = [...publishPlatforms.value];
},
{ immediate: true },
@@ -72,7 +92,7 @@ const saveMutation = useMutation({
articlesApi.update(articleId.value, {
title: title.value.trim(),
markdown_content: markdown.value,
platforms: publishPlatforms.value,
platforms: normalizePublishPlatformIds(publishPlatforms.value),
}),
onSuccess: async (data) => {
message.success(t("article.editor.messages.saved"));
@@ -80,7 +100,7 @@ const saveMutation = useMutation({
markdown.value = data.markdown_content ?? "";
initialTitle.value = title.value;
initialMarkdown.value = markdown.value;
publishPlatforms.value = [...(data.platforms ?? [])];
publishPlatforms.value = normalizePublishPlatformIds(data.platforms ?? []);
initialPublishPlatforms.value = [...publishPlatforms.value];
await Promise.all([
queryClient.invalidateQueries({ queryKey: ["articles"] }),
@@ -232,9 +252,7 @@ function stripLeadingTitleHeading(titleValue: string, markdownValue: string): st
}
function serializePlatformSelection(platformIds: string[]): string {
return [...platformIds]
.map((platformId) => platformId.trim())
.filter(Boolean)
return normalizePublishPlatformIds(platformIds)
.sort()
.join(",");
}
@@ -287,10 +305,17 @@ function serializePlatformSelection(platformIds: string[]): string {
<section class="article-editor-view__card">
<h3>{{ t("article.editor.platformsTitle") }}</h3>
<p>{{ t("article.editor.platformsHint") }}</p>
<a-skeleton
v-if="publishPlatformsLoading"
active
:title="false"
:paragraph="{ rows: 4 }"
/>
<PublishPlatformSelector
v-else
v-model="publishPlatforms"
class="article-editor-view__platforms"
:platforms="boundPublishPlatforms"
:platforms="publishPlatformOptions"
:disabled="editorLocked"
/>
</section>