feat(workspace): replace supported platform count with bound media account count
The "platforms" stat tile was a constant (5) that never reflected what the tenant actually had set up. Drop SupportedPlatformCount from the workspace overview API/domain/shared-types and have admin-web compute a bound media account count from the desktop accounts list, filtered through a new isMediaPublishAccount helper that excludes deleted rows and AI-only platforms (yuanbao/kimi/wenxin/deepseek/doubao/qwen). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import { useI18n } from "vue-i18n";
|
||||
import { mediaApi, resolveApiURL, tenantAccountsApi } from "@/lib/api";
|
||||
import { resolveAccountCheckedAt, resolveAccountHealth } from "@/lib/desktop-account-runtime";
|
||||
import { formatDateTime } from "@/lib/display";
|
||||
import { getPublishPlatformMeta, isPublishPlatformId, normalizePublishPlatformId } from "@/lib/publish-platforms";
|
||||
import { getPublishPlatformMeta, isMediaPublishAccount, normalizePublishPlatformId } from "@/lib/publish-platforms";
|
||||
|
||||
type AccountHealthFilter = "all" | "live" | "captcha" | "risk" | "expired";
|
||||
type PublishState = "immediate" | "queued" | "unavailable";
|
||||
@@ -79,8 +79,7 @@ const platformMap = computed(() => {
|
||||
|
||||
const mediaAccounts = computed<MediaAccountCard[]>(() => {
|
||||
return [...(accountsQuery.data.value ?? [])]
|
||||
.filter((account) => !account.deleted_at)
|
||||
.filter((account) => isPublishPlatformId(account.platform))
|
||||
.filter(isMediaPublishAccount)
|
||||
.map((account) => {
|
||||
const platformId = normalizePublishPlatformId(account.platform);
|
||||
const platform = platformMap.value.get(platformId);
|
||||
|
||||
@@ -26,10 +26,11 @@ import ArticlePublishStatus from "@/components/ArticlePublishStatus.vue";
|
||||
import ArticleSourceMeta from "@/components/ArticleSourceMeta.vue";
|
||||
import ArticleDetailDrawer from "@/components/ArticleDetailDrawer.vue";
|
||||
import PublishArticleModal from "@/components/PublishArticleModal.vue";
|
||||
import { articlesApi, workspaceApi } from "@/lib/api";
|
||||
import { articlesApi, tenantAccountsApi, workspaceApi } from "@/lib/api";
|
||||
import { buildArticleClipboardContent, resolveArticleActionState } from "@/lib/article-list-actions";
|
||||
import { formatDateTime, getTemplateMeta } from "@/lib/display";
|
||||
import { formatError } from "@/lib/errors";
|
||||
import { isMediaPublishAccount } from "@/lib/publish-platforms";
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const router = useRouter();
|
||||
@@ -44,6 +45,10 @@ const overviewQuery = useQuery({
|
||||
queryKey: ["workspace", "overview"],
|
||||
queryFn: () => workspaceApi.overview(),
|
||||
});
|
||||
const accountsQuery = useQuery({
|
||||
queryKey: ["tenant", "desktop-accounts", "workspace-overview"],
|
||||
queryFn: () => tenantAccountsApi.list(),
|
||||
});
|
||||
const recentArticlesQuery = useQuery({
|
||||
queryKey: ["workspace", "recent-articles"],
|
||||
queryFn: () => workspaceApi.recentArticles(),
|
||||
@@ -83,13 +88,17 @@ const statIcons = [
|
||||
PlaySquareOutlined,
|
||||
];
|
||||
|
||||
const boundMediaAccountCount = computed(() =>
|
||||
(accountsQuery.data.value ?? []).filter(isMediaPublishAccount).length,
|
||||
);
|
||||
|
||||
const statItems = computed(() => {
|
||||
const overview = overviewQuery.data.value;
|
||||
return [
|
||||
{ label: t("workspace.metrics.articles"), value: overview?.article_count ?? 0, icon: statIcons[0] },
|
||||
{ label: t("workspace.metrics.published"), value: overview?.published_count ?? 0, icon: statIcons[1] },
|
||||
{ label: t("workspace.metrics.brands"), value: overview?.brand_count ?? 0, icon: statIcons[2] },
|
||||
{ label: t("workspace.metrics.platforms"), value: overview?.supported_platform_count ?? 0, icon: statIcons[3] },
|
||||
{ label: t("workspace.metrics.mediaAccounts"), value: boundMediaAccountCount.value, icon: statIcons[3] },
|
||||
];
|
||||
});
|
||||
|
||||
@@ -231,6 +240,7 @@ async function handleDelete(articleId: number): Promise<void> {
|
||||
function refreshDashboard(): void {
|
||||
void Promise.all([
|
||||
overviewQuery.refetch(),
|
||||
accountsQuery.refetch(),
|
||||
recentArticlesQuery.refetch(),
|
||||
templateCardsQuery.refetch(),
|
||||
kolCardsQuery.refetch(),
|
||||
|
||||
Reference in New Issue
Block a user