| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import { Button, Empty, Space, Tooltip, Typography } from 'antd'
- import { ThunderboltOutlined } from '@ant-design/icons'
- import type { AIUnderstandingVO } from '../api/types'
- import { ACTIVE_PARENT_BTN_STYLE, DISABLED_PARENT_BTN_STYLE } from './DeconstructTree'
- const { Paragraph, Text } = Typography
- interface Props {
- data: AIUnderstandingVO | null
- loading?: boolean
- /** 后端字典: 仅当对应 configCode 在字典里时, "以此召回"按钮才生效 */
- configCodes: Record<string, string>
- onRecallByText: (text: string, configCodeOverride?: string) => void
- }
- /**
- * 字段 → configCode 映射
- * 4 个 RESULT_LOG_* 维度对应内容理解的 4 行
- */
- const ROW_CODE: Array<{ label: string; field: keyof AIUnderstandingVO; code: string }> = [
- { label: '内容选题', field: 'contentTopic', code: 'RESULT_LOG_TOPIC' },
- { label: '视频主题', field: 'videoTheme', code: 'RESULT_LOG_THEME' },
- { label: '视频关键词', field: 'videoKeywords', code: 'RESULT_LOG_KEYWORDS' },
- { label: '视频口播', field: 'videoNarration', code: 'RESULT_LOG_NARRATION' },
- ]
- /**
- * 视频内容理解-旧 (RESULT_LOG_* 维度)
- *
- * 数据源: video:detail Redis (loghubods.video_dimension_detail_add_column 同步而来)
- * 视频口播 字段不在 ODPS 维度表里, 始终为 null → 按钮 disabled
- */
- export default function AIUnderstandingPanel({ data, loading, configCodes, onRecallByText }: Props) {
- if (loading) return <div>加载中...</div>
- if (!data) return <Empty description="准备中" image={Empty.PRESENTED_IMAGE_SIMPLE} />
- const rows = ROW_CODE.map(({ label, field, code }) => ({
- label,
- code,
- value: ((data[field] as string | undefined | null) ?? '').toString().trim(),
- }))
- if (rows.every((r) => !r.value)) {
- return <Empty description="该视频AI理解结果为空" />
- }
- return (
- <Space direction="vertical" size={8} style={{ width: '100%' }}>
- {rows.map(({ label, value, code }) => {
- const dictHas = code in configCodes
- const supported = dictHas && !!value
- const tip = !dictHas
- ? `当前未启用"${label}"维度向量召回 (${code} 不在后端字典)`
- : !value
- ? '该字段无内容,无法召回'
- : ''
- const btn = supported ? (
- <Button
- type="primary"
- icon={<ThunderboltOutlined />}
- onClick={() => onRecallByText(value, code)}
- style={ACTIVE_PARENT_BTN_STYLE}
- >
- 以此召回
- </Button>
- ) : (
- <Tooltip title={tip}>
- <Button disabled icon={<ThunderboltOutlined />} style={DISABLED_PARENT_BTN_STYLE}>
- 以此召回
- </Button>
- </Tooltip>
- )
- return (
- <div
- key={label}
- style={{
- display: 'flex',
- alignItems: 'center',
- gap: 12,
- padding: '8px 12px',
- border: value ? '1px solid #ffd591' : '1px solid #e8e8e8',
- background: value ? '#fff7e6' : '#fafafa',
- borderRadius: 6,
- }}
- >
- <Text strong style={{ minWidth: 76, fontSize: 12, color: '#d46b08', flexShrink: 0 }}>
- {label}
- </Text>
- <div style={{ flex: 1, minWidth: 0, fontSize: 13 }}>
- {value ? (
- <Paragraph
- style={{ marginBottom: 0 }}
- ellipsis={{ rows: 3, tooltip: value }}
- >
- {value}
- </Paragraph>
- ) : (
- <Text type="secondary">-</Text>
- )}
- </div>
- {btn}
- </div>
- )
- })}
- {data.dt && (
- <Text type="secondary" style={{ fontSize: 11 }}>
- 数据分区: {data.dt}
- </Text>
- )}
- </Space>
- )
- }
|