fix 文档管理模块 & 法规对话模块

This commit is contained in:
2026-05-20 23:34:08 +08:00
parent c22b03dc07
commit b065d55c86
39 changed files with 1671 additions and 540 deletions

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
import { useTheme } from '../../contexts';
import type { ChatMessage, RetrievalData } from '../../types';
import { getQuickQuestions, ragChat } from '../../api/rag';
import { CitedAnswer } from './CitedAnswer';
const ragQuickQuestionsDefault = [
'电动自行车上路需要什么条件?',
@@ -24,6 +25,8 @@ export const RagChatPage: React.FC = () => {
const [showClearConfirm, setShowClearConfirm] = useState<boolean>(false);
const [selectedRetrieval, setSelectedRetrieval] = useState<RetrievalData | null>(null);
const [quickQuestions, setQuickQuestions] = useState<string[]>(ragQuickQuestionsDefault);
const [filterRegulationType, setFilterRegulationType] = useState<string>('');
const [highlightedSourceIdx, setHighlightedSourceIdx] = useState<number | null>(null);
function nextMessageId() {
const currentId = nextMessageIdRef.current;
@@ -55,8 +58,10 @@ export const RagChatPage: React.FC = () => {
setInput('');
setLoading(true);
setRetrievals([]);
setHighlightedSourceIdx(null);
let currentResponse = '';
const activeFilters = filterRegulationType.trim() || undefined;
void ragChat(
text,
@@ -112,7 +117,8 @@ export const RagChatPage: React.FC = () => {
},
() => {
setLoading(false);
}
},
activeFilters
);
};
@@ -130,8 +136,10 @@ export const RagChatPage: React.FC = () => {
setLoading(true);
setMessages((prev) => [...prev.slice(0, -1)]);
setRetrievals([]);
setHighlightedSourceIdx(null);
let currentResponse = '';
const activeFilters = filterRegulationType.trim() || undefined;
void ragChat(
lastUserMsg.content,
@@ -185,7 +193,8 @@ export const RagChatPage: React.FC = () => {
},
() => {
setLoading(false);
}
},
activeFilters
);
};
@@ -267,7 +276,17 @@ export const RagChatPage: React.FC = () => {
whiteSpace: 'pre-wrap',
border: msg.role === 'assistant' ? `1px solid ${theme.border}` : 'none',
}}>
{msg.content}
{msg.role === 'assistant' ? (
<CitedAnswer
text={msg.content}
sources={retrievals}
onCiteClick={(idx) => {
setHighlightedSourceIdx(idx);
const el = document.getElementById(`source-${idx}`);
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
}}
/>
) : msg.content}
{msg.role === 'assistant' && msg.retrievalIds && msg.retrievalIds.length > 0 && (
<div style={{
marginTop: 10,
@@ -331,6 +350,31 @@ export const RagChatPage: React.FC = () => {
background: theme.bg,
borderTop: `1px solid ${theme.border}`,
}}>
<div style={{
display: 'flex',
gap: 8,
marginBottom: 10,
alignItems: 'center',
}}>
<span className="mono" style={{ fontSize: 11, color: theme.text3, whiteSpace: 'nowrap' }}></span>
<input
value={filterRegulationType}
onChange={(e) => setFilterRegulationType(e.target.value)}
placeholder="如: GB / UN-ECE / IATF留空不过滤"
style={{
flex: 1,
maxWidth: 280,
padding: '5px 10px',
fontSize: 12,
background: theme.bgHover,
border: `1px solid ${theme.border}`,
borderRadius: 6,
color: theme.text,
outline: 'none',
}}
/>
</div>
<div style={{
display: 'flex',
gap: 8,
@@ -468,14 +512,16 @@ export const RagChatPage: React.FC = () => {
{retrievals.map((r, i) => (
<div
key={r.id}
id={`source-${i + 1}`}
onClick={() => setSelectedRetrieval(r)}
style={{
padding: 16,
background: theme.bgHover,
background: highlightedSourceIdx === i + 1 ? theme.bgElevated : theme.bgHover,
borderRadius: 10,
border: `1px solid ${theme.border}`,
border: `1px solid ${highlightedSourceIdx === i + 1 ? theme.accent : theme.border}`,
cursor: 'pointer',
position: 'relative',
transition: 'border-color 0.2s, background 0.2s',
}}
>
<div style={{