| import React, { useState, useEffect } from 'react'; |
| import { Form, Input, Select, Button, Upload, message } from 'antd'; |
| import axios from 'axios'; // 新增 axios 导入 |
| import { submitBountyReply, uploadBountyAttachment } from '@/services/bounty/bounty'; // ✅ 新增导入上传接口 |
| const { Option } = Select; |
| interface BountyReplyProps { |
| bountyId: number; // 需要回复的悬赏ID |
| onSuccess?: () => void; // 提交成功回调 |
| onCancel?: () => void; // 取消操作回调 |
| } |
| |
| const BountyReply: React.FC<BountyReplyProps> = ({ |
| bountyId, |
| onSuccess, |
| onCancel |
| }) => { |
| const [form] = Form.useForm(); |
| const [bountyList, setBountyList] = useState<{ id: number; title: string }[]>([]); |
| const [uploading, setUploading] = useState(false); // ✅ 新增上传状态 |
| // 加载可回复的悬赏列表(修改请求方式) |
| useEffect(() => { |
| const loadBountyList = async () => { |
| try { |
| const res = await axios.get('/api/bounties', { params: { status: 0 } }); // 替换 get 为 axios.get |
| if (res.data.code === 200) { |
| setBountyList(res.data.data.records || []); |
| } |
| } catch (err) { |
| message.error('加载悬赏列表失败'); |
| } |
| }; |
| loadBountyList(); |
| }, []); |
| |
| // 附件上传逻辑(修改请求方式) |
| const handleUpload = async (file: File) => { |
| try { |
| setUploading(true); |
| // 1. 上传文件获取路径 |
| const filePath = await uploadBountyAttachment(file); |
| // 2. 保存文件对象到表单(用于后续提交) |
| form.setFieldsValue({ attachment: filePath, file }); // ✅ 同时保存路径和文件对象 |
| return { url: filePath }; |
| } catch (err) { |
| message.error('上传失败'); |
| return { error: new Error('上传失败') }; |
| } finally { |
| setUploading(false); |
| } |
| }; |
| |
| // 提交回复逻辑(修改请求方式) |
| // ✅ 替换 axios 请求为服务方法调用 |
| const handleSubmit = async (values: { content: string; attachment?: string }) => { |
| try { |
| // 从表单获取文件对象(需在 handleUpload 中保存) |
| const file = form.getFieldValue('file'); // ✅ 获取文件对象 |
| |
| const res = await submitBountyReply({ |
| bountyId, |
| ...values, |
| file, // ✅ 传递文件对象 |
| }); |
| |
| if (res?.code === 200) { |
| message.success('提交成功'); |
| form.resetFields(); |
| onSuccess?.(); |
| } else { |
| throw new Error('接口异常: ' + JSON.stringify(res)); |
| } |
| } catch (err) { |
| console.error('提交失败:', err); |
| message.error('提交失败,请重试'); |
| } |
| }; |
| |
| // @ts-ignore |
| // @ts-ignore |
| // @ts-ignore |
| // @ts-ignore |
| // @ts-ignore |
| // @ts-ignore |
| return ( |
| <div className="page-container"> |
| <h2>回复悬赏</h2> |
| <Form |
| form={form} |
| layout="vertical" |
| onFinish={handleSubmit} |
| requiredMark="optional" |
| style={{ maxWidth: 600 }} |
| > |
| {/* 选择悬赏(默认选中传入的bountyId) */} |
| <Form.Item |
| name="bountyId" |
| label="选择悬赏" |
| rules={[{ required: true, message: '请选择要回复的悬赏' }]} |
| initialValue={bountyId} |
| > |
| <Select disabled={!!bountyId} placeholder="请选择要回复的悬赏"> |
| {bountyList.map((item) => ( |
| <Option key={item.id} value={item.id}> |
| {item.title} |
| </Option> |
| ))} |
| </Select> |
| </Form.Item> |
| |
| {/* 回复内容(保持原有逻辑) */} |
| <Form.Item |
| name="content" |
| label="回复内容" |
| rules={[{ required: true, message: '请输入回复内容' }]} |
| > |
| <Input.TextArea rows={4} placeholder="请输入回复内容" /> |
| </Form.Item> |
| |
| {/* 附件上传(保持原有逻辑) */} |
| <Form.Item name="attachment" label="附件上传"> |
| <Upload |
| customRequest={({ file, onSuccess, onError }) => { |
| handleUpload(file as File); // 显式断言 file 为 File 类型 |
| }} // 使用服务层上传 |
| maxCount={1} |
| accept=".doc,.docx,.pdf,.zip" |
| showUploadList={false} // 隐藏默认上传列表 |
| > |
| <Button loading={uploading}>上传附件</Button> |
| </Upload> |
| </Form.Item> |
| |
| {/* 提交按钮 */} |
| <Form.Item> |
| <Button type="primary" htmlType="submit"> |
| 提交回复 |
| </Button> |
| <Button |
| type="default" |
| onClick={() => { |
| form.resetFields(); |
| onCancel?.(); // 🔥 取消时触发回调 |
| }} |
| style={{ marginLeft: 16 }} |
| > |
| 取消 |
| </Button> |
| </Form.Item> |
| </Form> |
| </div> |
| ); |
| }; |
| |
| export default BountyReply; |