feat(article): expose auto_publish_platforms derived from publish accounts
Replace the freeform `platforms` field on articles/tasks (parsed out of wizard_state/input_params JSON) with `auto_publish_platforms`, resolved by joining schedule publish accounts to platform_accounts. The migration strips the legacy keys from existing rows so the new field is the single source of truth. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,7 +116,7 @@ const deleteMutation = useMutation({
|
||||
const columns = computed<TableColumnsType<ArticleListItem>>(() => [
|
||||
{ title: t("custom.article.titleColumn"), dataIndex: "title", key: "title", width: 340 },
|
||||
{ title: t("custom.filters.promptRule"), dataIndex: "prompt_rule_name", key: "prompt_rule_name", width: 160 },
|
||||
{ title: t("custom.schedule.platform"), dataIndex: "platforms", key: "platforms", width: 180 },
|
||||
{ title: t("custom.schedule.autoPublishPlatforms"), dataIndex: "auto_publish_platforms", key: "auto_publish_platforms", width: 180 },
|
||||
{ title: t("common.generateStatus"), dataIndex: "generate_status", key: "generate_status", width: 128 },
|
||||
{ title: t("common.publishStatus"), dataIndex: "publish_status", key: "publish_status", width: 128 },
|
||||
{ title: t("common.wordCount"), dataIndex: "word_count", key: "word_count", width: 100 },
|
||||
@@ -319,8 +319,8 @@ onBeforeUnmount(() => {
|
||||
<template v-else-if="column.key === 'prompt_rule_name'">
|
||||
{{ record.prompt_rule_name || "--" }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'platforms'">
|
||||
{{ formatPublishPlatformList(record.platforms) }}
|
||||
<template v-else-if="column.key === 'auto_publish_platforms'">
|
||||
{{ formatPublishPlatformList(record.auto_publish_platforms) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'generate_status'">
|
||||
<ArticleGenerateStatus :status="record.generate_status" />
|
||||
|
||||
@@ -80,7 +80,7 @@ const columns = computed<TableColumnsType<InstantTaskItem>>(() => [
|
||||
{ title: t("custom.schedule.rule"), dataIndex: "prompt_rule_name", key: "prompt_rule_name", width: 180 },
|
||||
{ title: t("custom.instant.executionStatus"), dataIndex: "status", key: "status", width: 140 },
|
||||
{ title: t("custom.instant.executionTime"), dataIndex: "execution_time", key: "execution_time", width: 170 },
|
||||
{ title: t("custom.schedule.platform"), dataIndex: "platforms", key: "platforms", width: 220 },
|
||||
{ title: t("custom.schedule.autoPublishPlatforms"), dataIndex: "auto_publish_platforms", key: "auto_publish_platforms", width: 220 },
|
||||
{ title: t("custom.task.generateCount"), dataIndex: "generate_count", key: "generate_count", width: 120 },
|
||||
{ title: t("custom.instant.createdTime"), dataIndex: "created_at", key: "created_at", width: 170 },
|
||||
{ title: t("common.actions"), key: "actions", width: 88, fixed: "right", align: "right" },
|
||||
@@ -235,8 +235,8 @@ onBeforeUnmount(() => {
|
||||
<template v-else-if="column.key === 'execution_time'">
|
||||
{{ formatDateTime(record.execution_time) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'platforms'">
|
||||
{{ formatPublishPlatformList(record.platforms) }}
|
||||
<template v-else-if="column.key === 'auto_publish_platforms'">
|
||||
{{ formatPublishPlatformList(record.auto_publish_platforms) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'generate_count'">
|
||||
{{ record.generate_count || 1 }}
|
||||
|
||||
@@ -21,9 +21,6 @@ import {
|
||||
publishStateLabel,
|
||||
type PublishAccountCard,
|
||||
} from "@/lib/publish-account-cards";
|
||||
import {
|
||||
normalizePublishPlatformIds,
|
||||
} from "@/lib/publish-platforms";
|
||||
|
||||
const props = defineProps<{
|
||||
open: boolean;
|
||||
@@ -93,10 +90,8 @@ watch(
|
||||
|
||||
const platformMap = computed(() => buildPublishPlatformMap(platformsQuery.data.value ?? []));
|
||||
|
||||
const articlePlatformIds = computed(() => normalizePublishPlatformIds(detailQuery.data.value?.platforms ?? []));
|
||||
|
||||
const accountCards = computed<PublishAccountCard[]>(() =>
|
||||
buildPublishAccountCards(accountsQuery.data.value ?? [], platformMap.value, articlePlatformIds.value),
|
||||
buildPublishAccountCards(accountsQuery.data.value ?? [], platformMap.value),
|
||||
);
|
||||
|
||||
watch(
|
||||
@@ -137,10 +132,7 @@ watchEffect(() => {
|
||||
return;
|
||||
}
|
||||
|
||||
const preferredPlatforms = new Set(articlePlatformIds.value);
|
||||
selectedAccountIds.value = accountCards.value
|
||||
.filter((card) => card.selectable && preferredPlatforms.has(card.platformId))
|
||||
.map((card) => card.id);
|
||||
selectedAccountIds.value = [];
|
||||
selectionHydrated.value = true;
|
||||
});
|
||||
|
||||
@@ -237,7 +229,6 @@ async function persistCoverIfNeeded(detail: ArticleDetail): Promise<ArticleDetai
|
||||
return articlesApi.update(detail.id, {
|
||||
title: detail.title?.trim() || t("article.untitled"),
|
||||
markdown_content: detail.markdown_content ?? "",
|
||||
platforms: normalizePublishPlatformIds(detail.platforms ?? []),
|
||||
cover_asset_url: nextUrl || null,
|
||||
cover_image_asset_id: coverImageAssetId.value,
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ import ScheduleTaskModal from "@/components/ScheduleTaskModal.vue";
|
||||
import { promptRulesApi, schedulesApi } from "@/lib/api";
|
||||
import { formatCronExecutionTime, formatDateTime } from "@/lib/display";
|
||||
import { formatError } from "@/lib/errors";
|
||||
import { formatPublishPlatformList } from "@/lib/publish-platforms";
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useI18n();
|
||||
@@ -84,7 +85,7 @@ const columns = computed<TableColumnsType<ScheduleTask>>(() => [
|
||||
{ title: t("custom.schedule.rule"), dataIndex: "prompt_rule_name", key: "prompt_rule_name", width: 180 },
|
||||
{ title: t("custom.instant.executionStatus"), dataIndex: "status", key: "status", width: 140 },
|
||||
{ title: t("custom.instant.executionTime"), dataIndex: "cron_expr", key: "cron_expr", width: 170 },
|
||||
{ title: t("custom.schedule.autoPublish"), dataIndex: "auto_publish", key: "auto_publish", width: 160 },
|
||||
{ title: t("custom.schedule.autoPublishPlatforms"), dataIndex: "auto_publish_platforms", key: "auto_publish_platforms", width: 200 },
|
||||
{ title: t("custom.task.generateCount"), dataIndex: "generate_count", key: "generate_count", width: 120 },
|
||||
{ title: t("custom.instant.createdTime"), dataIndex: "created_at", key: "created_at", width: 170 },
|
||||
{ title: t("common.actions"), key: "actions", width: 140, fixed: "right", align: "right" },
|
||||
@@ -222,11 +223,11 @@ function handleTableChange(nextPage: number, nextPageSize: number): void {
|
||||
<template v-else-if="column.key === 'cron_expr'">
|
||||
{{ formatCronExecutionTime(record.cron_expr) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'auto_publish'">
|
||||
<template v-else-if="column.key === 'auto_publish_platforms'">
|
||||
<a-tag :color="record.auto_publish ? 'blue' : 'default'">
|
||||
{{
|
||||
record.auto_publish
|
||||
? t("custom.schedule.autoPublishAccountCount", { count: record.publish_account_ids?.length ?? 0 })
|
||||
? formatPublishPlatformList(record.auto_publish_platforms)
|
||||
: t("custom.schedule.manualPublish")
|
||||
}}
|
||||
</a-tag>
|
||||
|
||||
@@ -1290,9 +1290,9 @@ const enUS = {
|
||||
name: "Task name",
|
||||
rule: "Prompt rule",
|
||||
cron: "Frequency",
|
||||
autoPublishPlatforms: "Auto publish platforms",
|
||||
autoPublish: "Auto publish",
|
||||
manualPublish: "Manual publish",
|
||||
autoPublishAccountCount: "Auto · {count} accounts",
|
||||
nextRun: "Next run",
|
||||
startAt: "Start time",
|
||||
endAt: "End time",
|
||||
|
||||
@@ -1300,9 +1300,9 @@ const zhCN = {
|
||||
name: "任务名称",
|
||||
rule: "关联规则",
|
||||
cron: "执行频率",
|
||||
autoPublishPlatforms: "自动发布平台",
|
||||
autoPublish: "自动发布",
|
||||
manualPublish: "手动发布",
|
||||
autoPublishAccountCount: "自动 · {count} 个账号",
|
||||
nextRun: "下次执行",
|
||||
startAt: "开始时间",
|
||||
endAt: "结束时间",
|
||||
|
||||
@@ -161,7 +161,7 @@ const recentTemplateArticles = computed<ArticleListItem[]>(() =>
|
||||
prompt_rule_id: null,
|
||||
prompt_rule_name: null,
|
||||
generation_mode: article.generation_mode,
|
||||
platforms: [],
|
||||
auto_publish_platforms: [],
|
||||
generate_status: article.generate_status,
|
||||
publish_status: article.publish_status,
|
||||
title: article.title,
|
||||
|
||||
Reference in New Issue
Block a user