fix media supply citation attribution
Desktop Client Build / Resolve Build Metadata (push) Successful in 26s
Frontend CI / Frontend (push) Successful in 2m53s
Backend CI / Backend (push) Successful in 16m37s
Desktop Client Build / Build Desktop Client (push) Successful in 23m40s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 28s
Desktop Client Build / Resolve Build Metadata (push) Successful in 26s
Frontend CI / Frontend (push) Successful in 2m53s
Backend CI / Backend (push) Successful in 16m37s
Desktop Client Build / Build Desktop Client (push) Successful in 23m40s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 28s
This commit is contained in:
@@ -273,7 +273,7 @@ const enUS = {
|
||||
trackingQuestion: {
|
||||
title: 'Question Detail',
|
||||
description:
|
||||
'Inspect answer content, citation sources, citation analysis, and content citations for a single question.',
|
||||
'Inspect answer content, citation sources, citation analysis, and answer citations for a single question.',
|
||||
},
|
||||
knowledge: {
|
||||
title: 'Knowledge Base',
|
||||
@@ -596,24 +596,25 @@ const enUS = {
|
||||
citationSourcesTitle: 'Citation Sources',
|
||||
citationAnalysis: 'Citation Analysis',
|
||||
citationAnalysisTitle: 'Citation Analysis',
|
||||
contentCitations: 'Content Citations',
|
||||
contentCitationsTitle: 'Content Citations',
|
||||
contentCitations: 'Answer Citations',
|
||||
contentCitationsTitle: 'Answer Citations',
|
||||
imitationAction: 'Imitation create',
|
||||
taskDebugTitle: 'Async Task Debug',
|
||||
taskDebugHint:
|
||||
'For troubleshooting the callback -> queue -> worker flow only. The four main content sections above stay unchanged.',
|
||||
contentCitationBadge: 'Content Citation',
|
||||
contentCitationBadge: 'Published Article Citation',
|
||||
mediaSupplySubmissionCitation: 'Submission Citation',
|
||||
manualMarkedArticle: 'External Article',
|
||||
markAsExternalArticle: 'Mark as external article',
|
||||
markedArticleSaved: 'Marked as external article.',
|
||||
noQuestions: 'No hot questions for the current filters',
|
||||
noCitationRanking: 'No attributable citations in the current window',
|
||||
noCitedArticles: 'No content citations in the current window',
|
||||
noCitedArticles: 'No published article citations in the current window',
|
||||
viewArticleContent: 'View article content',
|
||||
noAnswer: 'No sampled answer for this platform',
|
||||
noCitations: 'No citations for this platform',
|
||||
noCitationAnalysis: 'No citation analysis for this platform',
|
||||
noContentCitations: 'No content citations for the active platform',
|
||||
noContentCitations: 'No answer 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',
|
||||
@@ -641,7 +642,7 @@ const enUS = {
|
||||
samples: 'samples',
|
||||
citations: 'citations',
|
||||
citedArticleMeta: '{count} cited articles',
|
||||
contentCitationMeta: '{count} content references',
|
||||
contentCitationMeta: '{count} published article references',
|
||||
manual: 'Manual',
|
||||
automatic: 'Automatic',
|
||||
noChange: 'Flat',
|
||||
@@ -663,7 +664,7 @@ const enUS = {
|
||||
channelName: 'Channel',
|
||||
domain: 'Domain',
|
||||
share: 'Share',
|
||||
contentName: 'Content',
|
||||
contentName: 'Article',
|
||||
publishPlatform: 'Publish Platform',
|
||||
distinctSites: 'Distinct Sites',
|
||||
brandContent: 'Has Brand Content',
|
||||
|
||||
@@ -271,7 +271,7 @@ const zhCN = {
|
||||
},
|
||||
trackingQuestion: {
|
||||
title: '问题详情',
|
||||
description: '按问题查看大模型回答、引用来源、引用分析和内容引用。',
|
||||
description: '按问题查看大模型回答、引用来源、引用分析和回答引用。',
|
||||
},
|
||||
knowledge: {
|
||||
title: '知识库',
|
||||
@@ -556,8 +556,6 @@ const zhCN = {
|
||||
platformMatrixTitle: '平台对比矩阵',
|
||||
hotQuestions: 'Hot Questions',
|
||||
hotQuestionsTitle: '高频问题',
|
||||
hotQuestionsHint:
|
||||
'可选择全部关键词库(搜索词)或具体单个搜索词;选择单个搜索词时只展示并采集该搜索词。',
|
||||
questionSearchPlaceholder: '搜索当前范围下的问题',
|
||||
noQuestionSearchResults: '没有匹配的问题',
|
||||
questionDetailEyebrow: 'Question Detail',
|
||||
@@ -566,7 +564,7 @@ const zhCN = {
|
||||
backToQuestions: '返回问题列表',
|
||||
citationRanking: 'Citation Ranking',
|
||||
citationRankingTitle: '引用排行',
|
||||
citationRankingHint: '按发布外链和手动标记 URL 归因外部文章在模型引用来源中的出现次数与占比。',
|
||||
citationRankingHint: '按发布外链、投稿外链和手动标记 URL 归因外部文章在模型引用来源中的出现次数与占比。',
|
||||
citationWindow7: '近 7 天',
|
||||
citationWindow30: '近 30 天',
|
||||
citationWindowLabel: '近 {days} 天',
|
||||
@@ -577,23 +575,24 @@ const zhCN = {
|
||||
citationSourcesTitle: '引用来源',
|
||||
citationAnalysis: 'Citation Analysis',
|
||||
citationAnalysisTitle: '引用分析',
|
||||
contentCitations: 'Content Citations',
|
||||
contentCitationsTitle: '内容引用',
|
||||
contentCitations: '回答引用',
|
||||
contentCitationsTitle: '回答引用',
|
||||
imitationAction: '仿写创作',
|
||||
taskDebugTitle: '异步任务调试',
|
||||
taskDebugHint: '仅用于排查 callback -> queue -> worker 的异步流转,不影响上方四块主内容。',
|
||||
contentCitationBadge: '内容引用',
|
||||
contentCitationBadge: '发文引用',
|
||||
mediaSupplySubmissionCitation: '投稿引用',
|
||||
manualMarkedArticle: '外部文章',
|
||||
markAsExternalArticle: '标记为外部文章',
|
||||
markedArticleSaved: '已标记为外部文章',
|
||||
noQuestions: '当前筛选条件下暂无高频问题',
|
||||
noCitationRanking: '当前时间窗口内暂无可归因引用',
|
||||
noCitedArticles: '当前时间窗口内暂无内容引用',
|
||||
noCitedArticles: '当前时间窗口内暂无发文引用',
|
||||
viewArticleContent: '查看文章内容',
|
||||
noAnswer: '该平台暂无采样回答',
|
||||
noCitations: '该平台无引用来源',
|
||||
noCitationAnalysis: '该平台暂无引用分析',
|
||||
noContentCitations: '当前平台暂无内容引用',
|
||||
noContentCitations: '当前平台暂无回答引用',
|
||||
noTaskDebug: '当前条件下暂无异步任务调试数据',
|
||||
noPlatformBreakdown: '当前筛选条件下暂无可展示的平台数据',
|
||||
selectedPlatformUnauthorizedTitle: '当前平台未授权',
|
||||
@@ -620,7 +619,7 @@ const zhCN = {
|
||||
samples: '次采样',
|
||||
citations: '次引用',
|
||||
citedArticleMeta: '{count} 篇内容被引用',
|
||||
contentCitationMeta: '含 {count} 条内容引用',
|
||||
contentCitationMeta: '含 {count} 条发文引用',
|
||||
manual: '手动',
|
||||
automatic: '自动',
|
||||
noChange: '持平',
|
||||
@@ -642,7 +641,7 @@ const zhCN = {
|
||||
channelName: '渠道名称',
|
||||
domain: '来源域名',
|
||||
share: '占比',
|
||||
contentName: '内容名称',
|
||||
contentName: '文章名称',
|
||||
publishPlatform: '发布平台',
|
||||
distinctSites: '引用站点数',
|
||||
brandContent: '含品牌内容',
|
||||
|
||||
@@ -53,7 +53,7 @@ const columns = computed<TableColumnsType<MediaSupplyOrderDetail>>(() => [
|
||||
align: 'right',
|
||||
},
|
||||
{ title: '扣款', key: 'wallet', width: 150 },
|
||||
{ title: '媒体', key: 'items', width: 110, align: 'right' },
|
||||
{ title: '媒体', key: 'items', width: 110 },
|
||||
{ title: '回链', key: 'backlinks', width: 220 },
|
||||
{ title: '外部单号', key: 'external_order_code', dataIndex: 'external_order_code', width: 170 },
|
||||
{ title: '创建时间', key: 'created_at', dataIndex: 'created_at', width: 170 },
|
||||
@@ -267,7 +267,7 @@ function formatOrderError(message?: string | null): string {
|
||||
onShowSizeChange: handleTableChange,
|
||||
}"
|
||||
row-key="id"
|
||||
:scroll="{ x: 1580 }"
|
||||
:scroll="{ x: 1630 }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'title'">
|
||||
@@ -475,7 +475,7 @@ function formatOrderError(message?: string | null): string {
|
||||
color: #475467 !important;
|
||||
font-weight: 600 !important;
|
||||
border-bottom: 1px solid #e2e8f0 !important;
|
||||
text-align: center;
|
||||
padding: 12px 16px !important;
|
||||
}
|
||||
|
||||
.orders-table-wrap :deep(.ant-table-tbody > tr > td) {
|
||||
|
||||
@@ -802,9 +802,10 @@ function toResourceRow(item: CustomerSupplierMediaResource): MediaSupplyResource
|
||||
selectedRowKeys,
|
||||
preserveSelectedRowKeys: true,
|
||||
onChange: onSelectionChange,
|
||||
columnWidth: 60,
|
||||
}"
|
||||
row-key="id"
|
||||
:scroll="{ x: 1560 }"
|
||||
:scroll="{ x: 1764 }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
@@ -1424,12 +1425,12 @@ div.favorite-modal :deep(.ant-input::placeholder) {
|
||||
background: #f7f7f7;
|
||||
color: #666;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
border-color: #dcdcdc;
|
||||
padding: 10px 14px !important;
|
||||
}
|
||||
|
||||
.media-supply-table-wrap :deep(.ant-table-tbody > tr > td) {
|
||||
padding: 10px 14px;
|
||||
padding: 10px 14px !important;
|
||||
border-color: #dcdcdc;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { ArrowLeftOutlined, BookOutlined, CopyOutlined } from '@ant-design/icons-vue'
|
||||
import type {
|
||||
MonitoringQuestionCitationAnalysisItem,
|
||||
MonitoringQuestionContentCitation,
|
||||
MonitoringQuestionDetailCitation,
|
||||
MonitoringQuestionDetailPlatform,
|
||||
MonitoringSourceItem,
|
||||
@@ -199,10 +198,7 @@ const activeDeepSeekCitationReferenceLabels = computed<string[][]>(() => {
|
||||
})
|
||||
|
||||
const activeInlineContentCitations = computed<TrackingAnalyzedContentCitation[]>(() => {
|
||||
return analyzeContentCitations(
|
||||
activePlatform.value,
|
||||
detailQuery.data.value?.content_citations ?? [],
|
||||
)
|
||||
return analyzeAnswerCitations(activePlatform.value)
|
||||
})
|
||||
|
||||
const shouldShowInlineContentCitations = computed(() => {
|
||||
@@ -353,6 +349,12 @@ function isManualMarkedCitation(
|
||||
return citation?.source_type === 'manual_mark'
|
||||
}
|
||||
|
||||
function isMediaSupplySubmissionCitation(
|
||||
citation: MonitoringQuestionDetailCitation | null | undefined,
|
||||
): boolean {
|
||||
return citation?.source_type === 'media_supply_order_item'
|
||||
}
|
||||
|
||||
function canMarkCitationAsExternal(
|
||||
citation: MonitoringQuestionDetailCitation | null | undefined,
|
||||
): boolean {
|
||||
@@ -373,14 +375,22 @@ function isLinkedInlineCitationPlatform(platformId: string | null | undefined):
|
||||
return platformId === 'yuanbao' || platformId === 'qwen'
|
||||
}
|
||||
|
||||
function isKimiInlineCitationPlatform(platformId: string | null | undefined): boolean {
|
||||
return platformId === 'kimi'
|
||||
function isQwenInlineCitationPlatform(platformId: string | null | undefined): boolean {
|
||||
return platformId === 'qwen'
|
||||
}
|
||||
|
||||
function isYuanbaoInlineCitationPlatform(platformId: string | null | undefined): boolean {
|
||||
return platformId === 'yuanbao'
|
||||
}
|
||||
|
||||
function isDeepSeekInlineCitationPlatform(platformId: string | null | undefined): boolean {
|
||||
return platformId === 'deepseek'
|
||||
}
|
||||
|
||||
function supportsAnswerCitationTags(platformId: string | null | undefined): boolean {
|
||||
return isLinkedInlineCitationPlatform(platformId) || isDeepSeekInlineCitationPlatform(platformId)
|
||||
}
|
||||
|
||||
function createQwenSourceGroupPattern(): RegExp {
|
||||
return /\[\[source_group_web_(\d+)\]\]/g
|
||||
}
|
||||
@@ -409,10 +419,6 @@ function createQwenSourceGroupStripPattern(): RegExp {
|
||||
return /\[\[\s*source_group_web_[^\[\]]*?\]\]/gi
|
||||
}
|
||||
|
||||
function createMarkdownLinkPattern(): RegExp {
|
||||
return /\[([^\]\n]+)\]\((https?:\/\/[^)\s]+)\)/g
|
||||
}
|
||||
|
||||
function looksLikeHtmlAnswer(value: string | null | undefined): boolean {
|
||||
const normalized = String(value ?? '').trim()
|
||||
return /<\/?[a-z][^>]*>/i.test(normalized)
|
||||
@@ -430,13 +436,21 @@ function parseHtmlFragment(content: string): HTMLElement | null {
|
||||
: null
|
||||
}
|
||||
|
||||
function collectInlineCitationIndexes(answerText: string): number[] {
|
||||
const matches = [
|
||||
...answerText.matchAll(createQwenSourceGroupPattern()),
|
||||
...answerText.matchAll(createYuanbaoCitationPattern()),
|
||||
]
|
||||
function collectPlatformInlineCitationIndexes(
|
||||
answerText: string,
|
||||
platformId: string | null | undefined,
|
||||
): number[] {
|
||||
const pattern = isQwenInlineCitationPlatform(platformId)
|
||||
? createQwenSourceGroupPattern()
|
||||
: isYuanbaoInlineCitationPlatform(platformId)
|
||||
? createYuanbaoCitationPattern()
|
||||
: null
|
||||
|
||||
return matches
|
||||
if (!pattern) {
|
||||
return []
|
||||
}
|
||||
|
||||
return Array.from(answerText.matchAll(pattern))
|
||||
.map((match) => Number(match[1]))
|
||||
.filter((value) => Number.isFinite(value) && value > 0)
|
||||
}
|
||||
@@ -464,48 +478,6 @@ function deriveCitationChannelName(url: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function collectKimiInlineCitationOccurrences(answerText: string): Array<{
|
||||
url: string
|
||||
label: string | null
|
||||
citationCount: number
|
||||
}> {
|
||||
const counts = new Map<string, { label: string | null; citationCount: number }>()
|
||||
const pattern = createMarkdownLinkPattern()
|
||||
|
||||
for (const match of answerText.matchAll(pattern)) {
|
||||
const matchIndex = match.index ?? 0
|
||||
if (matchIndex > 0 && answerText[matchIndex - 1] === '!') {
|
||||
continue
|
||||
}
|
||||
|
||||
const label = String(match[1] ?? '').trim() || null
|
||||
const url = normalizeInlineCitationUrl(match[2])
|
||||
if (!url) {
|
||||
continue
|
||||
}
|
||||
|
||||
const existing = counts.get(url)
|
||||
if (existing) {
|
||||
counts.set(url, {
|
||||
label: existing.label ?? label,
|
||||
citationCount: existing.citationCount + 1,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
counts.set(url, {
|
||||
label,
|
||||
citationCount: 1,
|
||||
})
|
||||
}
|
||||
|
||||
return Array.from(counts.entries()).map(([url, value]) => ({
|
||||
url,
|
||||
label: value.label,
|
||||
citationCount: value.citationCount,
|
||||
}))
|
||||
}
|
||||
|
||||
function buildInlineCitationSourceLookup(
|
||||
platform: MonitoringQuestionDetailPlatform | null,
|
||||
): Map<string, MonitoringSourceItem> {
|
||||
@@ -1068,15 +1040,16 @@ function formatAnswerContent(platform: MonitoringQuestionDetailPlatform | null):
|
||||
return null
|
||||
}
|
||||
|
||||
const withInlineMarkers = isLinkedInlineCitationPlatform(platform?.ai_platform_id)
|
||||
? sanitized
|
||||
.replace(createQwenSourceGroupPattern(), (_, sourceGroupIndex) => {
|
||||
return buildInlineCitationMarker(Number(sourceGroupIndex), platform)
|
||||
})
|
||||
.replace(createYuanbaoCitationPattern(), (_, sourceGroupIndex) => {
|
||||
return buildInlineCitationMarker(Number(sourceGroupIndex), platform)
|
||||
})
|
||||
: sanitized
|
||||
let withInlineMarkers = sanitized
|
||||
if (isQwenInlineCitationPlatform(platform?.ai_platform_id)) {
|
||||
withInlineMarkers = sanitized.replace(createQwenSourceGroupPattern(), (_, sourceGroupIndex) => {
|
||||
return buildInlineCitationMarker(Number(sourceGroupIndex), platform)
|
||||
})
|
||||
} else if (isYuanbaoInlineCitationPlatform(platform?.ai_platform_id)) {
|
||||
withInlineMarkers = sanitized.replace(createYuanbaoCitationPattern(), (_, sourceGroupIndex) => {
|
||||
return buildInlineCitationMarker(Number(sourceGroupIndex), platform)
|
||||
})
|
||||
}
|
||||
|
||||
const normalizedMarkdown = withInlineMarkers
|
||||
.replace(createQwenSourceGroupStripPattern(), '')
|
||||
@@ -1139,41 +1112,11 @@ function collectDeepSeekInlineCitationOccurrences(
|
||||
}))
|
||||
}
|
||||
|
||||
function analyzeContentCitations(
|
||||
platform: MonitoringQuestionDetailPlatform | null,
|
||||
contentCitations: MonitoringQuestionContentCitation[],
|
||||
): TrackingAnalyzedContentCitation[] {
|
||||
const platformId = normalizeMonitoringPlatformId(platform?.ai_platform_id)
|
||||
const serverItems = contentCitations
|
||||
.filter((item) => normalizeMonitoringPlatformId(item.ai_platform_id) === platformId)
|
||||
.sort((left, right) => {
|
||||
if (right.citation_count !== left.citation_count) {
|
||||
return right.citation_count - left.citation_count
|
||||
}
|
||||
return left.article_title.localeCompare(right.article_title, 'zh-CN')
|
||||
})
|
||||
.map((item) => ({
|
||||
key: `server-${item.ai_platform_id}-${item.source_type}-${item.source_id}`,
|
||||
contentName: item.article_title || item.source_url || '--',
|
||||
channelName: item.publish_platform || deriveCitationChannelName(item.source_url),
|
||||
citationCount: item.citation_count,
|
||||
citationRate: item.citation_rate,
|
||||
citedURL: item.source_url || null,
|
||||
sourceType: item.source_type,
|
||||
}))
|
||||
|
||||
if (serverItems.length > 0) {
|
||||
return serverItems
|
||||
}
|
||||
|
||||
return analyzeInlineContentCitations(platform)
|
||||
}
|
||||
|
||||
function analyzeInlineContentCitations(
|
||||
function analyzeAnswerCitations(
|
||||
platform: MonitoringQuestionDetailPlatform | null,
|
||||
): TrackingAnalyzedContentCitation[] {
|
||||
const answerText = String(platform?.answer_text ?? '')
|
||||
if (!answerText) {
|
||||
if (!answerText || !supportsAnswerCitationTags(platform?.ai_platform_id)) {
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -1188,36 +1131,6 @@ function analyzeInlineContentCitations(
|
||||
return []
|
||||
}
|
||||
|
||||
return occurrences
|
||||
.sort((left, right) => {
|
||||
if (right.citationCount !== left.citationCount) {
|
||||
return right.citationCount - left.citationCount
|
||||
}
|
||||
return left.url.localeCompare(right.url, 'zh-CN')
|
||||
})
|
||||
.map((item) => ({
|
||||
key: `deepseek-${item.url}`,
|
||||
contentName: item.label || item.url,
|
||||
channelName: item.siteName || deriveCitationChannelName(item.url),
|
||||
citationCount: item.citationCount,
|
||||
citationRate: item.citationCount / totalCitationCount,
|
||||
citedURL: item.url,
|
||||
sourceType: null,
|
||||
}))
|
||||
}
|
||||
|
||||
if (isKimiInlineCitationPlatform(platform?.ai_platform_id)) {
|
||||
const occurrences = collectKimiInlineCitationOccurrences(answerText)
|
||||
if (!occurrences.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const totalCitationCount = occurrences.reduce((sum, item) => sum + item.citationCount, 0)
|
||||
if (!totalCitationCount) {
|
||||
return []
|
||||
}
|
||||
|
||||
const inlineCitationLookup = buildInlineCitationSourceLookup(platform)
|
||||
return occurrences
|
||||
.sort((left, right) => {
|
||||
if (right.citationCount !== left.citationCount) {
|
||||
@@ -1226,13 +1139,10 @@ function analyzeInlineContentCitations(
|
||||
return left.url.localeCompare(right.url, 'zh-CN')
|
||||
})
|
||||
.map((item) => {
|
||||
const source = inlineCitationLookup.get(item.url)
|
||||
const contentName = source?.title?.trim() || item.label || item.url
|
||||
const channelName = source?.site_name?.trim() || deriveCitationChannelName(item.url)
|
||||
return {
|
||||
key: `kimi-${item.url}`,
|
||||
contentName,
|
||||
channelName,
|
||||
key: `deepseek-${item.url}`,
|
||||
contentName: item.label || item.url,
|
||||
channelName: item.siteName || deriveCitationChannelName(item.url),
|
||||
citationCount: item.citationCount,
|
||||
citationRate: item.citationCount / totalCitationCount,
|
||||
citedURL: item.url,
|
||||
@@ -1241,11 +1151,10 @@ function analyzeInlineContentCitations(
|
||||
})
|
||||
}
|
||||
|
||||
if (!isLinkedInlineCitationPlatform(platform?.ai_platform_id)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const sourceGroupIndexes = collectInlineCitationIndexes(answerText)
|
||||
const sourceGroupIndexes = collectPlatformInlineCitationIndexes(
|
||||
answerText,
|
||||
platform?.ai_platform_id,
|
||||
)
|
||||
if (!sourceGroupIndexes.length) {
|
||||
return []
|
||||
}
|
||||
@@ -1557,39 +1466,49 @@ const contentCitationColumns = computed(() => [
|
||||
@click="openExternalURL(citation.cited_url)"
|
||||
@keydown.enter="openExternalURL(citation.cited_url)"
|
||||
>
|
||||
<div class="tracking-question-source-card__headline">
|
||||
<div class="tracking-question-source-card__indexes">
|
||||
<span
|
||||
v-for="label in resolveCitationIndexDisplayLabels(index, activePlatform)"
|
||||
:key="`${citation.cited_url}-${label}`"
|
||||
class="tracking-question-source-card__reference-badge"
|
||||
<div class="tracking-question-source-card__header">
|
||||
<div class="tracking-question-source-card__header-left">
|
||||
<div class="tracking-question-source-card__indexes">
|
||||
<span
|
||||
v-for="label in resolveCitationIndexDisplayLabels(index, activePlatform)"
|
||||
:key="`${citation.cited_url}-${label}`"
|
||||
class="tracking-question-source-card__reference-badge"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
<span
|
||||
v-if="shouldShowCitationSourceListIndex(index, activePlatform)"
|
||||
class="tracking-question-source-card__index"
|
||||
:class="{
|
||||
'tracking-question-source-card__index--secondary':
|
||||
resolveCitationIndexDisplayLabels(index, activePlatform).length > 0,
|
||||
}"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</span>
|
||||
</div>
|
||||
<strong class="tracking-question-source-card__site-name">{{ citation.site_name }}</strong>
|
||||
<a-tag
|
||||
v-if="isMediaSupplySubmissionCitation(citation)"
|
||||
color="cyan"
|
||||
class="tracking-question-source-card__badge"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
<span
|
||||
v-if="shouldShowCitationSourceListIndex(index, activePlatform)"
|
||||
class="tracking-question-source-card__index"
|
||||
:class="{
|
||||
'tracking-question-source-card__index--secondary':
|
||||
resolveCitationIndexDisplayLabels(index, activePlatform).length > 0,
|
||||
}"
|
||||
{{ t('tracking.mediaSupplySubmissionCitation') }}
|
||||
</a-tag>
|
||||
<a-tag
|
||||
v-else-if="citation.article_id"
|
||||
class="tracking-question-source-card__badge tracking-question-source-card__badge--published"
|
||||
>
|
||||
[{{ index + 1 }}]
|
||||
</span>
|
||||
{{ t('tracking.contentCitationBadge') }}
|
||||
</a-tag>
|
||||
<a-tag
|
||||
v-else-if="isManualMarkedCitation(citation)"
|
||||
color="green"
|
||||
class="tracking-question-source-card__badge"
|
||||
>
|
||||
{{ t('tracking.manualMarkedArticle') }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<strong>{{ citation.site_name }}</strong>
|
||||
<span
|
||||
v-if="resolveCitationTitle(citation)"
|
||||
class="tracking-question-source-card__divider"
|
||||
>
|
||||
·
|
||||
</span>
|
||||
<span
|
||||
class="tracking-question-source-card__title"
|
||||
:title="resolveCitationTitle(citation)"
|
||||
>
|
||||
{{ resolveCitationTitle(citation) }}
|
||||
</span>
|
||||
<div class="tracking-question-source-card__actions">
|
||||
<a-tooltip
|
||||
v-if="canMarkCitationAsExternal(citation)"
|
||||
@@ -1620,20 +1539,13 @@ const contentCitationColumns = computed(() => [
|
||||
</button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-tag
|
||||
v-if="citation.article_id"
|
||||
color="blue"
|
||||
class="tracking-question-source-card__badge"
|
||||
>
|
||||
{{ t('tracking.contentCitationBadge') }}
|
||||
</a-tag>
|
||||
<a-tag
|
||||
v-else-if="isManualMarkedCitation(citation)"
|
||||
color="green"
|
||||
class="tracking-question-source-card__badge"
|
||||
>
|
||||
{{ t('tracking.manualMarkedArticle') }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div
|
||||
v-if="resolveCitationTitle(citation)"
|
||||
class="tracking-question-source-card__title"
|
||||
:title="resolveCitationTitle(citation)"
|
||||
>
|
||||
{{ resolveCitationTitle(citation) }}
|
||||
</div>
|
||||
<div class="tracking-question-source-card__link">
|
||||
{{ citation.cited_url }}
|
||||
@@ -1711,7 +1623,7 @@ const contentCitationColumns = computed(() => [
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Content Citations -->
|
||||
<!-- Answer Citations -->
|
||||
<section v-if="shouldShowInlineContentCitations" class="tracking-question-card">
|
||||
<div class="tracking-question-card__header">
|
||||
<div class="tracking-question-card__section-title">
|
||||
@@ -1747,6 +1659,12 @@ const contentCitationColumns = computed(() => [
|
||||
<small v-if="record.sourceType === 'manual_mark'" class="meta-subtext">
|
||||
{{ t('tracking.manualMarkedArticle') }}
|
||||
</small>
|
||||
<small
|
||||
v-else-if="record.sourceType === 'media_supply_order_item'"
|
||||
class="meta-subtext"
|
||||
>
|
||||
{{ t('tracking.mediaSupplySubmissionCitation') }}
|
||||
</small>
|
||||
</template>
|
||||
<strong v-else class="table-text" :title="record.contentName">
|
||||
{{ record.contentName }}
|
||||
@@ -1805,11 +1723,24 @@ const contentCitationColumns = computed(() => [
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 24px 32px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e8edf5;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02);
|
||||
padding: 28px 32px;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 20px -2px rgba(15, 23, 42, 0.02);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tracking-question-page__hero::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -10%;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: radial-gradient(circle, rgba(59, 130, 246, 0.03) 0%, rgba(255, 255, 255, 0) 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tracking-question-page__header-top {
|
||||
@@ -1820,36 +1751,38 @@ const contentCitationColumns = computed(() => [
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
height: 32px;
|
||||
padding: 0 12px 0 8px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
gap: 8px;
|
||||
height: 36px;
|
||||
padding: 0 16px 0 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
color: #475569;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
margin-left: -8px;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.tracking-question-page__back:hover {
|
||||
background: #e2e8f0;
|
||||
border-color: #cbd5e1;
|
||||
color: #0f172a;
|
||||
background: #f8fafc;
|
||||
transform: translateX(-2px);
|
||||
}
|
||||
|
||||
.tracking-question-page__copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tracking-question-page__eyebrow {
|
||||
margin: 0;
|
||||
color: #2563eb;
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
@@ -1858,40 +1791,59 @@ const contentCitationColumns = computed(() => [
|
||||
.tracking-question-page__copy h1 {
|
||||
margin: 0;
|
||||
color: #0f172a;
|
||||
font-size: 32px;
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.02em;
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.tracking-question-page__meta {
|
||||
margin: 8px 0 0;
|
||||
margin: 4px 0 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
background: #f1f5f9;
|
||||
border-radius: 6px;
|
||||
border-radius: 8px;
|
||||
color: #475569;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
width: fit-content;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.tracking-question-page__alert {
|
||||
border-radius: 16px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.tracking-question-page__tabs-wrapper {
|
||||
background: #ffffff;
|
||||
padding: 4px 24px 0;
|
||||
border-radius: 16px;
|
||||
border: 1px solid #e8edf5;
|
||||
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02);
|
||||
padding: 0 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.tracking-question-tabs :deep(.ant-tabs-nav) {
|
||||
margin-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.tracking-question-tabs :deep(.ant-tabs-tab) {
|
||||
padding: 14px 16px;
|
||||
font-weight: 500;
|
||||
color: #475569;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.tracking-question-tabs :deep(.ant-tabs-tab-active) {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tracking-question-tabs :deep(.ant-tabs-ink-bar) {
|
||||
height: 3px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.tracking-question-tabs .is-muted {
|
||||
@@ -1901,8 +1853,10 @@ const contentCitationColumns = computed(() => [
|
||||
.tracking-question-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
|
||||
grid-auto-rows: 800px;
|
||||
gap: 20px;
|
||||
grid-auto-rows: calc(100vh - 280px);
|
||||
min-height: 550px;
|
||||
max-height: 750px;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.tracking-question-card {
|
||||
@@ -1910,10 +1864,10 @@ const contentCitationColumns = computed(() => [
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 24px 28px;
|
||||
border: 1px solid #e8edf5;
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(226, 232, 240, 0.8);
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.03);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.02), 0 10px 15px -3px rgba(0, 0, 0, 0.03), 0 0 0 1px rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
|
||||
.tracking-question-card--answer {
|
||||
@@ -1939,17 +1893,17 @@ const contentCitationColumns = computed(() => [
|
||||
.tracking-question-card__section-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
color: #111827;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
gap: 10px;
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tracking-question-card__accent {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 28px;
|
||||
border-radius: 999px;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
@@ -2093,7 +2047,9 @@ const contentCitationColumns = computed(() => [
|
||||
|
||||
.tracking-question-answer__headline h2 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.tracking-question-answer__meta {
|
||||
@@ -2102,15 +2058,16 @@ const contentCitationColumns = computed(() => [
|
||||
gap: 18px;
|
||||
margin-top: auto;
|
||||
padding-top: 18px;
|
||||
color: #9ca3af;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
border-top: 1px dashed #f1f5f9;
|
||||
}
|
||||
|
||||
.tracking-question-source-list,
|
||||
.tracking-question-content-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tracking-question-source-card,
|
||||
@@ -2118,43 +2075,61 @@ const contentCitationColumns = computed(() => [
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 12px 16px;
|
||||
gap: 8px;
|
||||
padding: 16px;
|
||||
padding-right: 76px;
|
||||
border: 1px solid #edf2f7;
|
||||
border-radius: 10px;
|
||||
background: #f8fbff;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
text-decoration: none;
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.tracking-question-source-card:hover,
|
||||
.tracking-question-content-card:hover {
|
||||
border-color: #dbeafe;
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.05);
|
||||
}
|
||||
|
||||
.tracking-question-source-card {
|
||||
padding-right: 58px;
|
||||
border-color: #3b82f6;
|
||||
background: #f8fafc;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 20px -8px rgba(59, 130, 246, 0.08), 0 4px 6px -2px rgba(59, 130, 246, 0.02);
|
||||
}
|
||||
|
||||
.tracking-question-source-card.is-linked {
|
||||
border-color: #93c5fd;
|
||||
background: #eef6ff;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
|
||||
border-color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
.tracking-question-source-card__headline {
|
||||
.tracking-question-source-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__site-name {
|
||||
color: #0f172a;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__indexes {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -2162,15 +2137,22 @@ const contentCitationColumns = computed(() => [
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 34px;
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
background: #e8f1ff;
|
||||
color: #1d4ed8;
|
||||
font-size: 12px;
|
||||
padding: 0 6px;
|
||||
border-radius: 6px;
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.tracking-question-source-card:hover .tracking-question-source-card__index {
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__index--secondary {
|
||||
@@ -2183,45 +2165,52 @@ const contentCitationColumns = computed(() => [
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 34px;
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
padding: 0 6px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #bfdbfe;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__headline strong {
|
||||
display: block;
|
||||
color: #2563eb;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__divider {
|
||||
color: #cbd5e1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__title {
|
||||
color: #475569;
|
||||
color: #334155;
|
||||
font-size: 14px;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
line-height: 1.45;
|
||||
word-break: break-all;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 20px;
|
||||
padding: 0 8px;
|
||||
margin: 0;
|
||||
margin-left: auto;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
font-size: 11px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tracking-question-source-card__badge--published {
|
||||
border: 1px solid #a7f3d0;
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.tracking-question-imitation-trigger {
|
||||
@@ -2231,22 +2220,19 @@ const contentCitationColumns = computed(() => [
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
color: #2563eb;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transform: translateY(1px);
|
||||
transition:
|
||||
opacity 0.18s ease,
|
||||
transform 0.18s ease,
|
||||
border-color 0.18s ease,
|
||||
background-color 0.18s ease;
|
||||
transform: scale(0.95);
|
||||
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.tracking-question-imitation-trigger:hover {
|
||||
border-color: #93c5fd;
|
||||
border-color: #2563eb;
|
||||
color: #2563eb;
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
@@ -2259,20 +2245,16 @@ const contentCitationColumns = computed(() => [
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 16px;
|
||||
transform: translateY(-50%);
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
transform: translateY(calc(-50% + 1px));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tracking-question-source-card:hover .tracking-question-imitation-trigger,
|
||||
.tracking-question-source-card:focus-within .tracking-question-imitation-trigger {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.tracking-question-source-card:hover .tracking-question-source-card__actions,
|
||||
.tracking-question-source-card:focus-within .tracking-question-source-card__actions {
|
||||
transform: translateY(-50%);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.tracking-question-imitation-trigger--table-action {
|
||||
@@ -2289,10 +2271,12 @@ const contentCitationColumns = computed(() => [
|
||||
.tracking-question-source-card__link {
|
||||
color: #94a3b8;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.tracking-question-content-card__copy a {
|
||||
@@ -2345,11 +2329,11 @@ const contentCitationColumns = computed(() => [
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
padding: 16px 24px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
:deep(.modern-table .ant-table-tbody > tr > td) {
|
||||
padding: 16px 24px;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
vertical-align: middle;
|
||||
transition: background-color 0.2s ease;
|
||||
@@ -2428,10 +2412,10 @@ const contentCitationColumns = computed(() => [
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
color: #0ea5e9;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
background: #f0f9ff;
|
||||
padding: 4px 10px;
|
||||
border-radius: 8px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e0f2fe;
|
||||
}
|
||||
|
||||
@@ -2547,9 +2531,29 @@ const contentCitationColumns = computed(() => [
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
@media (max-width: 1400px) {
|
||||
.tracking-question-grid {
|
||||
grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
|
||||
grid-auto-rows: calc(100vh - 300px);
|
||||
min-height: 500px;
|
||||
max-height: 650px;
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.tracking-question-grid {
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: auto;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.tracking-question-card {
|
||||
height: 550px;
|
||||
}
|
||||
|
||||
.tracking-question-card--span-2 {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.tracking-task-debug-grid,
|
||||
@@ -2564,11 +2568,12 @@ const contentCitationColumns = computed(() => [
|
||||
}
|
||||
|
||||
.tracking-question-page__copy h1 {
|
||||
font-size: 26px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.tracking-question-card {
|
||||
padding: 22px 18px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tracking-question-card__header--split,
|
||||
|
||||
@@ -771,7 +771,7 @@ function openQuestion(question: MonitoringHotQuestion): void {
|
||||
}
|
||||
|
||||
function openCitedArticle(item: MonitoringCitedArticle): void {
|
||||
if (item.source_type === 'manual_mark') {
|
||||
if (item.source_type === 'manual_mark' || item.source_type === 'media_supply_order_item') {
|
||||
openExternalURL(item.source_url)
|
||||
return
|
||||
}
|
||||
@@ -1067,12 +1067,16 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
v-if="formatDelta(card.value, card.previous)"
|
||||
:class="[
|
||||
'metric-card__delta',
|
||||
(card.value ?? 0) >= (card.previous ?? 0)
|
||||
(card.value ?? 0) > (card.previous ?? 0)
|
||||
? 'metric-card__delta--up'
|
||||
: 'metric-card__delta--down',
|
||||
: (card.value ?? 0) < (card.previous ?? 0)
|
||||
? 'metric-card__delta--down'
|
||||
: 'metric-card__delta--flat',
|
||||
]"
|
||||
>
|
||||
{{ formatDelta(card.value, card.previous) }}
|
||||
<span v-if="(card.value ?? 0) > (card.previous ?? 0)" class="trend-arrow">↑</span>
|
||||
<span v-else-if="(card.value ?? 0) < (card.previous ?? 0)" class="trend-arrow">↓</span>
|
||||
{{ (formatDelta(card.value, card.previous) ?? '').replace(/[+-]/, '') }}
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
@@ -1133,10 +1137,6 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
<div class="tracking-panel__header">
|
||||
<div>
|
||||
<h3 class="panel-title">AI 平台状态</h3>
|
||||
<span class="tracking-panel__helper">
|
||||
只读展示 desktop-client
|
||||
的绑定、授权和当前采样状态。授权入口放在桌面端,抓取过程静默执行。
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1145,6 +1145,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
v-for="platform in aiPlatformStatusCards"
|
||||
:key="platform.id"
|
||||
class="ai-platform-status-card"
|
||||
:style="{ '--platform-accent': platform.accent }"
|
||||
>
|
||||
<div class="ai-platform-status-card__head">
|
||||
<div class="ai-platform-status-card__identity">
|
||||
@@ -1354,7 +1355,6 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
<div class="tracking-panel__header tracking-panel__header--list">
|
||||
<div class="tracking-panel__header-left">
|
||||
<h3 class="panel-title">{{ t('tracking.hotQuestionsTitle') }}</h3>
|
||||
<span class="tracking-panel__helper">{{ t('tracking.hotQuestionsHint') }}</span>
|
||||
</div>
|
||||
<a-input
|
||||
v-model:value="hotQuestionSearch"
|
||||
@@ -1460,6 +1460,8 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
{{
|
||||
item.source_type === 'manual_mark'
|
||||
? t('tracking.manualMarkedArticle')
|
||||
: item.source_type === 'media_supply_order_item'
|
||||
? t('tracking.mediaSupplySubmissionCitation')
|
||||
: item.publish_platform
|
||||
}}
|
||||
</span>
|
||||
@@ -1594,8 +1596,16 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid #e6edf5;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfdff 100%);
|
||||
border: 1px solid #e2e8f0;
|
||||
background: #ffffff;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.ai-platform-status-card:hover {
|
||||
border-color: var(--platform-accent) !important;
|
||||
box-shadow: 0 10px 20px -8px var(--platform-accent);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.ai-platform-status-card__head {
|
||||
@@ -1613,27 +1623,28 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
|
||||
.ai-platform-status-card__identity strong {
|
||||
display: block;
|
||||
color: #111827;
|
||||
font-size: 16px;
|
||||
color: #0f172a;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.ai-platform-status-card__identity p {
|
||||
margin: 6px 0 0;
|
||||
color: #667085;
|
||||
margin: 4px 0 0;
|
||||
color: #64748b;
|
||||
line-height: 1.5;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ai-platform-status-card__badge {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 14px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -1649,18 +1660,19 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.ai-platform-status-card__row span {
|
||||
color: #667085;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ai-platform-status-card__row strong {
|
||||
color: #111827;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
text-align: right;
|
||||
word-break: break-all;
|
||||
@@ -1699,9 +1711,11 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tracking-panel {
|
||||
border-radius: 12px;
|
||||
:deep(.tracking-panel.ant-card) {
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(226, 232, 240, 0.8) !important;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.02), 0 10px 15px -3px rgba(0, 0, 0, 0.03), 0 0 0 1px rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
|
||||
.tracking-panel--citation {
|
||||
@@ -1718,6 +1732,8 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
|
||||
.tracking-panel__header-left {
|
||||
@@ -1731,9 +1747,9 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
|
||||
.panel-title {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
color: #111827;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #0f172a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -1743,9 +1759,9 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background: linear-gradient(180deg, #3b82f6 0%, #1d4ed8 100%);
|
||||
border-radius: 4px;
|
||||
margin-right: 10px;
|
||||
background: #2563eb;
|
||||
border-radius: 2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.tracking-panel__description {
|
||||
@@ -1818,43 +1834,69 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
background: #f7f9fc;
|
||||
border: 1px solid #f0f3fa;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
padding: 20px;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.metric-card:hover {
|
||||
border-color: #3b82f6;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.05), 0 4px 6px -2px rgba(59, 130, 246, 0.02);
|
||||
}
|
||||
|
||||
.metric-card__label {
|
||||
margin: 0;
|
||||
color: #8c8c8c;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.metric-card__value-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-top: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.metric-card__value-row strong {
|
||||
font-size: 24px;
|
||||
font-weight: 800;
|
||||
color: #141414;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
}
|
||||
|
||||
.metric-card__delta {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
}
|
||||
|
||||
.metric-card__delta--up {
|
||||
color: #15803d;
|
||||
color: #16a34a;
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #bbf7d0;
|
||||
}
|
||||
|
||||
.metric-card__delta--down {
|
||||
color: #dc2626;
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
}
|
||||
|
||||
.metric-card__delta--flat {
|
||||
color: #475569;
|
||||
background: #f1f5f9;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.platform-table,
|
||||
@@ -1876,19 +1918,27 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
|
||||
.platform-table__head,
|
||||
.citation-table__head {
|
||||
background: #fafafa;
|
||||
color: #8c8c8c;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: #f8fafc;
|
||||
color: #64748b;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.platform-table__row,
|
||||
.citation-table__row {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f9f9f9;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
background: #ffffff;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.platform-table__row:hover,
|
||||
.citation-table__row:hover {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.platform-table__row:last-child,
|
||||
@@ -2043,7 +2093,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
border-radius: 12px;
|
||||
border: 1px solid #f0f3fa;
|
||||
background: #ffffff;
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.citation-ranking-sheet__head,
|
||||
@@ -2475,19 +2525,51 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
@media (max-width: 1400px) {
|
||||
.citation-ranking-layout {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.citation-ranking-visual {
|
||||
flex-direction: row;
|
||||
gap: 32px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.citation-ranking-legend {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.tracking-grid--top,
|
||||
.tracking-grid--middle,
|
||||
.tracking-grid--middle {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.citation-ranking-visual {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.citation-ranking-legend {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.tracking-grid--bottom,
|
||||
.detail-grid,
|
||||
.detail-grid--bottom {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.citation-ranking-layout {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.citation-ranking-visual {
|
||||
min-height: auto;
|
||||
padding: 0;
|
||||
|
||||
Reference in New Issue
Block a user