add resource manage

Change-Id: Ib26c45ca71347e1a314d053b7a3c62cf90bb78ae
diff --git a/src/app/user/manage/resources/page.tsx b/src/app/user/manage/resources/page.tsx
index c48b626..6c18cf0 100644
--- a/src/app/user/manage/resources/page.tsx
+++ b/src/app/user/manage/resources/page.tsx
@@ -1,12 +1,384 @@
 'use client';
-import React from 'react';
+import React, {useEffect, useRef, useState} from 'react';
+// import {TabView, TabPanel} from "primereact/tabview";
+import {Card} from "primereact/card";
+import {Image} from "primereact/image";
+import {Button} from "primereact/button";
+// 弹窗
+import { Dialog } from 'primereact/dialog';
+import {InputText} from "primereact/inputtext";
+import {InputTextarea} from "primereact/inputtextarea";
+import {FileUpload} from "primereact/fileupload";
+// 类型转换
+import {toNumber} from "lodash";
+// 消息提醒
+import {Toast} from 'primereact/toast';
+// 接口传输
+import axios from "axios";
+// 页面跳转
+import {useRouter} from "next/navigation";
+// 分页
+import { Paginator, type PaginatorPageChangeEvent } from 'primereact/paginator';
+// 密码
+import { Password } from 'primereact/password';
+// 样式
+import './resources.scss';
 
