|
|
@@ -35,6 +35,7 @@ import {
|
|
|
getVideoDetail,
|
|
|
matchByText,
|
|
|
} from '../api/recall'
|
|
|
+import { buildGroupedConfigOptions, useConfigCodes } from '../api/configCodes'
|
|
|
import type {
|
|
|
AIUnderstandingVO,
|
|
|
DeconstructPointsVO,
|
|
|
@@ -61,12 +62,12 @@ function readUrlQueryText(): string | null {
|
|
|
return trimmed.length > 0 ? trimmed : null
|
|
|
}
|
|
|
|
|
|
-/** 从 URL ?configCode=xxx 读取并校验,只接受 CONFIG_OPTIONS 内的值,无效或缺省返 null */
|
|
|
+/** 从 URL ?configCode=xxx 读取,后端字典动态加载,这里只做形态校验(非空+大写) */
|
|
|
function readUrlConfigCode(): string | null {
|
|
|
const raw = new URLSearchParams(window.location.search).get('configCode')
|
|
|
if (!raw) return null
|
|
|
const upper = raw.trim().toUpperCase()
|
|
|
- return CONFIG_OPTIONS.some((o) => o.value === upper) ? upper : null
|
|
|
+ return upper.length > 0 ? upper : null
|
|
|
}
|
|
|
|
|
|
/** 从召回结果里剔除指定视频ID, 同时刷新 modality 计数 */
|
|
|
@@ -82,11 +83,6 @@ function filterOutSelf(data: RecallResultVO, excludeId: number | null): RecallRe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const CONFIG_OPTIONS = [
|
|
|
- { label: '选题', value: 'VIDEO_TOPIC' },
|
|
|
- { label: '灵感点', value: 'VIDEO_INSPIRATION' },
|
|
|
-]
|
|
|
-
|
|
|
export default function RecallTestPage() {
|
|
|
// URL 上有 queryText → 默认进入 Tab2 (优先级高于 videoId,与 Grafana 跳转用例一致)
|
|
|
// 用 defaultActiveKey 而非受控 activeKey,保留用户后续手动切 Tab 的自由
|
|
|
@@ -156,6 +152,7 @@ function VideoIdTab() {
|
|
|
const [points, setPoints] = useState<DeconstructPointsVO | null>(null)
|
|
|
const [loadingMain, setLoadingMain] = useState(false)
|
|
|
const [queried, setQueried] = useState(false)
|
|
|
+ const configCodes = useConfigCodes()
|
|
|
|
|
|
/** 视频Tab 不再有顶部维度选择, 维度由解构层级里每条点的"以此召回"按钮直接传入 */
|
|
|
const [topN, setTopN] = useState<number>(10)
|
|
|
@@ -213,10 +210,7 @@ function VideoIdTab() {
|
|
|
const finalConfigCode = configCodeOverride || 'VIDEO_TOPIC'
|
|
|
setLoadingRecall(true)
|
|
|
const preview = trimmed.length > 24 ? trimmed.slice(0, 24) + '…' : trimmed
|
|
|
- const codeLabel =
|
|
|
- finalConfigCode === 'VIDEO_TOPIC' ? '选题'
|
|
|
- : finalConfigCode === 'VIDEO_INSPIRATION' ? '灵感点'
|
|
|
- : finalConfigCode
|
|
|
+ const codeLabel = configCodes[finalConfigCode] ?? finalConfigCode
|
|
|
setRecallMeta({
|
|
|
dimensionLabel: codeLabel,
|
|
|
dimensionCode: finalConfigCode,
|
|
|
@@ -232,7 +226,7 @@ function VideoIdTab() {
|
|
|
setLoadingRecall(false)
|
|
|
}
|
|
|
},
|
|
|
- [topN, videoId],
|
|
|
+ [topN, videoId, configCodes],
|
|
|
)
|
|
|
|
|
|
/** URL 传入 videoId 时, 首次查询结束后自动按"选题"维度召回 (0 点击) */
|
|
|
@@ -394,7 +388,7 @@ function DetailRow({
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-/** 召回结果卡片标题: 维度Tag突出在前, 描述文字跟在后 */
|
|
|
+/** 召回结果卡片标题: "召回维度:[中文标签]" + 描述 */
|
|
|
function RecallTitle({
|
|
|
meta,
|
|
|
}: {
|
|
|
@@ -408,17 +402,19 @@ function RecallTitle({
|
|
|
</Space>
|
|
|
)
|
|
|
}
|
|
|
- // 不同维度配色
|
|
|
- const palette =
|
|
|
- meta.dimensionCode === 'VIDEO_TOPIC'
|
|
|
+ // 按 configCode 前缀走两套配色
|
|
|
+ const palette = meta.dimensionCode.startsWith('RESULT_LOG_')
|
|
|
+ ? { bg: '#fff7e6', border: '#ffd591', text: '#d46b08' }
|
|
|
+ : meta.dimensionCode === 'VIDEO_TOPIC'
|
|
|
? { bg: '#f9f0ff', border: '#d3adf7', text: '#531dab' }
|
|
|
: meta.dimensionCode === 'VIDEO_INSPIRATION'
|
|
|
? { bg: '#e6f4ff', border: '#91caff', text: '#0958d9' }
|
|
|
: { bg: '#f6ffed', border: '#b7eb8f', text: '#389e0d' }
|
|
|
|
|
|
return (
|
|
|
- <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
|
|
|
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
|
|
|
<SearchOutlined style={{ color: '#722ed1', fontSize: 16 }} />
|
|
|
+ <span style={{ fontSize: 14, color: 'rgba(0,0,0,0.65)' }}>召回维度:</span>
|
|
|
<span
|
|
|
style={{
|
|
|
background: palette.bg,
|
|
|
@@ -433,7 +429,6 @@ function RecallTitle({
|
|
|
>
|
|
|
{meta.dimensionLabel}
|
|
|
</span>
|
|
|
- <span style={{ color: 'rgba(0,0,0,0.45)', fontSize: 13 }}>维度召回</span>
|
|
|
<span style={{ color: 'rgba(0,0,0,0.65)', fontSize: 13 }}>· {meta.description}</span>
|
|
|
</div>
|
|
|
)
|
|
|
@@ -452,6 +447,8 @@ function TextRecallTab() {
|
|
|
const [topN, setTopN] = useState<number>(10)
|
|
|
const [result, setResult] = useState<RecallResultVO | null>(null)
|
|
|
const [loading, setLoading] = useState(false)
|
|
|
+ const configCodes = useConfigCodes()
|
|
|
+ const groupedOptions = buildGroupedConfigOptions(configCodes)
|
|
|
|
|
|
const onSubmit = useCallback(async () => {
|
|
|
if (!queryText.trim()) {
|
|
|
@@ -492,7 +489,7 @@ function TextRecallTab() {
|
|
|
/>
|
|
|
<Space wrap>
|
|
|
<Text strong>召回维度</Text>
|
|
|
- <Select value={configCode} onChange={setConfigCode} options={CONFIG_OPTIONS} style={{ width: 220 }} />
|
|
|
+ <Select value={configCode} onChange={setConfigCode} options={groupedOptions} style={{ width: 240 }} />
|
|
|
<Text strong>TopN</Text>
|
|
|
<InputNumber min={1} max={100} value={topN} onChange={(v) => setTopN(v ?? 10)} style={{ width: 80 }} />
|
|
|
<Button type="primary" icon={<SearchOutlined />} loading={loading} onClick={onSubmit}>
|