增加接悬赏前端,注意积分还没做

Change-Id: I0f0054b645618ec16330686b74989c4138a9393b
diff --git a/react-ui/src/pages/Reward/index.tsx b/react-ui/src/pages/Reward/index.tsx
index 231415c..c86f2c2 100644
--- a/react-ui/src/pages/Reward/index.tsx
+++ b/react-ui/src/pages/Reward/index.tsx
@@ -1,11 +1,12 @@
-import { ExclamationCircleOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
-import { Button, message, Modal, Switch } from 'antd';
+import { ExclamationCircleOutlined, PlusOutlined, DeleteOutlined, UploadOutlined } from '@ant-design/icons';
+import { Button, message, Modal, Switch, Upload } from 'antd';
 import React, { useRef, useState, useEffect } from 'react';
 import { FormattedMessage, useIntl } from 'umi';
 import { FooterToolbar, PageContainer } from '@ant-design/pro-layout';
 import type { ActionType, ProColumns } from '@ant-design/pro-table';
 import ProTable from '@ant-design/pro-table';
 import type { FormInstance } from 'antd';
+import type { UploadFile } from 'antd/es/upload/interface';
 import { getRewardList, removeReward, updateReward, addReward } from './service';
 import UpdateForm from './components/UpdateForm';
 import { getDictValueEnum } from '@/services/system/dict';
@@ -69,12 +70,53 @@
     }
 };
 
+/**
+ * 处理接悬赏提交
+ * @param rewardId 悬赏ID
+ * @param fileList 上传的文件列表
+ */
+const handleAcceptReward = async (rewardId: string, fileList: UploadFile[]) => {
+    const hide = message.loading('正在提交悬赏...');
+    try {
+        // 这里需要根据实际后端API进行调整
+        // 假设有一个接悬赏的API: acceptReward
+        const formData = new FormData();
+        formData.append('rewardId', rewardId);
+
+        // 添加文件到FormData
+        fileList.forEach((file, index) => {
+            if (file.originFileObj) {
+                formData.append(`files[${index}]`, file.originFileObj);
+            }
+        });
+
+        // 这里需要替换为实际的API调用
+        // const resp = await acceptReward(formData);
+
+        // 模拟API调用
+        await new Promise(resolve => setTimeout(resolve, 1000));
+
+        hide();
+        message.success('悬赏提交成功!');
+        return true;
+    } catch (error) {
+        hide();
+        message.error('提交失败,请重试!');
+        return false;
+    }
+};
+
 const RewardTableList: React.FC = () => {
     const formTableRef = useRef<FormInstance>();
 
     const [modalVisible, setModalVisible] = useState<boolean>(false);
     const [readOnly, setReadOnly] = useState<boolean>(false);
 
+    // 接悬赏相关状态
+    const [acceptModalVisible, setAcceptModalVisible] = useState<boolean>(false);
+    const [currentAcceptReward, setCurrentAcceptReward] = useState<RewardItem>();
+    const [fileList, setFileList] = useState<UploadFile[]>([]);
+
     const actionRef = useRef<ActionType>();
     const [currentRow, setCurrentRow] = useState<RewardItem>();
     const [selectedRows, setSelectedRows] = useState<RewardItem[]>([]);
@@ -92,6 +134,54 @@
         });
     }, []);
 
