import { useEffect, useMemo, useRef, useState } from 'react'
import ErrorState from '../../components/ErrorState.jsx'
import LoadingState from '../../components/LoadingState.jsx'
import DecodeKnowledgeModal from '../decode/DecodeKnowledgeModal.jsx'
import AxisColumn from './AxisColumn.jsx'
import ManualQueryModal from './ManualQueryModal.jsx'
import QueryColumn from './QueryColumn.jsx'
import SearchResultColumn from './SearchResultColumn.jsx'
import TopicTableQueryPanel from './TopicTableQueryPanel.jsx'
import { useLatestQueryDetail, useQueryBoard } from './useQueryBoard.js'
import { isQuerySearched } from './model.js'
function selectedQueryPayload(queryText, latest) {
if (!latest?.query_id) return null
return {
query: queryText,
query_id: latest.query_id,
detail_version: [
latest.candidate_count || 0,
latest.creation_hit_count || 0,
latest.decoded_count || 0,
latest.payload_count || 0,
].join(':'),
}
}
function manualFamilyFromBoard(board) {
const rows = (board?.queries || []).filter((row) => row.family_key === 'manual')
return {
key: 'manual',
label: '手动 Query',
axes: [],
items: rows.map((row, index) => ({
query: row.query_text,
parts: {},
keep: true,
reason: row.filter_reason || '',
sort_order: row.sort_order ?? index,
})),
}
}
function topicTableFamily() {
return {
key: 'topic_table',
label: '选题表生成',
axes: [],
items: [],
}
}
export default function QueryBoardPage() {
const {
preview,
board,
latestByQuery,
loading,
error,
lastUpdatedAt,
refreshBoard,
} = useQueryBoard()
const [activeKey, setActiveKey] = useState('f1')
const [selectedQuery, setSelectedQuery] = useState(null)
const [decodeItemId, setDecodeItemId] = useState('')
const [manualMode, setManualMode] = useState('')
const didSetDefaultTab = useRef(false)
const families = useMemo(() => {
const base = preview?.families || []
const manual = manualFamilyFromBoard(board)
return [...base, manual, topicTableFamily()]
}, [board, preview])
const family = families.find((row) => row.key === activeKey) || families[0] || { axes: [], items: [] }
const familyItems = family.items || []
const familyRunCount = familyItems.filter((item) => isQuerySearched(latestByQuery.get(item.query))).length
const totalRunCount = families.reduce((count, row) => {
return count + (row.items || []).filter((item) => isQuerySearched(latestByQuery.get(item.query))).length
}, 0)
const totalItemCount = families.reduce((sum, row) => sum + (row.items || []).length, 0)
const detailState = useLatestQueryDetail(selectedQuery)
const lastUpdatedText = useMemo(() => {
return lastUpdatedAt ? lastUpdatedAt.toLocaleTimeString('zh-CN', { hour12: false }) : ''
}, [lastUpdatedAt])
useEffect(() => {
if (!didSetDefaultTab.current && (window.location.hash || '#/') === '#/' && families.some((row) => row.key === 'f1')) {
didSetDefaultTab.current = true
setActiveKey('f1')
}
}, [families])
useEffect(() => {
const firstKey = families[0]?.key
if (firstKey && !families.some((row) => row.key === activeKey) && preview) {
setActiveKey(firstKey)
}
}, [families, activeKey, preview])
useEffect(() => {
if (!familyItems.length) {
if (selectedQuery) setSelectedQuery(null)
return
}
if (selectedQuery && familyItems.some((item) => item.query === selectedQuery.query)) {
const latest = latestByQuery.get(selectedQuery.query)
const next = selectedQueryPayload(selectedQuery.query, latest)
if (next && (next.query_id !== selectedQuery.query_id || next.detail_version !== selectedQuery.detail_version)) {
setSelectedQuery(next)
}
return
}
const first = familyItems.find((item) => isQuerySearched(latestByQuery.get(item.query)))
if (first) {
const latest = latestByQuery.get(first.query)
setSelectedQuery(selectedQueryPayload(first.query, latest))
} else {
setSelectedQuery(null)
}
}, [activeKey, board, familyItems, latestByQuery, selectedQuery])
if (error) return