feat(schedule-tasks): support auto-publish via media accounts

Replace the legacy target_platform string on schedule tasks with a
workspace-aware auto-publish payload (auto_publish + publish_account_ids
JSONB + cover_asset_url + cover_image_asset_id) and migrate the schema,
sqlc queries, generated models, domain struct, ScheduleTaskService DTOs,
and dispatch worker to round-trip the new fields. PromptRuleGeneration
gains a WithPublishJobService hook so executeGeneration can enqueue an
auto-publish job once the article is ready, and worker-generate wires
the publish-job service in. On the admin-web side, extract
PublishArticleModal's account-card builders into a shared
publish-account-cards module, rebuild GenerateTaskDrawer's schedule
mode around account selection plus a CoverPickerModal, and surface the
new "auto publish" column on ScheduleTaskTab. Shared types and i18n
strings cover the new fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 01:32:19 +08:00
parent c9267d2fae
commit 6e6e19cccb
22 changed files with 1380 additions and 603 deletions
@@ -16,7 +16,6 @@ import ScheduleTaskModal from "@/components/ScheduleTaskModal.vue";
import { promptRulesApi, schedulesApi } from "@/lib/api";
import { formatCronExecutionTime, formatDateTime } from "@/lib/display";
import { formatError } from "@/lib/errors";
import { formatPublishPlatformSummary } from "@/lib/publish-platforms";
const queryClient = useQueryClient();
const { t } = useI18n();
@@ -85,7 +84,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.platform"), dataIndex: "target_platform", key: "target_platform", width: 220 },
{ title: t("custom.schedule.autoPublish"), dataIndex: "auto_publish", key: "auto_publish", width: 160 },
{ 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" },
@@ -223,8 +222,14 @@ 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 === 'target_platform'">
{{ formatPublishPlatformSummary(record.target_platform) }}
<template v-else-if="column.key === 'auto_publish'">
<a-tag :color="record.auto_publish ? 'blue' : 'default'">
{{
record.auto_publish
? t("custom.schedule.autoPublishAccountCount", { count: record.publish_account_ids?.length ?? 0 })
: t("custom.schedule.manualPublish")
}}
</a-tag>
</template>
<template v-else-if="column.key === 'generate_count'">
{{ record.generate_count || 1 }}