mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
聊天页面新增导出按钮
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'
|
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'
|
||||||
import { Search, MessageSquare, AlertCircle, Loader2, RefreshCw, X, ChevronDown, Info, Calendar, Database, Hash, Play, Pause, Image as ImageIcon, Link, Mic, CheckCircle, Copy, Check } from 'lucide-react'
|
import { Search, MessageSquare, AlertCircle, Loader2, RefreshCw, X, ChevronDown, Info, Calendar, Database, Hash, Play, Pause, Image as ImageIcon, Link, Mic, CheckCircle, Copy, Check, Download } from 'lucide-react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { createPortal } from 'react-dom'
|
import { createPortal } from 'react-dom'
|
||||||
import { useChatStore } from '../stores/chatStore'
|
import { useChatStore } from '../stores/chatStore'
|
||||||
import { useBatchTranscribeStore } from '../stores/batchTranscribeStore'
|
import { useBatchTranscribeStore } from '../stores/batchTranscribeStore'
|
||||||
@@ -117,6 +118,8 @@ const SessionItem = React.memo(function SessionItem({
|
|||||||
|
|
||||||
|
|
||||||
function ChatPage(_props: ChatPageProps) {
|
function ChatPage(_props: ChatPageProps) {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isConnected,
|
isConnected,
|
||||||
isConnecting,
|
isConnecting,
|
||||||
@@ -1228,7 +1231,7 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const voiceMessages = result.messages
|
const voiceMessages: Message[] = result.messages
|
||||||
if (voiceMessages.length === 0) {
|
if (voiceMessages.length === 0) {
|
||||||
alert('当前会话没有语音消息')
|
alert('当前会话没有语音消息')
|
||||||
return
|
return
|
||||||
@@ -1245,6 +1248,15 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
setShowBatchConfirm(true)
|
setShowBatchConfirm(true)
|
||||||
}, [sessions, currentSessionId, isBatchTranscribing])
|
}, [sessions, currentSessionId, isBatchTranscribing])
|
||||||
|
|
||||||
|
const handleExportCurrentSession = useCallback(() => {
|
||||||
|
if (!currentSessionId) return
|
||||||
|
navigate('/export', {
|
||||||
|
state: {
|
||||||
|
preselectSessionIds: [currentSessionId]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [currentSessionId, navigate])
|
||||||
|
|
||||||
// 确认批量转写
|
// 确认批量转写
|
||||||
const confirmBatchTranscribe = useCallback(async () => {
|
const confirmBatchTranscribe = useCallback(async () => {
|
||||||
if (!currentSessionId) return
|
if (!currentSessionId) return
|
||||||
@@ -1465,6 +1477,14 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="header-actions">
|
<div className="header-actions">
|
||||||
|
<button
|
||||||
|
className="icon-btn export-session-btn"
|
||||||
|
onClick={handleExportCurrentSession}
|
||||||
|
disabled={!currentSessionId}
|
||||||
|
title="导出当前会话"
|
||||||
|
>
|
||||||
|
<Download size={18} />
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`icon-btn batch-transcribe-btn${isBatchTranscribing ? ' transcribing' : ''}`}
|
className={`icon-btn batch-transcribe-btn${isBatchTranscribing ? ' transcribing' : ''}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
import { useState, useEffect, useCallback, useRef, useMemo } from 'react'
|
||||||
|
import { useLocation } from 'react-router-dom'
|
||||||
import { Search, Download, FolderOpen, RefreshCw, Check, Calendar, FileJson, FileText, Table, Loader2, X, ChevronDown, ChevronLeft, ChevronRight, FileSpreadsheet, Database, FileCode, CheckCircle, XCircle, ExternalLink } from 'lucide-react'
|
import { Search, Download, FolderOpen, RefreshCw, Check, Calendar, FileJson, FileText, Table, Loader2, X, ChevronDown, ChevronLeft, ChevronRight, FileSpreadsheet, Database, FileCode, CheckCircle, XCircle, ExternalLink } from 'lucide-react'
|
||||||
import * as configService from '../services/config'
|
import * as configService from '../services/config'
|
||||||
import './ExportPage.scss'
|
import './ExportPage.scss'
|
||||||
@@ -38,6 +39,7 @@ interface ExportResult {
|
|||||||
type SessionLayout = 'shared' | 'per-session'
|
type SessionLayout = 'shared' | 'per-session'
|
||||||
|
|
||||||
function ExportPage() {
|
function ExportPage() {
|
||||||
|
const location = useLocation()
|
||||||
const defaultTxtColumns = ['index', 'time', 'senderRole', 'messageType', 'content']
|
const defaultTxtColumns = ['index', 'time', 'senderRole', 'messageType', 'content']
|
||||||
const [sessions, setSessions] = useState<ChatSession[]>([])
|
const [sessions, setSessions] = useState<ChatSession[]>([])
|
||||||
const [filteredSessions, setFilteredSessions] = useState<ChatSession[]>([])
|
const [filteredSessions, setFilteredSessions] = useState<ChatSession[]>([])
|
||||||
@@ -63,6 +65,19 @@ function ExportPage() {
|
|||||||
const exportStartTime = useRef<number>(0)
|
const exportStartTime = useRef<number>(0)
|
||||||
const [elapsedSeconds, setElapsedSeconds] = useState(0)
|
const [elapsedSeconds, setElapsedSeconds] = useState(0)
|
||||||
const displayNameDropdownRef = useRef<HTMLDivElement>(null)
|
const displayNameDropdownRef = useRef<HTMLDivElement>(null)
|
||||||
|
const preselectAppliedRef = useRef(false)
|
||||||
|
|
||||||
|
const preselectSessionIds = useMemo(() => {
|
||||||
|
const state = location.state as { preselectSessionIds?: unknown; preselectSessionId?: unknown } | null
|
||||||
|
const rawList = Array.isArray(state?.preselectSessionIds)
|
||||||
|
? state?.preselectSessionIds
|
||||||
|
: (typeof state?.preselectSessionId === 'string' ? [state.preselectSessionId] : [])
|
||||||
|
|
||||||
|
return rawList
|
||||||
|
.filter((item): item is string => typeof item === 'string')
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
}, [location.state])
|
||||||
|
|
||||||
const [options, setOptions] = useState<ExportOptions>({
|
const [options, setOptions] = useState<ExportOptions>({
|
||||||
format: 'excel',
|
format: 'excel',
|
||||||
@@ -184,6 +199,24 @@ function ExportPage() {
|
|||||||
loadExportDefaults()
|
loadExportDefaults()
|
||||||
}, [loadSessions, loadExportPath, loadExportDefaults])
|
}, [loadSessions, loadExportPath, loadExportDefaults])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
preselectAppliedRef.current = false
|
||||||
|
}, [location.key, preselectSessionIds])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (preselectAppliedRef.current) return
|
||||||
|
if (sessions.length === 0 || preselectSessionIds.length === 0) return
|
||||||
|
|
||||||
|
const exists = new Set(sessions.map(session => session.username))
|
||||||
|
const matched = preselectSessionIds.filter(id => exists.has(id))
|
||||||
|
preselectAppliedRef.current = true
|
||||||
|
|
||||||
|
if (matched.length > 0) {
|
||||||
|
setSelectedSessions(new Set(matched))
|
||||||
|
setSearchKeyword('')
|
||||||
|
}
|
||||||
|
}, [sessions, preselectSessionIds])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
setSelectedSessions(new Set())
|
setSelectedSessions(new Set())
|
||||||
|
|||||||
Reference in New Issue
Block a user