11import { Check , MessageCircle , Plus , Search , Trash2 , X } from 'lucide-react'
2- import { useEffect , useState } from 'react'
2+ import { useEffect , useRef , useState } from 'react'
33
44import { Button } from '@/components/ui/button'
55import { Input } from '@/components/ui/input'
@@ -46,6 +46,7 @@ export function JargonManagementPage() {
4646 const [ page , setPage ] = useState ( 1 )
4747 const [ pageSize , setPageSize ] = useState ( 20 )
4848 const [ search , setSearch ] = useState ( '' )
49+ const [ debouncedSearch , setDebouncedSearch ] = useState ( '' )
4950 const [ scopeFilter , setScopeFilter ] = useState < 'all' | 'global' | 'local' > ( 'all' )
5051 const [ filterChatId , setFilterChatId ] = useState < string > ( 'all' )
5152 const [ filterIsJargon , setFilterIsJargon ] = useState < string > ( 'all' )
@@ -68,30 +69,41 @@ export function JargonManagementPage() {
6869 } )
6970 const [ chatList , setChatList ] = useState < JargonChatInfo [ ] > ( [ ] )
7071 const [ formChatList , setFormChatList ] = useState < JargonChatInfo [ ] > ( [ ] )
72+ const jargonListRequestSeqRef = useRef ( 0 )
7173 const { toast } = useToast ( )
7274
7375 // 加载黑话列表
7476 const loadJargons = async ( ) => {
77+ const requestSeq = jargonListRequestSeqRef . current + 1
78+ jargonListRequestSeqRef . current = requestSeq
7579 try {
7680 setLoading ( true )
7781 const response = await getJargonList ( {
7882 page,
7983 page_size : pageSize ,
80- search : search || undefined ,
84+ search : debouncedSearch || undefined ,
8185 session_id : scopeFilter !== 'global' && filterChatId !== 'all' ? filterChatId : undefined ,
8286 is_jargon : filterIsJargon === 'all' ? undefined : filterIsJargon === 'true' ? true : filterIsJargon === 'false' ? false : undefined ,
8387 is_global : scopeFilter === 'all' ? undefined : scopeFilter === 'global' ,
8488 } )
89+ if ( requestSeq !== jargonListRequestSeqRef . current ) {
90+ return
91+ }
8592 setJargons ( response . data )
8693 setTotal ( response . total )
8794 } catch ( error ) {
95+ if ( requestSeq !== jargonListRequestSeqRef . current ) {
96+ return
97+ }
8898 toast ( {
8999 title : '加载失败' ,
90100 description : error instanceof Error ? error . message : '无法加载黑话列表' ,
91101 variant : 'destructive' ,
92102 } )
93103 } finally {
94- setLoading ( false )
104+ if ( requestSeq === jargonListRequestSeqRef . current ) {
105+ setLoading ( false )
106+ }
95107 }
96108 }
97109
@@ -125,12 +137,27 @@ export function JargonManagementPage() {
125137 }
126138 }
127139
140+ useEffect ( ( ) => {
141+ const timerId = window . setTimeout ( ( ) => {
142+ const normalizedSearch = search . trim ( )
143+ setDebouncedSearch ( ( current ) => ( current === normalizedSearch ? current : normalizedSearch ) )
144+ setPage ( ( current ) => ( current === 1 ? current : 1 ) )
145+ setSelectedIds ( ( current ) => ( current . size === 0 ? current : new Set < number > ( ) ) )
146+ } , 300 )
147+
148+ return ( ) => window . clearTimeout ( timerId )
149+ } , [ search ] )
150+
128151 useEffect ( ( ) => {
129152 loadJargons ( )
153+ // eslint-disable-next-line react-hooks/exhaustive-deps
154+ } , [ page , pageSize , debouncedSearch , scopeFilter , filterChatId , filterIsJargon ] )
155+
156+ useEffect ( ( ) => {
130157 loadStats ( )
131158 loadChatList ( )
132159 // eslint-disable-next-line react-hooks/exhaustive-deps
133- } , [ page , pageSize , search , scopeFilter , filterChatId , filterIsJargon ] )
160+ } , [ ] )
134161
135162 // 查看详情
136163 const handleViewDetail = async ( jargon : Jargon ) => {
@@ -332,7 +359,7 @@ export function JargonManagementPage() {
332359 < Search className = "absolute left-2.5 top-2 h-4 w-4 text-muted-foreground" />
333360 < Input
334361 id = "search"
335- placeholder = "搜索内容、含义 ..."
362+ placeholder = "搜索黑话内容 ..."
336363 value = { search }
337364 onChange = { ( e ) => setSearch ( e . target . value ) }
338365 className = "h-8 pl-9"
0 commit comments