diff --git a/web/frontend/src/views/ScoresView.vue b/web/frontend/src/views/ScoresView.vue index 0631f19..2e88785 100644 --- a/web/frontend/src/views/ScoresView.vue +++ b/web/frontend/src/views/ScoresView.vue @@ -74,6 +74,40 @@ function signalIcon(s: string) { return '' } +// AI 分析 +const aiLoading = ref(false) +const aiContent = ref('') +const aiError = ref('') +let aiES: EventSource | null = null + +function closeAI() { + aiES?.close() + aiES = null + aiLoading.value = false +} + +async function askAI() { + if (!scoreResult.value) return + closeAI() + aiLoading.value = true + aiContent.value = '' + aiError.value = '' + + const ts = encodeURIComponent(scoreResult.value.ts_code) + const td = encodeURIComponent(scoreResult.value.trade_date) + aiES = new EventSource(`/api/v1/ai/analyze?ts_code=${ts}&trade_date=${td}`) + aiES.addEventListener('token', (e) => { aiContent.value += e.data }) + aiES.addEventListener('error', (e) => { + aiError.value = (e as any)?.data || '请求失败' + closeAI() + }) + aiES.addEventListener('done', () => closeAI()) + aiES.onerror = () => { + if (!aiContent.value) aiError.value = '连接中断' + closeAI() + } +} + // 历史查询(折叠) const showHistory = ref(false) const historyFilter = reactive<{ @@ -325,6 +359,36 @@ onMounted(async () => { .result-card { margin-top: 4px; } +.ai-section { + margin-top: 12px; +} +.ai-card { + border: 1px solid var(--el-border-color); + border-radius: 6px; + margin-top: 8px; + overflow: hidden; +} +.ai-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 12px; + background: var(--el-fill-color-light); + font-weight: 600; +} +.ai-body { + padding: 12px; +} +.ai-text { + line-height: 1.8; + white-space: pre-wrap; +} +.ai-error { + color: var(--el-color-danger); +} +.ai-loading { + color: var(--el-text-color-secondary); +} .history-header { display: flex; align-items: center;