From 1b1ab7ee0c3af9dc6a0b806ad890a20dbdff2a6c Mon Sep 17 00:00:00 2001 From: liangxu Date: Fri, 24 Apr 2026 22:21:01 +0800 Subject: [PATCH] feat(admin-web): surface monitoring platform authorization status Dashboard and question-detail views now read platform_authorization_status from the API. Tracking disables collect-now when the account has no desktop client, no authorized platforms, or the selected platform is unauthorized, and keeps the six-platform matrix stable; question-detail replaces tabs and cards with an explicit unavailable notice when the account is not authorized for monitoring. Adds the shared type and en/zh strings covering each status. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/admin-web/src/i18n/messages/en-US.ts | 22 +++++++++ apps/admin-web/src/i18n/messages/zh-CN.ts | 22 +++++++++ .../src/views/TrackingQuestionDetailView.vue | 49 +++++++++++++++++-- apps/admin-web/src/views/TrackingView.vue | 45 +++++++++++++++-- packages/shared-types/src/index.ts | 9 ++++ 5 files changed, 137 insertions(+), 10 deletions(-) diff --git a/apps/admin-web/src/i18n/messages/en-US.ts b/apps/admin-web/src/i18n/messages/en-US.ts index 91003b7..548c426 100644 --- a/apps/admin-web/src/i18n/messages/en-US.ts +++ b/apps/admin-web/src/i18n/messages/en-US.ts @@ -351,6 +351,9 @@ const enUS = { collectTodayOnly: "Collect Now only supports today's data. Switch back to today to continue.", collectClientChecking: "Checking whether the current account's desktop client is online.", collectClientOnlineRequired: "The current account's desktop client must be online before collecting.", + noDesktopClientCollectReason: "This account has no registered desktop client, so collection cannot start.", + noAuthorizedPlatformsCollectReason: "This account has no authorized AI platforms, so collection cannot start.", + collectPlatformUnauthorized: "The selected platform is not authorized for this account.", pluginMode: "Plugin sampling", pluginHint: "Plugin-mode data depends on device uptime. Low coverage should be treated as directional only.", awaitingSnapshot: "Waiting for the next valid snapshot", @@ -393,6 +396,25 @@ const enUS = { noCitationAnalysis: "No citation analysis for this platform", noContentCitations: "No content citations for the active platform", noTaskDebug: "No async task debug data for the current filters", + noPlatformBreakdown: "No platform data is available for the current filters", + selectedPlatformUnauthorizedTitle: "Selected Platform Not Authorized", + selectedPlatformUnauthorizedDescription: "This AI platform has no active authorization for the current account. Switch to an authorized platform or authorize it in the desktop client.", + noDetailPlatformsTitle: "No Platforms Available", + noDetailPlatformsDescription: "No AI platform data is available for the current filters.", + platformAuthorization: { + authorized: { + title: "AI Platform Authorization Active", + description: "This account has AI platform authorization available for monitoring collection.", + }, + no_desktop_client: { + title: "No Desktop Client Detected", + description: "This account has not registered a desktop client. Daily tasks will wait for an eligible client before dispatch, and the dashboard will not show collection as available.", + }, + no_authorized_platforms: { + title: "No Authorized AI Platforms", + description: "This account has no bound or authorized AI platform accounts. The system will not generate or dispatch collection tasks for unauthorized platforms.", + }, + }, samples: "samples", citations: "citations", citedArticleMeta: "{count} cited articles", diff --git a/apps/admin-web/src/i18n/messages/zh-CN.ts b/apps/admin-web/src/i18n/messages/zh-CN.ts index 9ad209b..af14d19 100644 --- a/apps/admin-web/src/i18n/messages/zh-CN.ts +++ b/apps/admin-web/src/i18n/messages/zh-CN.ts @@ -351,6 +351,9 @@ const zhCN = { collectTodayOnly: "立即采集只支持今天的数据,请切回今天后再操作", collectClientChecking: "正在检查当前账号的桌面客户端状态", collectClientOnlineRequired: "当前登录账号的桌面客户端未在线,暂时不能立即采集", + noDesktopClientCollectReason: "当前账号尚未注册桌面客户端,不能发起采集", + noAuthorizedPlatformsCollectReason: "当前账号暂无已授权 AI 平台,不能发起采集", + collectPlatformUnauthorized: "当前筛选平台未授权,不能发起采集", pluginMode: "插件采样", pluginHint: "插件模式下结果受设备在线率影响,低覆盖样本仅供趋势参考。", awaitingSnapshot: "等待下一次有效快照", @@ -393,6 +396,25 @@ const zhCN = { noCitationAnalysis: "该平台暂无引用分析", noContentCitations: "当前平台暂无内容引用", noTaskDebug: "当前条件下暂无异步任务调试数据", + noPlatformBreakdown: "当前筛选条件下暂无可展示的平台数据", + selectedPlatformUnauthorizedTitle: "当前平台未授权", + selectedPlatformUnauthorizedDescription: "该 AI 平台没有当前账号的有效授权记录,请切换到已授权平台或在桌面端完成授权。", + noDetailPlatformsTitle: "暂无可展示平台", + noDetailPlatformsDescription: "当前筛选条件下没有可展示的 AI 平台数据。", + platformAuthorization: { + authorized: { + title: "AI 平台授权正常", + description: "当前账号已有可用于监控采集的 AI 平台授权。", + }, + no_desktop_client: { + title: "未检测到桌面客户端", + description: "当前账号尚未注册桌面客户端。每日任务会等待有效客户端上线后再下发,仪表盘不会展示为可采集状态。", + }, + no_authorized_platforms: { + title: "暂无已授权 AI 平台", + description: "当前账号没有已绑定或已授权的 AI 平台。系统不会为未授权平台生成或下发采集任务。", + }, + }, samples: "次采样", citations: "次引用", citedArticleMeta: "{count} 篇内容被引用", diff --git a/apps/admin-web/src/views/TrackingQuestionDetailView.vue b/apps/admin-web/src/views/TrackingQuestionDetailView.vue index ff22461..5e00f4e 100644 --- a/apps/admin-web/src/views/TrackingQuestionDetailView.vue +++ b/apps/admin-web/src/views/TrackingQuestionDetailView.vue @@ -65,6 +65,21 @@ const detailQuery = useQuery({ const activePlatformId = ref(""); const detailPlatforms = computed(() => detailQuery.data.value?.platforms ?? []); +const hasNoDetailPlatforms = computed(() => { + return Boolean(detailQuery.data.value) && detailPlatforms.value.length === 0; +}); +const shouldShowDetailUnavailableNotice = computed(() => { + return hasNoDetailPlatforms.value; +}); +const detailUnavailableNoticeType = computed<"warning" | "info">(() => { + return "info"; +}); +const detailUnavailableNoticeTitle = computed(() => { + return requestedPlatformId.value ? t("tracking.selectedPlatformUnauthorizedTitle") : t("tracking.noDetailPlatformsTitle"); +}); +const detailUnavailableNoticeDescription = computed(() => { + return requestedPlatformId.value ? t("tracking.selectedPlatformUnauthorizedDescription") : t("tracking.noDetailPlatformsDescription"); +}); const detailCitationAnalysis = computed(() => detailQuery.data.value?.citation_analysis ?? []); const citationSourcesScrollRef = ref(null); const highlightedCitationIndex = ref(null); @@ -919,7 +934,19 @@ const contentCitationColumns = computed(() => [
-
+ + +
[
-
+
@@ -1035,7 +1065,7 @@ const contentCitationColumns = computed(() => [
-
+
[ - +
@@ -1078,7 +1108,7 @@ const contentCitationColumns = computed(() => [
-
+
[ padding-right: 12px; } +.tracking-question-table-wrap { + margin: 0; + padding: 0; +} + +.tracking-question-empty { + margin-top: 40px; +} + .tracking-question-answer__headline { display: flex; align-items: center; diff --git a/apps/admin-web/src/views/TrackingView.vue b/apps/admin-web/src/views/TrackingView.vue index 961bf53..f005128 100644 --- a/apps/admin-web/src/views/TrackingView.vue +++ b/apps/admin-web/src/views/TrackingView.vue @@ -10,6 +10,7 @@ import type { Brand, DesktopAccountInfo, MonitoringHotQuestion, + MonitoringPlatformAuthorizationStatus, } from "@geo/shared-types"; import { aiPlatformCatalog } from "@geo/shared-types"; import { computed, watch } from "vue"; @@ -283,6 +284,22 @@ const currentUserClientOnline = computed(() => { return dashboardQuery.data.value?.runtime.current_user_client_online === true; }); +const platformBreakdownRows = computed(() => { + return dashboardQuery.data.value?.platform_breakdown ?? []; +}); + +const platformAuthorizationStatus = computed(() => { + return dashboardQuery.data.value?.runtime.platform_authorization_status ?? "authorized"; +}); + +const selectedPlatformAuthorized = computed(() => { + if (selectedPlatformId.value === "all") { + return true; + } + const authorizedPlatformIDs = dashboardQuery.data.value?.runtime.authorized_monitoring_platform_ids ?? []; + return authorizedPlatformIDs.some((item) => normalizeMonitoringPlatformId(item) === selectedPlatformId.value); +}); + const collectNowDisabledReason = computed(() => { if (!selectedBrandId.value) { return t("tracking.collectBrandRequired"); @@ -296,6 +313,15 @@ const collectNowDisabledReason = computed(() => { if (dashboardQuery.isLoading.value && !dashboardQuery.data.value) { return t("tracking.collectClientChecking"); } + if (platformAuthorizationStatus.value === "no_desktop_client") { + return t("tracking.noDesktopClientCollectReason"); + } + if (platformAuthorizationStatus.value === "no_authorized_platforms") { + return t("tracking.noAuthorizedPlatformsCollectReason"); + } + if (selectedPlatformId.value !== "all" && dashboardQuery.data.value && !selectedPlatformAuthorized.value) { + return t("tracking.collectPlatformUnauthorized"); + } if (!currentUserClientOnline.value) { return t("tracking.collectClientOnlineRequired"); } @@ -625,7 +651,7 @@ function normalizeTrackingBusinessDate(value: unknown): string | null { return null; } - const today = dayjs().startOf("day"); + const today = dayjs(trackingToday).startOf("day"); const earliestAllowed = today.subtract(trackingMaxHistoryDays - 1, "day"); if (parsed.isAfter(today, "day") || parsed.isBefore(earliestAllowed, "day")) { return null; @@ -634,8 +660,8 @@ function normalizeTrackingBusinessDate(value: unknown): string | null { } function disableTrackingDate(current: dayjs.Dayjs): boolean { - const today = dayjs().endOf("day"); - const earliestAllowed = dayjs().subtract(trackingMaxHistoryDays - 1, "day").startOf("day"); + const today = dayjs(trackingToday).endOf("day"); + const earliestAllowed = dayjs(trackingToday).subtract(trackingMaxHistoryDays - 1, "day").startOf("day"); return current.isAfter(today) || current.isBefore(earliestAllowed); } @@ -739,7 +765,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {

{{ t("tracking.platformMatrixTitle") }}

-
+
{{ t("tracking.columns.platform") }} {{ t("tracking.metrics.mentionRate") }} @@ -748,7 +774,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
@@ -763,6 +789,11 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
+
@@ -1188,6 +1219,10 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean { font-size: 13px; } +.tracking-panel__empty { + padding: 28px 0 16px; +} + .tracking-metric-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); diff --git a/packages/shared-types/src/index.ts b/packages/shared-types/src/index.ts index 258db3d..268a8e2 100644 --- a/packages/shared-types/src/index.ts +++ b/packages/shared-types/src/index.ts @@ -1110,8 +1110,16 @@ export interface MonitoringCitedArticle { citation_rate: number | null; } +export type MonitoringPlatformAuthorizationStatus = + | "authorized" + | "no_desktop_client" + | "no_authorized_platforms"; + export interface MonitoringDashboardRuntime { current_user_client_online: boolean; + platform_authorization_status: MonitoringPlatformAuthorizationStatus; + authorized_monitoring_platform_ids: string[]; + authorized_monitoring_platform_count: number; } export interface MonitoringDashboardCompositeResponse { @@ -1174,6 +1182,7 @@ export interface MonitoringQuestionDetailResponse { question_id: number; question_hash: string; question_text: string; + platform_authorization_status: MonitoringPlatformAuthorizationStatus; time_window: { date_from: string; date_to: string;