阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 1 | import instance from '@/utils/axios'; |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 2 | import React, { useCallback, useEffect, useState } from 'react'; |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 3 | import styles from './upload.module.css'; |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 4 | import {postTorrentUpload } from '@/api/torrent'; |
| 5 | import { useLocation, useNavigate } from 'react-router-dom'; // 用于跳转 |
| 6 | import { getTagsByMainTag } from '@/utils/common'; |
| 7 | import { Checkbox, Row, Col } from 'antd'; // 使用 antd 的 Checkbox 组件 |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 8 | import { MainTag, MainPostTag } from '@/types/common'; |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 9 | import { Select } from 'antd'; |
| 10 | import { UploadOutlined } from '@ant-design/icons'; |
| 11 | import type { UploadProps } from 'antd'; |
| 12 | import { Button, message, Upload as UploadArea } from 'antd'; |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 13 | import request from '@/utils/request'; |
| 14 | import {useApi} from '@/hooks/request'; |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 15 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 16 | |
| 17 | const CreatePost = () => { |
| 18 | const location = useLocation(); |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 19 | const [postTitle, setPostTitle] = useState(''); |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 20 | const [postContent, setPostContent] = useState(''); |
| 21 | const [isChecked, setIsChecked] = useState(false); |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 22 | const {type} = location.state || {type: ''}; // 获取路由传递的参数 |
| 23 | const [tagIds, setTagIds] = useState<number[]>([]); |
| 24 | const [postType, setPostType] = useState<string>(type || ''); // 初始化 postType |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 25 | const navigate = useNavigate(); |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 26 | const [tags, setTags] = useState<Map<string, number>>(new Map()); |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 27 | const [torrentId, setTorrentId] = useState<number>(0); // 用于存储上传的种子 ID |
| 28 | const [messageApi, contextHolder] = message.useMessage(); |
| 29 | |
| 30 | const {refresh} = useApi((payload)=> request.post('/post', payload), false) |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 31 | |
| 32 | const props: UploadProps = { |
| 33 | name: 'file', |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 34 | action: process.env.API_BASE_URL + postTorrentUpload, // 替换为实际的上传接口地址 |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 35 | headers: { |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 36 | authorization: `Bearer ${localStorage.getItem('token')}`, // 使用本地存储的 token |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 37 | }, |
| 38 | onChange(info) { |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 39 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 40 | if (info.file.status === 'done') { |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 41 | const response = info.file.response; |
| 42 | if(response && response.code !== 200) { |
| 43 | messageApi.error(response.message || '上传失败'); |
| 44 | return; |
| 45 | } |
| 46 | else { |
| 47 | console.log('上传成功:', response); |
| 48 | messageApi.success('上传成功') |
| 49 | console.log(response.data.torrentId); |
| 50 | setTorrentId(response.data.torrentId); // 假设返回的数据中有 torrentId |
| 51 | } |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 52 | } else if (info.file.status === 'error') { |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 53 | messageApi.error(`${info.file.name} 文件上传失败`); |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 54 | } |
| 55 | }, |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 56 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 57 | }; |
| 58 | |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 59 | |
| 60 | const handleSubmit = async () => { |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 61 | console.log(torrentId) |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 62 | if (!postTitle.trim() || !postType || !postContent.trim()) { |
| 63 | alert('请填写完整内容(资源名、类型、内容介绍)'); |
| 64 | return; |
| 65 | } |
| 66 | |
| 67 | if (!isChecked) { |
| 68 | alert('请先确认您已知晓以上内容'); |
| 69 | return; |
| 70 | } |
| 71 | |
| 72 | const payload = { |
| 73 | post: { |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 74 | postTitle, |
| 75 | postContent, |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 76 | torrentId, |
| 77 | postType:'resource' |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 78 | }, |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 79 | tagIds: new Array(...tagIds, MainPostTag[postType as keyof typeof MainPostTag]), // 确保 tagIds 是一个数组 |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 80 | }; |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 81 | try{ |
| 82 | const res = await refresh(payload) |
| 83 | messageApi.success('发布成功', 3).then(()=>{ |
| 84 | navigate('/') |
| 85 | }); |
| 86 | ; // 发布成功后跳转到首页 |
| 87 | } catch (err){ |
| 88 | messageApi.error((err as Error).message || '发布失败,请稍后再试'); |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 89 | } |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 90 | |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 91 | }; |
| 92 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 93 | useEffect(() => { |
| 94 | setTags(getTagsByMainTag(type)); // 获取对应类型的标签 |
| 95 | },[]); |
| 96 | |
| 97 | const handlePostTypeChange = useCallback((value:string) => { |
| 98 | setPostType(value); |
| 99 | setTags(getTagsByMainTag(value)); // 更新 tags |
| 100 | setTagIds([]); // 清空已选的标签 ID |
| 101 | }, [postType, setTags, setTagIds]); |
| 102 | |
| 103 | |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 104 | return ( |
| 105 | <div className={styles.container}> |
San3yuan | 292794c | 2025-06-08 20:02:46 +0800 | [diff] [blame] | 106 | {contextHolder} |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 107 | <div className={styles.formGroup}> |
| 108 | <label>资源名:</label> |
| 109 | <input |
| 110 | type="text" |
| 111 | value={postTitle} |
| 112 | placeholder="请输入文本" |
| 113 | onChange={(e) => setPostTitle(e.target.value)} |
| 114 | className={styles.input} |
| 115 | /> |
| 116 | </div> |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 117 | |
| 118 | <div className={styles.formGroup}> |
| 119 | <label>种子类型:</label> |
| 120 | <Select |
| 121 | value={postType} |
| 122 | onChange={handlePostTypeChange} |
| 123 | |
| 124 | options ={ MainTag.map((item) => ({ |
| 125 | label: item, |
| 126 | value: item |
| 127 | }))} /> |
| 128 | </div> |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 129 | |
| 130 | <div className={styles.formGroup}> |
| 131 | <label>类型选择:</label> |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 132 | <Checkbox.Group |
| 133 | value={tagIds} |
| 134 | onChange={(checkedValues) => setTagIds(checkedValues as number[])} |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 135 | > |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 136 | <Row gutter={[12, 12]}> |
| 137 | {[...tags.entries()].map(([name, id]) => ( |
| 138 | <Col key={id} xs={12} sm={8} md={6} lg={4}> |
| 139 | <Checkbox value={id}>{name}</Checkbox> |
| 140 | </Col> |
| 141 | ))} |
| 142 | </Row> |
| 143 | </Checkbox.Group> |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 144 | </div> |
| 145 | |
| 146 | {/* 暂时移除上传文件表单 */} |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 147 | <div className={styles.formGroup}> |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 148 | <label>上传资源:</label> |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 149 | <UploadArea {...props}> |
| 150 | <Button icon={<UploadOutlined />}>Upload</Button> |
| 151 | </UploadArea> |
| 152 | </div> |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 153 | |
| 154 | <div className={styles.formGroup}> |
| 155 | <label>内容介绍:</label> |
| 156 | <textarea |
| 157 | placeholder="请输入内容介绍" |
| 158 | value={postContent} |
| 159 | onChange={(e) => setPostContent(e.target.value)} |
| 160 | maxLength={200} |
| 161 | className={styles.textarea} |
| 162 | /> |
| 163 | <div className={styles.charCount}>{postContent.length}/200</div> |
| 164 | </div> |
| 165 | |
| 166 | <div className={styles.requirement}>【发布内容要求】</div> |
| 167 | |
| 168 | <div className={styles.checkbox}> |
| 169 | <input |
| 170 | type="checkbox" |
| 171 | checked={isChecked} |
| 172 | onChange={() => setIsChecked(!isChecked)} |
| 173 | /> |
| 174 | <span>我已知晓以上内容</span> |
| 175 | </div> |
| 176 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 177 | <button onClick={handleSubmit} className={styles.submitBtn} disabled={!isChecked}> |
阳菜,放晴! | 7e1e3a5 | 2025-06-05 23:00:51 +0800 | [diff] [blame] | 178 | 我已知晓 |
| 179 | </button> |
| 180 | </div> |
| 181 | ); |
| 182 | }; |
| 183 | |
San3yuan | 30e245f | 2025-06-07 20:04:23 +0800 | [diff] [blame] | 184 | export default CreatePost; |