2026-01-19 11:03:08 +00:00
|
|
|
import React, { useState, useEffect } from 'react';
|
2026-03-26 06:55:12 +00:00
|
|
|
import {
|
|
|
|
|
Card, Form, Input, Button, DatePicker, Select, Space,
|
|
|
|
|
Typography, App, Divider, Row, Col, Tag
|
|
|
|
|
} from 'antd';
|
|
|
|
|
import {
|
|
|
|
|
ArrowLeftOutlined, UserOutlined, CalendarOutlined,
|
|
|
|
|
TeamOutlined, FileTextOutlined, PlusOutlined,
|
|
|
|
|
UploadOutlined, SaveOutlined,
|
|
|
|
|
VideoCameraAddOutlined, TagOutlined
|
|
|
|
|
} from '@ant-design/icons';
|
|
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
|
import dayjs from 'dayjs';
|
2026-01-19 11:03:08 +00:00
|
|
|
import apiClient from '../utils/apiClient';
|
|
|
|
|
import { buildApiUrl, API_ENDPOINTS } from '../config/api';
|
2026-03-26 06:55:12 +00:00
|
|
|
|
|
|
|
|
const { Title, Text } = Typography;
|
|
|
|
|
const { TextArea } = Input;
|
2026-01-19 11:03:08 +00:00
|
|
|
|
|
|
|
|
const CreateMeeting = ({ user }) => {
|
|
|
|
|
const navigate = useNavigate();
|
2026-03-26 06:55:12 +00:00
|
|
|
const { message } = App.useApp();
|
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [users, setUsers] = useState([]);
|
|
|
|
|
const [prompts, setPrompts] = useState([]);
|
2026-01-19 11:03:08 +00:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
fetchUsers();
|
2026-03-26 06:55:12 +00:00
|
|
|
fetchPrompts();
|
2026-01-19 11:03:08 +00:00
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const fetchUsers = async () => {
|
|
|
|
|
try {
|
2026-03-26 06:55:12 +00:00
|
|
|
const res = await apiClient.get(buildApiUrl(API_ENDPOINTS.USERS.LIST));
|
|
|
|
|
setUsers(res.data.users || []);
|
|
|
|
|
} catch (e) {}
|
2026-01-19 11:03:08 +00:00
|
|
|
};
|
|
|
|
|
|
2026-03-26 06:55:12 +00:00
|
|
|
const fetchPrompts = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await apiClient.get(buildApiUrl(API_ENDPOINTS.PROMPTS.ACTIVE('MEETING_TASK')));
|
|
|
|
|
setPrompts(res.data.prompts || []);
|
|
|
|
|
} catch (e) {}
|
2026-01-19 11:03:08 +00:00
|
|
|
};
|
|
|
|
|
|
2026-03-26 06:55:12 +00:00
|
|
|
const onFinish = async (values) => {
|
|
|
|
|
setLoading(true);
|
2026-01-19 11:03:08 +00:00
|
|
|
try {
|
2026-03-26 06:55:12 +00:00
|
|
|
const payload = {
|
|
|
|
|
...values,
|
|
|
|
|
meeting_time: values.meeting_time.format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
attendees: values.attendees.join(','),
|
|
|
|
|
creator_id: user.user_id
|
2026-01-19 11:03:08 +00:00
|
|
|
};
|
2026-03-26 06:55:12 +00:00
|
|
|
const res = await apiClient.post(buildApiUrl(API_ENDPOINTS.MEETINGS.CREATE), payload);
|
|
|
|
|
if (res.code === '200') {
|
|
|
|
|
message.success('会议创建成功');
|
|
|
|
|
navigate(`/meetings/${res.data.meeting_id}`);
|
2026-01-19 11:03:08 +00:00
|
|
|
}
|
2026-03-26 06:55:12 +00:00
|
|
|
} catch (error) {
|
|
|
|
|
message.error(error.response?.data?.message || '创建失败');
|
2026-01-19 11:03:08 +00:00
|
|
|
} finally {
|
2026-03-26 06:55:12 +00:00
|
|
|
setLoading(false);
|
2026-01-19 11:03:08 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2026-03-26 06:55:12 +00:00
|
|
|
<div className="create-meeting-modern" style={{ maxWidth: 800, margin: '0 auto', padding: '24px 0' }}>
|
|
|
|
|
<Card bordered={false} style={{ borderRadius: 16, boxShadow: '0 4px 20px rgba(0,0,0,0.05)' }}>
|
|
|
|
|
<div style={{ display: 'flex', alignItems: 'center', marginBottom: 32 }}>
|
|
|
|
|
<Button icon={<ArrowLeftOutlined />} shape="circle" onClick={() => navigate(-1)} style={{ marginRight: 16 }} />
|
|
|
|
|
<Title level={3} style={{ margin: 0 }}>新建会议纪要</Title>
|
2026-01-19 11:03:08 +00:00
|
|
|
</div>
|
2026-03-26 06:55:12 +00:00
|
|
|
|
|
|
|
|
<Form form={form} layout="vertical" onFinish={onFinish} initialValues={{ meeting_time: dayjs() }}>
|
|
|
|
|
<Form.Item label="会议主题" name="title" rules={[{ required: true, message: '请输入会议主题' }]}>
|
|
|
|
|
<Input size="large" prefix={<VideoCameraAddOutlined />} placeholder="请输入会议主题..." />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Row gutter={24}>
|
|
|
|
|
<Col span={12}>
|
|
|
|
|
<Form.Item label="开始时间" name="meeting_time" rules={[{ required: true }]}>
|
|
|
|
|
<DatePicker showTime size="large" style={{ width: '100%' }} />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col span={12}>
|
|
|
|
|
<Form.Item label="使用总结模板" name="prompt_id">
|
|
|
|
|
<Select size="large" placeholder="选择总结模版">
|
|
|
|
|
{prompts.map(p => <Select.Option key={p.id} value={p.id}>{p.name}</Select.Option>)}
|
|
|
|
|
</Select>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Col>
|
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
|
|
<Form.Item label="参会人员" name="attendees" rules={[{ required: true, message: '请选择参会人员' }]}>
|
|
|
|
|
<Select mode="multiple" size="large" placeholder="选择参会人">
|
|
|
|
|
{users.map(u => <Select.Option key={u.user_id} value={u.caption}>{u.caption}</Select.Option>)}
|
|
|
|
|
</Select>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item label="标签" name="tags">
|
|
|
|
|
<Select mode="tags" size="large" placeholder="输入标签按回车" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item label="会议备注" name="description">
|
|
|
|
|
<TextArea rows={4} placeholder="添加会议背景或说明..." />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<Button type="primary" htmlType="submit" size="large" icon={<SaveOutlined />} loading={loading} block style={{ height: 50, fontSize: 16, borderRadius: 8 }}>
|
|
|
|
|
创建并进入详情
|
|
|
|
|
</Button>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</Card>
|
2026-01-19 11:03:08 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-26 06:55:12 +00:00
|
|
|
export default CreateMeeting;
|