feat: scope articles by brand

This commit is contained in:
2026-05-20 15:37:25 +08:00
parent 5fb9d0b0dd
commit dd082e2ed1
72 changed files with 3213 additions and 432 deletions
@@ -22,6 +22,7 @@ import {
getSourceTypeLabel,
hasActiveGenerationStatus,
} from '@/lib/display'
import { useCompanyStore } from '@/stores/company'
const props = defineProps<{
open: boolean
@@ -34,6 +35,7 @@ const emit = defineEmits<{
const queryClient = useQueryClient()
const { t } = useI18n()
const companyStore = useCompanyStore()
const activeTab = ref('content')
const enabled = computed(() => props.open && Boolean(props.articleId))
const streamTitle = ref('')
@@ -42,20 +44,25 @@ const streamStatus = ref<string | null>(null)
const streamFeatureEnabled = isGenerationStreamEnabled()
const detailQuery = useQuery({
queryKey: computed(() => ['articles', 'detail', props.articleId]),
enabled,
queryKey: computed(() => ['articles', 'detail', companyStore.currentBrandId, props.articleId]),
enabled: computed(() => enabled.value && Boolean(companyStore.currentBrandId)),
queryFn: () => articlesApi.detail(props.articleId as number),
})
const versionsQuery = useQuery({
queryKey: computed(() => ['articles', 'versions', props.articleId]),
enabled,
queryKey: computed(() => ['articles', 'versions', companyStore.currentBrandId, props.articleId]),
enabled: computed(() => enabled.value && Boolean(companyStore.currentBrandId)),
queryFn: () => articlesApi.versions(props.articleId as number),
})
const publishRecordsQuery = useQuery({
queryKey: computed(() => ['articles', 'publish-records', props.articleId]),
enabled,
queryKey: computed(() => [
'articles',
'publish-records',
companyStore.currentBrandId,
props.articleId,
]),
enabled: computed(() => enabled.value && Boolean(companyStore.currentBrandId)),
queryFn: () => articlesApi.publishRecords(props.articleId as number),
})
@@ -8,6 +8,7 @@ import { useI18n } from 'vue-i18n'
import { articlesApi, mediaApi } from '@/lib/api'
import { getPublishStatusMeta } from '@/lib/display'
import { getPublishPlatformMeta, normalizePublishPlatformId } from '@/lib/publish-platforms'
import { useCompanyStore } from '@/stores/company'
interface PublishPlatformEntry {
key: string
@@ -42,6 +43,7 @@ const props = withDefaults(
)
const { t } = useI18n()
const companyStore = useCompanyStore()
const popoverOpen = ref(false)
const shouldLoadRecords = computed(() => Boolean(props.articleId) && props.status !== 'unpublished')
const shouldLoadPlatforms = computed(() => props.showPlatforms && shouldLoadRecords.value)
@@ -54,8 +56,13 @@ const platformsQuery = useQuery({
})
const publishRecordsQuery = useQuery({
queryKey: computed(() => ['articles', 'publish-records', props.articleId]),
enabled: shouldLoadRecords,
queryKey: computed(() => [
'articles',
'publish-records',
companyStore.currentBrandId,
props.articleId,
]),
enabled: computed(() => shouldLoadRecords.value && Boolean(companyStore.currentBrandId)),
queryFn: () => articlesApi.publishRecords(props.articleId as number),
staleTime: 30 * 1000,
})
@@ -19,10 +19,12 @@ import { useArticleRegenerateAction } from '@/lib/article-regenerate-action'
import { getGenerateStatusMeta, getPublishStatusMeta } from '@/lib/display'
import { formatError } from '@/lib/errors'
import { formatPublishPlatformList } from '@/lib/publish-platforms'
import { useCompanyStore } from '@/stores/company'
const queryClient = useQueryClient()
const router = useRouter()
const { t } = useI18n()
const companyStore = useCompanyStore()
const page = ref(1)
const pageSize = ref(20)
@@ -93,7 +95,14 @@ const articleParams = computed<ArticleListParams>(() => {
})
const listQuery = useQuery({
queryKey: computed(() => ['articles', 'list', 'custom_generation', articleParams.value]),
queryKey: computed(() => [
'articles',
'list',
companyStore.currentBrandId,
'custom_generation',
articleParams.value,
]),
enabled: computed(() => Boolean(companyStore.currentBrandId)),
queryFn: () => articlesApi.list(articleParams.value),
})
@@ -25,6 +25,7 @@ import {
publishStatusShortLabel,
type PublishAccountCard,
} from '@/lib/publish-account-cards'
import { useCompanyStore } from '@/stores/company'
const props = defineProps<{
open: boolean
@@ -38,6 +39,7 @@ const emit = defineEmits<{
const queryClient = useQueryClient()
const { t } = useI18n()
const companyStore = useCompanyStore()
const promptDrawerOpen = ref(false)
const coverPickerOpen = ref(false)
@@ -108,6 +110,7 @@ const selectedSchedulePublishPlatformIds = computed(() => {
const scheduleCoverRequired = computed(() =>
coverUploadRequired(selectedSchedulePublishPlatformIds.value),
)
const currentBrandId = computed(() => companyStore.currentBrandId)
const effectiveScheduleCoverEnabled = computed(
() => scheduleCoverRequired.value || form.coverEnabled,
)
@@ -207,6 +210,7 @@ function buildSchedulePayload() {
return {
name: form.name.trim(),
prompt_rule_id: form.promptRuleId!,
brand_id: currentBrandId.value,
cron_expr: buildDailyCron(form.scheduleTime),
auto_publish: form.autoPublish,
publish_account_ids: form.autoPublish ? form.publishAccountIds : [],
@@ -220,6 +224,7 @@ function buildSchedulePayload() {
function buildInstantPayload() {
return {
prompt_rule_id: form.promptRuleId!,
brand_id: currentBrandId.value ?? undefined,
extra_params: {
task_name: form.name.trim(),
generation_mode: 'instant',
@@ -287,6 +292,11 @@ function handleScheduleCoverToggle(checked: boolean): void {
}
function validateForm(): boolean {
if (!currentBrandId.value) {
message.warning(t('templates.wizard.messages.selectBrandBeforeQuestion'))
return false
}
if (!form.name.trim()) {
message.warning(t('custom.messages.missingTaskName'))
return false
@@ -11,8 +11,10 @@ import GeneratedArticleLinksDrawer from '@/components/GeneratedArticleLinksDrawe
import { instantTasksApi, promptRulesApi } from '@/lib/api'
import { formatDateTime, getGenerateStatusMeta } from '@/lib/display'
import { formatPublishPlatformList } from '@/lib/publish-platforms'
import { useCompanyStore } from '@/stores/company'
const { t } = useI18n()
const companyStore = useCompanyStore()
const page = ref(1)
const pageSize = ref(20)
@@ -72,7 +74,8 @@ const listParams = computed<InstantTaskListParams>(() => {
})
const listQuery = useQuery({
queryKey: computed(() => ['instantTasks', 'list', listParams.value]),
queryKey: computed(() => ['instantTasks', 'list', companyStore.currentBrandId, listParams.value]),
enabled: computed(() => Boolean(companyStore.currentBrandId)),
queryFn: () => instantTasksApi.list(listParams.value),
})
@@ -41,6 +41,7 @@ import {
publishStateLabel,
type PublishAccountCard,
} from '@/lib/publish-account-cards'
import { useCompanyStore } from '@/stores/company'
const props = defineProps<{
open: boolean
@@ -54,6 +55,7 @@ const emit = defineEmits<{
const { t } = useI18n()
const queryClient = useQueryClient()
const companyStore = useCompanyStore()
const selectedAccountIds = ref<string[]>([])
const coverEnabled = ref(false)
@@ -71,8 +73,16 @@ let publishAdmissionRunId = 0
const ackInProgress = ref(false)
const detailQuery = useQuery({
queryKey: computed(() => ['articles', 'detail', props.articleId, 'publish-modal']),
enabled: computed(() => props.open && Boolean(props.articleId)),
queryKey: computed(() => [
'articles',
'detail',
companyStore.currentBrandId,
props.articleId,
'publish-modal',
]),
enabled: computed(
() => props.open && Boolean(props.articleId) && Boolean(companyStore.currentBrandId),
),
queryFn: () => articlesApi.detail(props.articleId as number),
})
@@ -20,9 +20,11 @@ import { promptRulesApi, schedulesApi } from '@/lib/api'
import { formatDateTime, getGenerateStatusMeta, hasActiveGenerationStatus } from '@/lib/display'
import { formatError } from '@/lib/errors'
import { formatPublishPlatformList } from '@/lib/publish-platforms'
import { useCompanyStore } from '@/stores/company'
const queryClient = useQueryClient()
const { t } = useI18n()
const companyStore = useCompanyStore()
const modalOpen = ref(false)
const editingTask = ref<ScheduleTask | null>(null)
@@ -81,7 +83,8 @@ const listParams = computed<ScheduleTaskListParams>(() => {
})
const listQuery = useQuery({
queryKey: computed(() => ['schedules', 'list', listParams.value]),
queryKey: computed(() => ['schedules', 'list', companyStore.currentBrandId, listParams.value]),
enabled: computed(() => Boolean(companyStore.currentBrandId)),
queryFn: () => schedulesApi.list(listParams.value),
})