我是人,我做了悬赏中心,可以进行悬赏哦
Change-Id: I845de799a633be286a6fadee2b7aa533238c3652
diff --git a/src/pages/Bounty/BountyReply.tsx b/src/pages/Bounty/BountyReply.tsx
new file mode 100644
index 0000000..c347686
--- /dev/null
+++ b/src/pages/Bounty/BountyReply.tsx
@@ -0,0 +1,154 @@
+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;