+    // 处理文件上传变化
+    const handleFileChange = ({ fileList: newFileList }: { fileList: UploadFile[] }) => {
+        // 限制只能上传一个文件
+        if (newFileList.length > 1) {
+            message.warning('只能上传一个文件!');
+            setFileList([newFileList[newFileList.length - 1]]); // 保留最后一个文件
+        } else {
+            setFileList(newFileList);
+        }
+    };
+
+    // 文件上传前的检查
+    const beforeUpload = (file: File) => {
+        const isValidSize = file.size / 1024 / 1024 < 50; // 限制50MB
+        if (!isValidSize) {
+            message.error('文件大小不能超过50MB!');
+            return false;
+        }
+
+        // 检查是否已经有文件了
+        if (fileList.length >= 1) {
+            message.warning('只能上传一个文件,当前文件将替换已选择的文件!');
+        }
+
+        return false; // 阻止自动上传,我们手动处理
+    };
+
+    // 处理接悬赏提交
+    const handleAcceptSubmit = async () => {
+        if (!currentAcceptReward) return;
+
+        if (fileList.length === 0) {
+            message.warning('请选择一个文件!');
+            return;
+        }
+
+        const success = await handleAcceptReward(currentAcceptReward.rewardId, fileList);
+        if (success) {
+            setAcceptModalVisible(false);
+            setCurrentAcceptReward(undefined);
+            setFileList([]);
+            // 刷新表格数据
+            if (actionRef.current) {
+                actionRef.current.reload();
+            }
+        }
+    };
+
     const columns: ProColumns<RewardItem>[] = [
         {
             title: '悬赏ID',
@@ -144,7 +234,7 @@
         {
             title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
             dataIndex: 'option',
-            width: '220px',
+            width: '300px',
             valueType: 'option',
             render: (_, record) => [
                 <Button
@@ -163,6 +253,19 @@
                 <Button
                     type="link"
                     size="small"
+                    key="accept"
+                    style={{ color: '#52c41a' }}
+                    onClick={() => {
+                        setCurrentAcceptReward(record);
+                        setAcceptModalVisible(true);
+                        setFileList([]);
+                    }}
+                >
+                    接悬赏
+                </Button>,
+                <Button
+                    type="link"
+                    size="small"
                     key="edit"
                     hidden={!access.hasPerms('reward:reward:edit')}
                     onClick={() => {
@@ -271,6 +374,7 @@
                     }}
                 />
             </div>
+
             {selectedRows?.length > 0 && (
                 <FooterToolbar
                     extra={
@@ -305,6 +409,8 @@
                     </Button>
                 </FooterToolbar>
             )}
+
+            {/* 原有的编辑/新增模态框 */}
             <UpdateForm
                 readOnly={readOnly}
                 onSubmit={async (values) => {
@@ -331,6 +437,46 @@
                 values={currentRow || {}}
                 statusOptions={statusOptions}
             />
+
+            {/* 接悬赏模态框 */}
+            <Modal
+                title={`接悬赏 - ${currentAcceptReward?.title || ''}`}
+                open={acceptModalVisible}
+                onOk={handleAcceptSubmit}
+                onCancel={() => {
+                    setAcceptModalVisible(false);
+                    setCurrentAcceptReward(undefined);
+                    setFileList([]);
+                }}
+                width={600}
+                okText="提交悬赏"
+                cancelText="取消"
+            >
+                <div style={{ marginBottom: 16 }}>
+                    <p><strong>悬赏标题:</strong>{currentAcceptReward?.title}</p>
+                    <p><strong>悬赏金额:</strong>¥{currentAcceptReward?.amount}</p>
+                    <p><strong>备注:</strong>{currentAcceptReward?.remark || '无'}</p>
+                </div>
+
+                <div>
+                    <p style={{ marginBottom: 8, fontWeight: 'bold' }}>上传种子文件:</p>
+                    <Upload
+                        fileList={fileList}
+                        onChange={handleFileChange}
+                        beforeUpload={beforeUpload}
+                        onRemove={(file) => {
+                            setFileList([]);
+                        }}
+                        maxCount={1}
+                        accept=".torrent"
+                    >
+                        <Button icon={<UploadOutlined />}>选择种子文件</Button>
+                    </Upload>
+                    <p style={{ marginTop: 8, color: '#666', fontSize: '12px' }}>
+                        只能上传一个种子文件,文件大小不超过50MB
+                    </p>
+                </div>
+            </Modal>
         </PageContainer>
     );
 };