feat(kol): support multiple platform hints with shared tag renderer
Frontend CI / Frontend (push) Successful in 2m47s
Backend CI / Backend (push) Failing after 6m50s

Turn the KOL prompt platform hint into a multi-select backed by the
media platforms API, persist hints as a 、-joined string, and add a
reusable KolPlatformTags component so manage/generate/package/template/
workspace views and the generate-task drawer all render the hints
consistently with truncation and overflow handling.

Also auto-select the first available subscription prompt in
GenerateTaskDrawer when switching to the subscription-prompt target so
users land on a usable option without an extra click.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 01:48:04 +08:00
parent db95b8e4ee
commit 8991edabb5
10 changed files with 322 additions and 57 deletions
+9 -4
View File
@@ -1,6 +1,7 @@
<script setup lang="ts">
import KnowledgeGroupSelect from '@/components/KnowledgeGroupSelect.vue'
import KolDynamicForm from '@/components/kol/KolDynamicForm.vue'
import KolPlatformTags from '@/components/kol/KolPlatformTags.vue'
import { kolGenerateApi } from '@/lib/api'
import { formatError } from '@/lib/errors'
import { parseKolCardConfig } from '@/lib/kol-card-config'
@@ -150,10 +151,14 @@ function handleSubmit() {
{{ schema.package_name }}
<span class="divider">/</span>
{{ schema.prompt_name }}
<a-tag v-if="schema.platform_hint" color="cyan" class="platform-badge">
{{ schema.platform_hint }}
</a-tag>
</h2>
<KolPlatformTags
v-if="schema.platform_hint"
:value="schema.platform_hint"
size="small"
:truncate="false"
class="platform-badge"
/>
<p class="header-eyebrow">{{ t('kol.generate.fillVariables') }}</p>
</div>
</div>
@@ -268,7 +273,7 @@ function handleSubmit() {
}
.platform-badge {
margin-left: 8px;
margin-top: 2px;
}
.header-eyebrow {
+6 -3
View File
@@ -16,6 +16,7 @@ import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import KolPackageFormModal from '@/components/kol/KolPackageFormModal.vue'
import KolPlatformTags from '@/components/kol/KolPlatformTags.vue'
import KolPromptEditor from '@/components/kol/KolPromptEditor.vue'
import KolPromptFormModal from '@/components/kol/KolPromptFormModal.vue'
import { kolManageApi } from '@/lib/api'
@@ -400,9 +401,11 @@ function canCancelSelfSubscription(pkg: KolPackageSummary) {
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'platform_hint'">
<a-tag color="blue">
{{ record.platform_hint || t('kol.manage.platformHintDefault') }}
</a-tag>
<KolPlatformTags
:value="record.platform_hint || t('kol.manage.platformHintDefault')"
:max="3"
size="small"
/>
</template>
<template v-else-if="column.key === 'status'">
<a-tag
@@ -1,4 +1,5 @@
<script setup lang="ts">
import KolPlatformTags from '@/components/kol/KolPlatformTags.vue'
import { kolMarketplaceApi, resolveApiURL } from '@/lib/api'
import { formatError } from '@/lib/errors'
import {
@@ -158,9 +159,12 @@ function goBack() {
<div v-for="prompt in pkg.prompts" :key="prompt.id" class="prompt-item">
<div class="prompt-info">
<span class="prompt-name">{{ prompt.name }}</span>
<a-tag v-if="prompt.platform_hint" color="cyan" size="small">
{{ prompt.platform_hint }}
</a-tag>
<KolPlatformTags
v-if="prompt.platform_hint"
:value="prompt.platform_hint"
:max="4"
size="small"
/>
</div>
<div class="prompt-action">
<a-tooltip :title="subscription?.status !== 'active' ? '订阅后可用' : ''">
+23 -10
View File
@@ -30,6 +30,7 @@ import ArticleDetailDrawer from '@/components/ArticleDetailDrawer.vue'
import ArticleGenerateStatus from '@/components/ArticleGenerateStatus.vue'
import ArticlePublishStatus from '@/components/ArticlePublishStatus.vue'
import ArticleSourceMeta from '@/components/ArticleSourceMeta.vue'
import KolPlatformTags from '@/components/kol/KolPlatformTags.vue'
import PublishArticleModal from '@/components/PublishArticleModal.vue'
import { articlesApi, templatesApi, workspaceApi } from '@/lib/api'
import { buildArticleClipboardContent, resolveArticleActionState } from '@/lib/article-list-actions'
@@ -826,9 +827,14 @@ function refreshRecords(): void {
</div>
<span>{{ card.kol_display_name }}</span>
</div>
<div v-if="card.platform_hint" class="templates-view__kol-platform">
{{ card.platform_hint }}
</div>
<KolPlatformTags
v-if="card.platform_hint"
:value="card.platform_hint"
:max="2"
size="small"
:wrap="false"
class="templates-view__kol-platform"
/>
</div>
</div>
</article>
@@ -1457,6 +1463,7 @@ function refreshRecords(): void {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-top: 16px;
padding-top: 12px;
border-top: 1px solid #f3f4f6;
@@ -1466,12 +1473,22 @@ function refreshRecords(): void {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1 1 auto;
font-size: 12px;
color: #374151;
font-weight: 500;
}
.templates-view__kol-author span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.templates-view__author-avatar {
flex: 0 0 auto;
width: 20px;
height: 20px;
border-radius: 50%;
@@ -1485,13 +1502,9 @@ function refreshRecords(): void {
}
.templates-view__kol-platform {
background: #eff6ff;
color: #2563eb;
font-size: 11px;
font-weight: 500;
padding: 2px 8px;
border-radius: 6px;
white-space: nowrap;
flex: 0 1 auto;
max-width: 54%;
justify-content: flex-end;
}
@media (max-width: 1200px) {
+23 -10
View File
@@ -25,6 +25,7 @@ import ArticleDetailDrawer from '@/components/ArticleDetailDrawer.vue'
import ArticleGenerateStatus from '@/components/ArticleGenerateStatus.vue'
import ArticlePublishStatus from '@/components/ArticlePublishStatus.vue'
import ArticleSourceMeta from '@/components/ArticleSourceMeta.vue'
import KolPlatformTags from '@/components/kol/KolPlatformTags.vue'
import PublishArticleModal from '@/components/PublishArticleModal.vue'
import { articlesApi, tenantAccountsApi, workspaceApi } from '@/lib/api'
import { buildArticleClipboardContent, resolveArticleActionState } from '@/lib/article-list-actions'
@@ -440,9 +441,14 @@ function stopRecentArticlesPolling(): void {
</div>
<span>{{ card.kol_display_name }}</span>
</div>
<div v-if="card.platform_hint" class="kol-card-platform">
{{ card.platform_hint }}
</div>
<KolPlatformTags
v-if="card.platform_hint"
:value="card.platform_hint"
:max="2"
size="small"
:wrap="false"
class="kol-card-platform"
/>
</div>
</div>
</div>
@@ -952,6 +958,7 @@ function stopRecentArticlesPolling(): void {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-top: 16px;
padding-top: 12px;
border-top: 1px solid #f3f4f6;
@@ -961,12 +968,22 @@ function stopRecentArticlesPolling(): void {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1 1 auto;
font-size: 12px;
color: #374151;
font-weight: 500;
}
.kol-card-author span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.author-avatar {
flex: 0 0 auto;
width: 20px;
height: 20px;
border-radius: 50%;
@@ -980,13 +997,9 @@ function stopRecentArticlesPolling(): void {
}
.kol-card-platform {
background: #eff6ff;
color: #2563eb;
font-size: 11px;
font-weight: 500;
padding: 2px 8px;
border-radius: 6px;
white-space: nowrap;
flex: 0 1 auto;
max-width: 54%;
justify-content: flex-end;
}
@media (max-width: 1200px) {