From c60db6457879acad0d2e4733b10ebf8e9577d16a Mon Sep 17 00:00:00 2001 From: chenhao Date: Fri, 6 Mar 2026 13:45:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=AF=BC=E5=87=BApdf=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/business/MeetingCreate.tsx | 18 ++- frontend/src/pages/business/MeetingDetail.tsx | 49 +++++- frontend/src/pages/business/Meetings.tsx | 7 +- frontend/src/pages/business/SpeakerReg.tsx | 149 +++++++++++------- 4 files changed, 156 insertions(+), 67 deletions(-) diff --git a/frontend/src/pages/business/MeetingCreate.tsx b/frontend/src/pages/business/MeetingCreate.tsx index cf61b50..fa8ac20 100644 --- a/frontend/src/pages/business/MeetingCreate.tsx +++ b/frontend/src/pages/business/MeetingCreate.tsx @@ -150,7 +150,23 @@ const MeetingCreate: React.FC = () => {

点击或拖拽录音文件

{uploadProgress > 0 && uploadProgress < 100 && } - {audioUrl && 就绪: {audioUrl.split('/').pop()}} + {audioUrl && ( +
+ + 就绪: {audioUrl.split('/').pop()} + +
+ )} diff --git a/frontend/src/pages/business/MeetingDetail.tsx b/frontend/src/pages/business/MeetingDetail.tsx index 26db02a..0dc6945 100644 --- a/frontend/src/pages/business/MeetingDetail.tsx +++ b/frontend/src/pages/business/MeetingDetail.tsx @@ -227,6 +227,9 @@ const MeetingDetail: React.FC = () => { const [actionLoading, setActionLoading] = useState(false); const [downloadLoading, setDownloadLoading] = useState<'pdf' | 'word' | null>(null); + const [isEditingSummary, setIsEditingSummary] = useState(false); + const [summaryDraft, setSummaryDraft] = useState(''); + const [llmModels, setLlmModels] = useState([]); const [prompts, setPrompts] = useState([]); const [, setUserList] = useState([]); @@ -317,6 +320,23 @@ const MeetingDetail: React.FC = () => { } }; + const handleSaveSummary = async () => { + setActionLoading(true); + try { + await updateMeeting({ + id: meeting?.id, + summaryContent: summaryDraft, + }); + message.success('总结内容已更新'); + setIsEditingSummary(false); + fetchData(Number(id)); + } catch (err) { + console.error(err); + } finally { + setActionLoading(false); + } + }; + const handleReSummary = async () => { const vals = await summaryForm.validateFields(); setActionLoading(true); @@ -527,12 +547,37 @@ const MeetingDetail: React.FC = () => { AI 总结} + extra={ + meeting.summaryContent && isOwner && ( + + {isEditingSummary ? ( + <> + + + + ) : ( + + )} + + ) + } style={{ height: '100%', display: 'flex', flexDirection: 'column' }} bodyStyle={{ flex: 1, overflowY: 'auto', padding: '24px', minHeight: 0 }} > -
+
{meeting.summaryContent ? ( -
{meeting.summaryContent}
+ isEditingSummary ? ( + setSummaryDraft(e.target.value)} + style={{ height: '100%', resize: 'none' }} + /> + ) : ( +
{meeting.summaryContent}
+ ) ) : (
{meeting.status === 2 ? ( diff --git a/frontend/src/pages/business/Meetings.tsx b/frontend/src/pages/business/Meetings.tsx index fe0ed22..e04f2ec 100644 --- a/frontend/src/pages/business/Meetings.tsx +++ b/frontend/src/pages/business/Meetings.tsx @@ -190,12 +190,12 @@ const MeetingCreateForm: React.FC<{ marginTop: 20, padding: '4px 12px', fontSize: 13, - maxWidth: '90%', + maxWidth: '500px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} - size="large" + // size="large" > 就绪: {audioUrl.split('/').pop()} @@ -299,7 +299,8 @@ const MeetingCardItem: React.FC<{ item: MeetingVO, config: any, fetchData: () => width: '100%', // 占满 Space 容器 overflow: 'hidden', boxSizing: 'border-box', - minWidth: 0 // 关键:允许 flex 子项收缩 + minWidth: 0 ,// 关键:允许 flex 子项收缩 + maxWidth: 250 }}> { } }; + const uploadProps: UploadProps = { + beforeUpload: (file) => { + const isAudio = file.type.startsWith('audio/'); + if (!isAudio) { + message.error('只能上传音频文件!'); + return Upload.LIST_IGNORE; + } + setAudioBlob(file); + setAudioUrl(URL.createObjectURL(file)); + return false; // Prevent auto upload + }, + showUploadList: false, + }; + const handleSubmit = async () => { if (!audioBlob) { - message.warning('请先录制声纹文件'); + message.warning('请先录制或上传声纹文件'); return; } @@ -149,67 +164,79 @@ const SpeakerReg: React.FC = () => { {/* 左侧:采集与录音 */} - 录音指导文本 - -
- - “{REG_CONTENT}” - - 请在点击录音后,自然、清晰地朗读以上内容 -
- -
-
- {!recording ? ( -
- -
- - {recording ? `录制中... ${seconds}/${DEFAULT_DURATION}s` : "点击红色图标开始录音"} - -
- {recording && ( -
- + + +
+ + “{REG_CONTENT}” + + 请在点击录音后,自然、清晰地朗读以上内容
- )} -
+ +
+
+ {!recording ? ( +
+ +
+ + {recording ? `录制中... ${seconds}/${DEFAULT_DURATION}s` : "点击红色图标开始录音"} + +
+ {recording && ( +
+ +
+ )} +
+ + +
+ + + +
+ 支持上传 mp3, wav, m4a 等常见音频格式 +
+
+
+ {audioUrl && (
采集完成,请试听: - +
@@ -259,9 +286,9 @@ const SpeakerReg: React.FC = () => {
注册技巧:
- 1. 尽可能在安静的环境下录音。
- 2. 使用平时的语速和语调朗读文字。
- 3. 倒计时结束后系统将自动停止。 + 1. 尽可能在安静的环境下录音或上传清晰的音频。
+ 2. 使用平时的语速和语调。
+ 3. 在线录音倒计时结束后系统将自动停止。