2026-04-08 11:19:33 +00:00
|
|
|
|
import React from 'react';
|
|
|
|
|
|
import { Drawer, Form, Input, Button, DatePicker, Select, Space, Upload, Card, Progress, Typography } from 'antd';
|
2026-04-07 10:48:35 +00:00
|
|
|
|
import { SaveOutlined, UploadOutlined, DeleteOutlined, AudioOutlined } from '@ant-design/icons';
|
|
|
|
|
|
import configService from '../utils/configService';
|
2026-04-08 11:19:33 +00:00
|
|
|
|
import { AUDIO_UPLOAD_ACCEPT } from '../services/meetingAudioService';
|
|
|
|
|
|
import useMeetingFormDrawer from '../hooks/useMeetingFormDrawer';
|
2026-03-26 06:55:12 +00:00
|
|
|
|
|
2026-04-07 10:48:35 +00:00
|
|
|
|
const { Text } = Typography;
|
2026-03-26 06:55:12 +00:00
|
|
|
|
|
2026-03-27 07:43:08 +00:00
|
|
|
|
const MeetingFormDrawer = ({ open, onClose, onSuccess, meetingId = null }) => {
|
2026-04-08 11:19:33 +00:00
|
|
|
|
const {
|
|
|
|
|
|
form,
|
|
|
|
|
|
isEdit,
|
|
|
|
|
|
loading,
|
|
|
|
|
|
users,
|
|
|
|
|
|
prompts,
|
|
|
|
|
|
selectedAudioFile,
|
|
|
|
|
|
audioUploading,
|
|
|
|
|
|
audioUploadProgress,
|
|
|
|
|
|
audioUploadMessage,
|
|
|
|
|
|
maxAudioSize,
|
|
|
|
|
|
handleAudioBeforeUpload,
|
|
|
|
|
|
clearSelectedAudio,
|
|
|
|
|
|
handleSubmit,
|
|
|
|
|
|
} = useMeetingFormDrawer({ open, onClose, onSuccess, meetingId });
|
2026-03-26 06:55:12 +00:00
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Drawer
|
|
|
|
|
|
title={isEdit ? '编辑会议' : '新建会议'}
|
|
|
|
|
|
placement="right"
|
|
|
|
|
|
width={560}
|
|
|
|
|
|
open={open}
|
|
|
|
|
|
onClose={onClose}
|
|
|
|
|
|
destroyOnClose
|
|
|
|
|
|
extra={
|
|
|
|
|
|
<Space>
|
2026-04-07 10:48:35 +00:00
|
|
|
|
<Button type="primary" icon={<SaveOutlined />} loading={loading || audioUploading} onClick={handleSubmit}>
|
2026-03-26 06:55:12 +00:00
|
|
|
|
{isEdit ? '保存修改' : '创建会议'}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
}
|
|
|
|
|
|
>
|
2026-04-08 11:19:33 +00:00
|
|
|
|
<Form form={form} layout="vertical">
|
2026-03-26 06:55:12 +00:00
|
|
|
|
<Form.Item label="会议主题" name="title" rules={[{ required: true, message: '请输入会议主题' }]}>
|
|
|
|
|
|
<Input placeholder="请输入会议主题..." />
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item label="开始时间" name="meeting_time" rules={[{ required: true }]}>
|
|
|
|
|
|
<DatePicker showTime style={{ width: '100%' }} />
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item label="使用总结模板" name="prompt_id">
|
|
|
|
|
|
<Select allowClear placeholder="选择总结模版">
|
|
|
|
|
|
{prompts.map((p) => (
|
|
|
|
|
|
<Select.Option key={p.id} value={p.id}>{p.name}</Select.Option>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
2026-04-15 06:25:46 +00:00
|
|
|
|
<Form.Item label="参会人员" name="attendee_ids">
|
|
|
|
|
|
<Select mode="multiple" placeholder="可不选参会人">
|
2026-03-26 06:55:12 +00:00
|
|
|
|
{users.map((u) => (
|
2026-03-27 07:43:08 +00:00
|
|
|
|
<Select.Option key={u.user_id} value={u.user_id}>{u.caption}</Select.Option>
|
2026-03-26 06:55:12 +00:00
|
|
|
|
))}
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item label="标签" name="tags">
|
|
|
|
|
|
<Select mode="tags" placeholder="输入标签按回车" />
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
2026-04-07 10:48:35 +00:00
|
|
|
|
{!isEdit ? (
|
|
|
|
|
|
<Form.Item label="会议音频">
|
|
|
|
|
|
<Card
|
|
|
|
|
|
variant="borderless"
|
|
|
|
|
|
style={{
|
|
|
|
|
|
borderRadius: 14,
|
|
|
|
|
|
border: '1px solid #d9e2f2',
|
|
|
|
|
|
background: selectedAudioFile ? 'linear-gradient(135deg, #f8fbff 0%, #ffffff 100%)' : '#fbfdff',
|
|
|
|
|
|
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.86)',
|
|
|
|
|
|
}}
|
|
|
|
|
|
styles={{ body: { padding: 18 } }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Space direction="vertical" size={14} style={{ width: '100%' }}>
|
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'flex-start' }}>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Text type="secondary">
|
|
|
|
|
|
支持 {AUDIO_UPLOAD_ACCEPT.replace(/\./g, '').toUpperCase()};
|
2026-04-14 01:56:57 +00:00
|
|
|
|
<br/>音频文件最大 {maxAudioSize ? configService.formatFileSize(maxAudioSize) : '加载中'}。
|
2026-04-07 10:48:35 +00:00
|
|
|
|
</Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Upload accept={AUDIO_UPLOAD_ACCEPT} showUploadList={false} beforeUpload={handleAudioBeforeUpload}>
|
|
|
|
|
|
<Button icon={<UploadOutlined />} disabled={audioUploading}>选择音频</Button>
|
|
|
|
|
|
</Upload>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{selectedAudioFile ? (
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: 16,
|
|
|
|
|
|
padding: '12px 14px',
|
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
|
background: '#ffffff',
|
|
|
|
|
|
border: '1px solid #dbe7f5',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Space size={12}>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: 36,
|
|
|
|
|
|
height: 36,
|
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
|
display: 'grid',
|
|
|
|
|
|
placeItems: 'center',
|
|
|
|
|
|
background: '#edf4ff',
|
|
|
|
|
|
color: '#1d4ed8',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<AudioOutlined />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Text strong style={{ display: 'block' }}>{selectedAudioFile.name}</Text>
|
|
|
|
|
|
<Text type="secondary">{configService.formatFileSize(selectedAudioFile.size)}</Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
<Button type="text" icon={<DeleteOutlined />} onClick={clearSelectedAudio} disabled={audioUploading}>
|
|
|
|
|
|
移除
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
|
border: '1px dashed #c7d5ea',
|
|
|
|
|
|
padding: '18px 16px',
|
|
|
|
|
|
background: '#ffffff',
|
|
|
|
|
|
color: 'rgba(17, 43, 78, 0.66)',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
可在会议详情中补传。
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{audioUploading ? (
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
padding: '12px 14px',
|
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
|
background: '#f0f7ff',
|
|
|
|
|
|
border: '1px solid #bfdbfe',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
|
|
|
|
<Text strong>音频上传中</Text>
|
|
|
|
|
|
<Text strong style={{ color: '#1677ff' }}>{audioUploadProgress}%</Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Text type="secondary" style={{ display: 'block', marginBottom: 10 }}>
|
|
|
|
|
|
{audioUploadMessage || '正在上传音频文件...'}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Progress percent={audioUploadProgress} status="active" strokeColor={{ from: '#69b1ff', to: '#1677ff' }} />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
) : null}
|
2026-03-26 06:55:12 +00:00
|
|
|
|
</Form>
|
|
|
|
|
|
</Drawer>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default MeetingFormDrawer;
|