-const EmptyPage: React.FC = () => {
-  return (
-    <div className="p-d-flex p-jc-center p-ai-center" style={{ height: '100vh' }}>
-      {"一个空页面"}
-    </div>
-  );
+
+
+// 用户发布的资源
+interface Resource {
+    resourceId: number;
+    resourceName: string;
+    resourcePicture: string;
+    resourceSummary: string; // 资源简介(一句话)
+    resourceDetail: string; // 资源介绍
+    uploadTime: string; // 上传时间
+    lastUpdateTime: string; // 最近更新时间
+    price: number;
+    downloads: number;
+    likes: number;
+    collections: number;
+    comments: number;
+    seeds: number; // 种子数
+    classify: string; // 资源分类(材质包:resourcePack,模组:mod,整合包:modPack ,地图:map
+}
+
+// 用户发布的资源列表
+interface ResourceList {
+    records: Resource[];
+    total: number; // 总记录数
+    pages: number; // 总页数
+    current: number; // 当前页码
+    sizes: number; // 每页大小
+}
+
+export default function UserManageResources() {
+    // 路由
+    const router = useRouter();
+    // 发布资源列表
+    const [resourceList, setResourceList] = useState<Resource[]>([]);
+    // 要删除资源的id
+    const [deleteResourceId, setDeleteResourceId] =  useState<number>(0);
+    // 资源封面路径
+    const [resourcePictureUrl, setResourcePictureUrl] = useState<string>('');
+    // 编辑资源的分类
+    const [resourceClassify, setResourceClassify] = useState<string>('');
+    // 消息提醒
+    const toast = useRef<Toast>(null);
+    // 分页
+    const [first, setFirst] = useState(0);
+    const [rows, setRows] = useState(5);
+    const [totalResources, setTotalResources] = useState<number>(0);
+    const onPageChange = (event: PaginatorPageChangeEvent) => {
+        setFirst(event.first);
+        setRows(event.rows);
+    };
+    // 删除资源弹窗
+    const [deleteVisible, setDeleteVisible] = useState(false);
+    const [deleteResourceFormData, setDeleteResourceFormData] = useState({
+        password: '',
+    });
+
+    // 编辑资源弹窗
+    const [editVisible, setEditVisible] = useState(false);
+    const [editResourceFormData, setEditResourceFormData] = useState({
+        resourceId: 0,
+        resourceName: '',
+        resourceSummary: '',
+        resourceDetail: '',
+        price: '',
+    });
+
+    useEffect(() => {
+        fetchResourceList();
+    }, [first, rows]);
+
+
+    // 获取用户发布资源
+    const fetchResourceList = async () => {
+        try {
+            const pageNumber = first / rows + 1;
+            const response = await axios.get<ResourceList>(process.env.PUBLIC_URL + `/user/upload`, {
+                params: {userId: 22301010, pageNumber: pageNumber, rows: rows}
+            });
+
+            console.log('获取发布资源列表:', response.data.records);
+            setResourceList(response.data.records);
+            setTotalResources(response.data.total);
+        } catch (err) {
+            console.error('获取发布资源失败', err);
+            toast.current?.show({severity: 'error', summary: 'error', detail: '获取发布资源失败'});
+        }
+    };
+
+    // 处理删除资源接口
+    const handleDeleteSubmit = async () => {
+        try {
+            const deleteData = {
+                resourceId: deleteResourceId,
+                userId: 223010100,
+                password: deleteResourceFormData.password,
+            };
+            // 发送DELETE请求
+            const response = await axios.delete(process.env.PUBLIC_URL + `/resource`, {
+                params: {resourceId: deleteData.resourceId, userId: deleteData.userId, password: deleteData.password},
+            });
+            console.log("用户" + 22301010 + "要删除" + deleteData.resourceId + "号资源");
+            console.log(deleteData);
+            console.log(response);
+            console.log(response.status)
+
+            if (response.status === 204) {
+                console.log("用户成功删除资源");
+                // setIsDeleteResource(true);
+                toast.current?.show({severity: 'success', summary: 'Success', detail: '删除资源成功'});
+                setDeleteVisible(false);
+                // 重置表单
+                setDeleteResourceFormData({
+                    password: '',
+                });
+                // 重新拉取资源列表
+                fetchResourceList();
+            } else {
+                console.log('用户密码错误');
+                toast.current?.show({severity: 'error', summary: 'Error', detail: '密码错误,删除资源失败'});
+            }
+
+        } catch (error) {
+            console.error('资源删除失败:', error);
+            toast.current?.show({ severity: 'error', summary: 'error', detail: '密码错误,资源删除失败' });
+        }
+    };
+
+    // 处理编辑资源接口
+    const handleEditSubmit = async () => {
+        try {
+            const postData = {
+                resourceId: editResourceFormData.resourceId,
+                resourceName: editResourceFormData.resourceName,
+                resourcePicture: resourcePictureUrl,
+                resourceSummary: editResourceFormData.resourceSummary,
+                resourceDetail: editResourceFormData.resourceDetail,
+                price: toNumber(editResourceFormData.price),
+                classify: resourceClassify,
+            };
+            // 发送POST请求
+            const response = await axios.put(process.env.PUBLIC_URL + '/resource/info', postData);
+            console.log("编辑资源的信息:", postData);
+
+            if (response.status === 200) {
+                toast.current?.show({ severity: 'success', summary: 'Success', detail: '资源编辑成功' });
+                // 编辑成功
+                setEditVisible(false);
+                fetchResourceList();
+            }
+        } catch (error) {
+            console.error('资源上传失败:', error);
+            toast.current?.show({ severity: 'error', summary: 'error', detail: '资源上传失败' });
+        }
+    };
+
+    return (
+        <div className="resources-container">
+            <Toast ref={toast}></Toast>
+            <div className="resources-title">
+                <h1>我上传的资源</h1>
+            </div>
+
+            <div className="resource-list">
+                {resourceList.map((resourceList) => (
+                    <Card key={resourceList.resourceId} className="resources-list-card"
+                          onClick={() => router.push(`/resource/resource-detail/${resourceList.resourceId}`)}>
+                        <Image alt="avatar"
+                               src={process.env.NEXT_PUBLIC_NGINX_URL + "resource/" + resourceList.resourcePicture}
+                               className="resource-avatar" width="250" height="140"/>
+                        <div className="resource-header">
+                            <div className="resource-content">
+                                <h3>{resourceList.resourceName}</h3>
+                            </div>
+
+                            <div className="resource-operation">
+                                <Button
+                                    label="编辑"
+                                    onClick={(e) => {
+                                        e.stopPropagation(); // 关键修复:阻止事件冒泡,避免触发Card的点击事件
+                                        setEditVisible(true);
+                                        
+                                        setResourceClassify(resourceList.classify);
+                                        setEditResourceFormData({
+                                            resourceId: resourceList.resourceId,
+                                            resourceName: resourceList.resourceName,
+                                            resourceSummary: resourceList.resourceSummary,
+                                            resourceDetail: resourceList.resourceDetail,
+                                            price: resourceList.price.toString(),
+                                        });
+                                        console.log("用户编辑资源");
+                                    }}
+                                />
+                                <Button
+                                    label="删除"
+                                    onClick={(e) => {
+                                        e.stopPropagation(); // 关键修复:阻止事件冒泡,避免触发Card的点击事件
+                                        setDeleteResourceId(resourceList.resourceId);
+                                        setDeleteVisible(true);
+                                    }}
+                                    style={{backgroundColor: "rgba(255, 87, 51, 1)"}}
+                                />
+                            </div>
+                        </div>
+                    </Card>
+                ))}
+                {totalResources > 5 && <Paginator
+                    className="Paginator"
+                    first={first}
+                    rows={rows}
+                    totalRecords={totalResources}
+                    rowsPerPageOptions={[5, 10]}
+                    onPageChange={onPageChange}
+                />}
+            </div>
+
+            {/*删除资源时,获取用户密码弹窗*/}
+            <Dialog
+                header="删除资源"
+                visible={deleteVisible}
+                onHide={() => setDeleteVisible(false)}
+                className="resource-delete-dialog"
+                modal
+                footer={
+                    <div className="dialog-footer">
+                        <Button label="确认" icon="pi pi-check" onClick={handleDeleteSubmit} autoFocus />
+                        <Button label="取消" icon="pi pi-times" onClick={() => setDeleteVisible(false)} className="p-button-text" />
+                    </div>
+                }
+            >
+                <div className="dialog-form">
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="name">密码</label>
+                        </div>
+                        <Password
+                            id="passwrod"
+                            value={deleteResourceFormData.password}
+                            onChange={(e) => setDeleteResourceFormData(prev => ({
+                                ...prev,
+                                password: e.target.value
+                            }))}
+                            placeholder="请输入密码"
+                            className="w-full"
+                            toggleMask
+                        />
+                    </div>
+                </div>
+            </Dialog>
+
+            {/*编辑资源弹窗*/}
+            <Dialog
+                header="编辑资源"
+                visible={editVisible}
+                onHide={() => setEditVisible(false)}
+                className="resource-edit-dialog"
+                modal
+                footer={
+                    <div className="dialog-footer">
+                        <Button label="确认" icon="pi pi-check" onClick={handleEditSubmit} autoFocus />
+                        <Button label="取消" icon="pi pi-times" onClick={() => setEditVisible(false)} className="p-button-text" />
+                    </div>
+                }
+            >
+                <div className="dialog-form">
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="name">资源名称</label>
+                        </div>
+                        <InputText
+                            id="name"
+                            value={editResourceFormData.resourceName}
+                            onChange={(e) => setEditResourceFormData(prev => ({
+                                ...prev,
+                                resourceName:  e.target.value
+                            }))}
+                            className="w-full"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="summary">资源简介</label>
+                        </div>
+                        <InputText
+                            id="summary"
+                            value={editResourceFormData.resourceSummary}
+                            onChange={(e) => setEditResourceFormData(prev => ({
+                                ...prev,
+                                resourceSummary:  e.target.value
+                            }))}
+                            className="w-full"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="detail">资源介绍</label>
+                        </div>
+                        <InputTextarea
+                            id="detail"
+                            value={editResourceFormData.resourceDetail}
+                            onChange={(e) => setEditResourceFormData(prev => ({
+                                ...prev,
+                                resourceDetail:  e.target.value
+                            }))}
+                            rows={5}
+                            className="w-full"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="price">价格</label>
+                        </div>
+                        <InputText
+                            id="price"
+                            value={editResourceFormData?.price.toString()}
+                            onChange={(e) => setEditResourceFormData(prev => ({
+                                ...prev,
+                                price:  e.target.value
+                            }))}
+                            className="w-full"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label>封面图片</label>
+                        </div>
+
+                        <FileUpload
+                            mode="advanced"
+                            name="resource-image"
+                            customUpload
+
+                            uploadHandler={async (e) => {
+                                const formData = new FormData();
+                                formData.append("file", e.files[0]);
+
+                                try {
+                                    const res = await axios.post(`${process.env.PUBLIC_URL}/file`, formData);
+
+                                    const fileUrl = res.data.url;
+                                    console.log(fileUrl);
+                                    setResourcePictureUrl(fileUrl);
+                                    toast.current?.show({ severity: 'success', summary: '上传成功' });
+                                } catch (error) {
+                                    console.log(error);
+                                    toast.current?.show({ severity: 'error', summary: '上传失败' });
+                                }
+                            }}
+                            auto
+                            accept="image/*"
+                            chooseLabel="选择资源封面"
+                        />
+                    </div>
+                </div>
+            </Dialog>
+        </div>
+    )
 };
-
-export default EmptyPage;