blob: 0bfa18445ce333bd58026a2d9b4d7a8a04c8322a [file] [log] [blame]
'use client';
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 { useLocalStorage } from '../../../hook/useLocalStorage';
// 样式
import './resources.scss';
interface User {
Id: number;
}
// 用户发布的资源
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 user = useLocalStorage<User>('user');
const userId: number = user?.Id ?? -1;
// 路由
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, 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,
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("用户" + userId + "要删除" + deleteData.resourceId + "号资源");
console.log(deleteData);
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={ "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>
)
};