blob: 0f23e82ee71c569cc68097c801ac496753b8e460 [file] [log] [blame]
Krishyaf1d0ea82025-05-03 17:01:58 +08001import React, { useState } from 'react';
2import axios from 'axios';
Krishya7ec1dd02025-04-19 15:29:03 +08003import { Edit } from '@icon-park/react';
4import './CreatePostButton.css';
5
Krishya2283d882025-05-27 22:25:19 +08006const user = JSON.parse(localStorage.getItem('user')); // user = { user_id: 123, ... }
7const userId = user?.user_id;
8
Krishya7ec1dd02025-04-19 15:29:03 +08009
Krishyaf1d0ea82025-05-03 17:01:58 +080010const CreatePostButton = () => {
11 const [showModal, setShowModal] = useState(false);
12
Krishyaf1d0ea82025-05-03 17:01:58 +080013 const [title, setTitle] = useState('');
14 const [content, setContent] = useState('');
15 const [previewUrls, setPreviewUrls] = useState([]);
Krishya2283d882025-05-27 22:25:19 +080016 const [files, setFiles] = useState([]);
Krishyaf1d0ea82025-05-03 17:01:58 +080017
Krishya2283d882025-05-27 22:25:19 +080018 // 选择图片并预览
19 const handleImageChange = (e) => {
20 const selectedFiles = Array.from(e.target.files);
21 if (!selectedFiles.length) return;
22 setFiles(selectedFiles);
23 setPreviewUrls(selectedFiles.map(f => URL.createObjectURL(f)));
Krishyaf1d0ea82025-05-03 17:01:58 +080024 };
25
Krishyaf1d0ea82025-05-03 17:01:58 +080026 const handleSubmit = async () => {
27 if (!title.trim() || !content.trim()) {
28 alert('标题和内容均为必填项');
29 return;
30 }
31
Krishya2283d882025-05-27 22:25:19 +080032 const formData = new FormData();
33 formData.append('title', title.trim());
34 formData.append('postContent', content.trim());
35
36 files.forEach(file => {
37 formData.append('imageUrl', file); // 多文件使用同一个字段名
38 });
39
Krishyaf1d0ea82025-05-03 17:01:58 +080040 try {
41 await axios.post(
Krishya2283d882025-05-27 22:25:19 +080042 `/echo/forum/posts/${userId}/createPost`,
43 formData,
Krishyaf1d0ea82025-05-03 17:01:58 +080044 {
Krishya2283d882025-05-27 22:25:19 +080045 headers: { 'Content-Type': 'multipart/form-data' }
Krishyaf1d0ea82025-05-03 17:01:58 +080046 }
47 );
Krishya2283d882025-05-27 22:25:19 +080048
49 // 清空表单
Krishyaf1d0ea82025-05-03 17:01:58 +080050 setTitle('');
51 setContent('');
Krishya2283d882025-05-27 22:25:19 +080052 setFiles([]);
Krishyaf1d0ea82025-05-03 17:01:58 +080053 setPreviewUrls([]);
Krishyaf1d0ea82025-05-03 17:01:58 +080054 setShowModal(false);
55 alert('发帖成功');
Krishyaf1d0ea82025-05-03 17:01:58 +080056 } catch (err) {
57 console.error('发帖失败:', err.response?.data || err);
58 alert(err.response?.data?.error || '发帖失败,请稍后重试');
59 }
Krishya7ec1dd02025-04-19 15:29:03 +080060 };
61
62 return (
Krishyaf1d0ea82025-05-03 17:01:58 +080063 <>
64 <div className="create-post">
65 <button onClick={() => setShowModal(true)} className="create-btn">
66 <Edit theme="outline" size="18" style={{ marginRight: 6 }} />
67 发帖
68 </button>
69 </div>
70
71 {showModal && (
72 <div className="cp-modal-overlay" onClick={() => setShowModal(false)}>
73 <div className="cp-modal-dialog" onClick={e => e.stopPropagation()}>
74 <h3>创建新帖子</h3>
75
76 <input
77 type="text"
78 placeholder="帖子标题"
79 value={title}
80 onChange={e => setTitle(e.target.value)}
81 />
82
83 <textarea
84 placeholder="正文内容"
85 value={content}
86 onChange={e => setContent(e.target.value)}
87 />
88
89 <label className="file-label">
90 选择图片
91 <input
92 type="file"
93 accept="image/*"
94 multiple
95 onChange={handleImageChange}
96 style={{ display: 'none' }}
97 />
98 </label>
99
100 <div className="cp-preview">
101 {previewUrls.map((url, i) => (
Krishya2283d882025-05-27 22:25:19 +0800102 <img key={i} src={url} alt={`预览 ${i}`} />
Krishyaf1d0ea82025-05-03 17:01:58 +0800103 ))}
104 </div>
105
106 <div className="cp-actions">
107 <button className="btn cancel" onClick={() => setShowModal(false)}>
108 取消
109 </button>
110 <button className="btn submit" onClick={handleSubmit}>
111 发布
112 </button>
113 </div>
114 </div>
115 </div>
116 )}
117 </>
Krishya7ec1dd02025-04-19 15:29:03 +0800118 );
119};
120
121export default CreatePostButton;
Krishya2283d882025-05-27 22:25:19 +0800122