前端简单界面

Change-Id: I7df9774daf4df8d92b13e659effe426ab0b6180b
diff --git a/pt--frontend/src/components/RequestBoard.jsx b/pt--frontend/src/components/RequestBoard.jsx
new file mode 100644
index 0000000..f90f2fb
--- /dev/null
+++ b/pt--frontend/src/components/RequestBoard.jsx
@@ -0,0 +1,300 @@
+import React, { useState, useEffect } from 'react';
+import {
+    createRequest,
+    deleteRequest,
+    updateMoney,
+    findByUserid,
+    findByName,
+    getTotalMoneyByName,
+    updateLoaduserByName,
+} from '../api/request';
+
+const RequestBoard = ({ currentUserId }) => {
+    const [requests, setRequests] = useState([]); // 始终存储当前用户的求助帖
+    const [searchedRequests, setSearchedRequests] = useState([]); // 存储搜索结果
+    const [formData, setFormData] = useState({
+        userid: currentUserId,
+        name: '',
+        plot: '',
+        money: '',
+        year: '',
+        country: '',
+        photo: null,
+    });
+    const [searchName, setSearchName] = useState('');
+    const [totalMoney, setTotalMoney] = useState(null);
+
+    // 获取当前用户求助帖
+    const loadUserRequests = async () => {
+        const data = await findByUserid(currentUserId);
+        setRequests(data);
+    };
+
+    useEffect(() => {
+        loadUserRequests();
+    }, []);
+
+    // 表单变更处理
+    const handleChange = (e) => {
+        const { name, value, files } = e.target;
+        setFormData((prev) => ({
+            ...prev,
+            [name]: files ? files[0] : value,
+        }));
+    };
+
+    // 提交创建
+    const handleCreate = async (e) => {
+        e.preventDefault();
+        const fd = new FormData();
+        Object.entries(formData).forEach(([key, value]) => {
+            if (value !== '' && value !== null) fd.append(key, value);
+        });
+
+        const res = await createRequest(fd);
+        if (res.data === true) {
+            alert('创建成功');
+            setFormData(prev => ({
+                ...prev,
+                name: '',
+                plot: '',
+                money: '',
+                year: '',
+                country: '',
+                photo: null,
+            }));
+            loadUserRequests(); // 创建成功后刷新当前用户帖子
+        } else {
+            alert('创建失败');
+        }
+    };
+
+    // 删除
+    const handleDelete = async (id) => {
+        await deleteRequest(id);
+        loadUserRequests(); // 删除后刷新当前用户帖子
+    };
+
+    // 更新金额
+    const handleUpdateMoney = async (id, newMoney) => {
+        if (!newMoney) return;
+        await updateMoney(id, newMoney);
+        loadUserRequests(); // 更新金额后刷新当前用户帖子
+    };
+
+    // 按名称搜索并计算总金额
+    const handleSearch = async () => {
+        const data = await findByName(searchName);
+        const total = await getTotalMoneyByName(searchName);
+        setSearchedRequests(data); // 搜索结果存储到独立状态
+        setTotalMoney(total);
+    };
+
+    // 上传更新被协助用户 ID(批量更新同名求助帖)
+    const handleUploadLoaduser = async (name) => {
+        try {
+            await updateLoaduserByName(name, currentUserId);
+            alert('更新成功');
+            loadUserRequests(); // 更新后刷新当前用户帖子
+            setSearchedRequests([]); // 同步清空搜索结果(可选)
+        } catch (error) {
+            alert('更新失败,请稍后重试');
+            console.error(error);
+        }
+    };
+
+    return (
+        <div className="p-4 max-w-4xl mx-auto">
+            <h2 className="text-2xl font-bold mb-4">发布求助帖</h2>
+            <form className="grid grid-cols-2 gap-4 mb-6" onSubmit={handleCreate}>
+                <input
+                    name="name"
+                    placeholder="标题/名称"
+                    className="border p-2"
+                    value={formData.name}
+                    onChange={handleChange}
+                />
+                <textarea
+                    name="plot"
+                    placeholder="内容/情节"
+                    className="border p-2 col-span-2"
+                    value={formData.plot}
+                    onChange={handleChange}
+                />
+                <input
+                    name="money"
+                    type="number"
+                    placeholder="金额"
+                    className="border p-2"
+                    value={formData.money}
+                    onChange={handleChange}
+                />
+                <input
+                    name="year"
+                    type="number"
+                    placeholder="年份"
+                    className="border p-2"
+                    value={formData.year}
+                    onChange={handleChange}
+                />
+                <input
+                    name="country"
+                    placeholder="国家"
+                    className="border p-2"
+                    value={formData.country}
+                    onChange={handleChange}
+                />
+                <input
+                    name="photo"
+                    type="file"
+                    className="border p-2 col-span-2"
+                    onChange={handleChange}
+                />
+                <button
+                    type="submit"
+                    className="bg-blue-500 text-white p-2 col-span-2 rounded"
+                >
+                    发布
+                </button>
+            </form>
+
+            <div className="mb-6">
+                <h3 className="text-xl font-semibold mb-2">查找求助帖</h3>
+                <div className="flex gap-2 mb-2">
+                    <input
+                        type="text"
+                        placeholder="输入标题"
+                        value={searchName}
+                        onChange={(e) => setSearchName(e.target.value)}
+                        className="border p-2 flex-1"
+                    />
+                    <button
+                        onClick={handleSearch}
+                        className="bg-green-500 text-white p-2 rounded"
+                    >
+                        查找
+                    </button>
+                </div>
+                {totalMoney !== null && (
+                    <p className="text-gray-700">
+                        该名称对应的总金额:<strong>{totalMoney}</strong>
+                    </p>
+                )}
+            </div>
+
+            {/* 搜索结果展示(有搜索结果时显示) */}
+            {searchedRequests.length > 0 && (
+                <div className="mb-6">
+                    <h3 className="text-xl font-semibold mb-2">搜索结果</h3>
+                    <button
+                        onClick={() => {
+                            setSearchedRequests([]);
+                            setSearchName('');
+                            setTotalMoney(null);
+                        }}
+                        className="bg-gray-500 text-white p-1 px-2 rounded mb-2"
+                    >
+                        ← 返回我的求助帖
+                    </button>
+                    {searchedRequests.length === 0 ? (
+                        <p className="text-gray-500">无匹配的求助帖</p>
+                    ) : (
+                        <div className="grid grid-cols-1 gap-4">
+                            {searchedRequests.map((request) => (
+                                <div key={request.requestid} className="border p-3 rounded shadow">
+                                    <h4 className="text-lg font-semibold">{request.name}</h4>
+                                    <p className="text-gray-600 mb-2">{request.plot}</p>
+                                    <div className="flex gap-2 mb-2">
+                                        <span>金额:{request.money}</span>
+                                        <span>年份:{request.year || '未填写'}</span>
+                                        <span>国家:{request.country || '未填写'}</span>
+                                    </div>
+                                    {request.photo && (
+                                        <img
+                                            src={`http://localhost:8080${request.photo}`}
+                                            alt="求助帖"
+                                            className="w-32 h-auto mb-2"
+                                        />
+                                    )}
+                                    <div className="flex gap-2">
+                                        <input
+                                            type="number"
+                                            placeholder="新金额"
+                                            onChange={(e) => handleUpdateMoney(request.requestid, e.target.value)}
+                                            className="border p-1 flex-1"
+                                        />
+                                        <button
+                                            onClick={() => handleDelete(request.requestid)}
+                                            className="bg-red-500 text-white p-1 px-2 rounded"
+                                        >
+                                            删除
+                                        </button>
+                                        <button
+                                            onClick={() => handleUploadLoaduser(request.name)}
+                                            className="bg-blue-500 text-white p-1 px-2 rounded"
+                                        >
+                                            上传更新loaduser
+                                        </button>
+                                    </div>
+                                </div>
+                            ))}
+                        </div>
+                    )}
+                </div>
+            )}
+
+            {/* 我的求助帖展示(无搜索结果时显示) */}
+            {searchedRequests.length === 0 && (
+                <div className="mb-6">
+                    <h3 className="text-xl font-semibold mb-2">我的求助帖</h3>
+                    {requests.length === 0 ? (
+                        <p className="text-gray-500">暂无求助帖</p>
+                    ) : (
+                        <div className="grid grid-cols-1 gap-4">
+                            {requests.map((request) => (
+                                <div key={request.requestid} className="border p-3 rounded shadow">
+                                    <h4 className="text-lg font-semibold">{request.name}</h4>
+                                    <p className="text-gray-600 mb-2">{request.plot}</p>
+                                    <div className="flex gap-2 mb-2">
+                                        <span>金额:{request.money}</span>
+                                        <span>年份:{request.year || '未填写'}</span>
+                                        <span>国家:{request.country || '未填写'}</span>
+                                    </div>
+                                    {request.photo && (
+                                        <img
+                                            src={`http://localhost:8080${request.photo}`}
+                                            alt="求助帖"
+                                            className="w-32 h-auto mb-2"
+                                        />
+                                    )}
+                                    <div className="flex gap-2">
+                                        <input
+                                            type="number"
+                                            placeholder="新金额"
+                                            onChange={(e) => handleUpdateMoney(request.requestid, e.target.value)}
+                                            className="border p-1 flex-1"
+                                        />
+                                        <button
+                                            onClick={() => handleDelete(request.requestid)}
+                                            className="bg-red-500 text-white p-1 px-2 rounded"
+                                        >
+                                            删除
+                                        </button>
+                                        <button
+                                            onClick={() => handleUploadLoaduser(request.name)}
+                                            className="bg-blue-500 text-white p-1 px-2 rounded"
+                                        >
+                                            上传更新loaduser
+                                        </button>
+                                    </div>
+                                </div>
+                            ))}
+                        </div>
+                    )}
+                </div>
+            )}
+        </div>
+    );
+};
+
+export default RequestBoard;