add upload resource

Change-Id: I35f0f32f053f424c8dc03629e833e3f984389865
diff --git a/src/app/user/page.tsx b/src/app/user/page.tsx
index 0af92a4..7a1b631 100644
--- a/src/app/user/page.tsx
+++ b/src/app/user/page.tsx
@@ -6,6 +6,15 @@
 import { Button } from 'primereact/button';
 import { Card } from 'primereact/card';
 import {Image} from "primereact/image";
+// 发布资源
+import { Dialog } from 'primereact/dialog';
+import {InputText} from "primereact/inputtext";
+import {InputTextarea} from "primereact/inputtextarea";
+import {FileUpload} from "primereact/fileupload";
+// 资源分类
+import { RadioButton, RadioButtonChangeEvent } from "primereact/radiobutton";
+// 资源标签
+import { MultiSelect, MultiSelectChangeEvent } from 'primereact/multiselect';
 // 浮动按钮
 import { SpeedDial } from 'primereact/speeddial';
 // 评分图标
@@ -14,15 +23,13 @@
 import { Toast } from 'primereact/toast';
 // 页面跳转
 import { useRouter } from "next/navigation";
-// import Link from 'next/link';
 
 // 接口传输
 import axios from "axios";
 
 // 样式
 import './user.scss';
-
-
+import {toNumber} from "lodash";
 
 // 用户信息
 interface UserInfo {
@@ -46,7 +53,7 @@
     seedPercentageList: number[]; // 上传资源类型百分比列表,按材质包、模组、整合包、地图的顺序返回
 }
 
-// 用户发布的资源
+// 用户发布过的资源
 interface Resource {
     resourceId: number;
     resourceName: string;
@@ -64,11 +71,34 @@
     classify: string; // 资源分类(材质包:resourcePack,模组:mod,整合包:modPack ,地图:map
 }
 
-// 用户发布的资源列表
+// 用户发布过的资源列表
 interface ResourceList {
     records: Resource[];
 }
 
+// 资源标签
+interface GameplayOption {
+    name: string;
+    code: number;
+}
+
+// 资源标签选项
+const gameplayOptions: GameplayOption[] = [
+    { name: '科技', code: 1 },
+    { name: '魔法', code: 2 },
+    { name: '建筑', code: 3 },
+    { name: '风景', code: 4 },
+    { name: '竞技', code: 5 },
+    { name: '生存', code: 6 },
+    { name: '冒险', code: 7 },
+    { name: '跑酷', code: 8 },
+    { name: '艺术', code: 9 },
+    { name: '剧情', code: 10 },
+    { name: '社交', code: 11 },
+    { name: '策略', code: 12 },
+    { name: '极限', code: 13 }
+];
+
 export default function UserPage() {
     // 路由
     const router = useRouter();
@@ -80,7 +110,10 @@
     const [userData, setUserData] = useState<UserData>();
     // 消息提醒
     const toast = useRef<Toast>(null);
-
+    // 资源标签
+    const [selectedGameplay, setSelectedGameplay] = useState<GameplayOption[]>([]);
+    // 判断用户是否上传资源封面
+    const [isUploadPicture, setIsUploadPicture] = useState<boolean>(false);
 
     useEffect(() => {
         fetchUserInfo();
@@ -165,7 +198,7 @@
         },
         {
             template: () => (
-                <Button  label="发布资源" onClick={() => router.push(`/user/manage/resources/`)}/>
+                <Button  label="发布资源" onClick={() => setVisible(true)}/>
             )
         },
         {
@@ -175,12 +208,125 @@
         }
     ];
 
+    // 发布资源弹窗
+    const [visible, setVisible] = useState(false);
+    const [resourceFormData, setResourceFormData] = useState({
+        resource: {
+            resourceName: '',
+            resourcePicture: '',
+            resourceSummary: '',
+            resourceDetail: '',
+            uploadTime: '',
+            lastUpdateTime: '',
+            price: '',
+            classify: '',
+        },
+        gameplayList: [''],
+        completeRewardId: null,
+        userId: 0,
+    });
+    const [ingredient, setIngredient] = useState<string>('');
+
+
+    // 图片上传消息通知
+    const onUpload = () => {
+        setIsUploadPicture(true);
+        toast.current?.show({ severity: 'info', summary: 'Success', detail: 'File Uploaded' });
+    };
+
+    // 上传资源接口
+    const handleSubmit = async () => {
+        try {
+            // 规定用户必须输入的内容
+            if (resourceFormData.resource.resourceName == '') {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源名称' });
+                return;
+            }
+            if (resourceFormData.resource.resourceSummary == '') {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源简介' });
+                return;
+            }
+            if (resourceFormData.resource.price == '') {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源价格' });
+                return;
+            }
+            if (resourceFormData.resource.classify == '') {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源分类' });
+                return;
+            }
+            if (
+                resourceFormData.gameplayList.length === 1 &&
+                resourceFormData.gameplayList[0] === ''
+            ) {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源标签' });
+                return;
+            }
+            if (!isUploadPicture) {
+                toast.current?.show({ severity: 'info', summary: 'error', detail: '缺少资源封面' });
+                return;
+            }
+
+            const currentDate = new Date().toISOString().split('T')[0];
+            const postData = {
+                resource: {
+                    resourceName: resourceFormData.resource.resourceName,
+                    resourcePicture: resourceFormData.resource.resourcePicture,
+                    resourceSummary: resourceFormData.resource.resourceSummary,
+                    resourceDetail: resourceFormData.resource.resourceDetail,
+                    uploadTime: currentDate,
+                    lastUpdateTime: currentDate,
+                    price: toNumber(resourceFormData.resource.price),
+                    classify: resourceFormData.resource.classify,
+                },
+                gameplayList: resourceFormData.gameplayList,
+                completeRewardId: null,
+                userId: 22301010, // 记得用户登录状态获取
+            };
+            // 发送POST请求
+            const response = await axios.post(process.env.PUBLIC_URL + '/resource', postData);
+            console.log("上传资源的信息:", postData);
+
+            if (response.status === 200) {
+                toast.current?.show({ severity: 'success', summary: 'Success', detail: '资源上传成功' });
+                // 上传成功
+                setVisible(false);
+                // 重置表单
+                setResourceFormData({
+                    resource: {
+                        resourceName: '',
+                        resourcePicture: '',
+                        resourceSummary: '',
+                        resourceDetail: '',
+                        uploadTime: '',
+                        lastUpdateTime: '',
+                        price: '',
+                        classify: '',
+                    },
+                    gameplayList: [],
+                    completeRewardId: null,
+                    userId: 0,
+                });
+                // 重置资源分类
+                setIngredient("");
+                // 重置资源标签
+                setSelectedGameplay([]);
+                // 重置上传封面状态
+                setIsUploadPicture(false);
+                // 可以刷新资源列表
+                // fetchResourceList();
+            }
+        } catch (error) {
+            console.error('资源上传失败:', error);
+            toast.current?.show({ severity: 'error', summary: 'error', detail: '资源上传失败' });
+        }
+    };
+
 
 
 
     return (
         <div className="user-container">
-
+            <Toast ref={toast}></Toast>
             {/*个人信息*/}
             <div className="user-profile-card">
                 <Avatar
@@ -350,6 +496,234 @@
                 />
             </div>
 
+            {/*发布资源弹窗*/}
+            <Dialog
+                header="发布资源"
+                visible={visible}
+                onHide={() => setVisible(false)}
+                className="publish-dialog"
+                modal
+                footer={
+                    <div className="dialog-footer">
+                        <Button label="发布" icon="pi pi-check" onClick={handleSubmit} autoFocus />
+                        <Button label="取消" icon="pi pi-times" onClick={() => setVisible(false)} className="p-button-text" />
+                    </div>
+                }
+            >
+                <div className="publish-form">
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label htmlFor="name">资源名称</label>
+                        </div>
+                        <InputText
+                            id="name"
+                            value={resourceFormData.resource.resourceName}
+                            onChange={(e) => setResourceFormData(prev => ({
+                                ...prev, // 复制顶层所有属性
+                                resource: {
+                                    ...prev.resource, // 复制resource对象的所有属性
+                                    resourceName: e.target.value  // 只更新resourceName
+                                }
+                            }))}
+                            placeholder="请输入资源名称"
+                            className="w-full"
+                            required
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label htmlFor="summary">资源简介</label>
+                        </div>
+                        <InputText
+                            id="summary"
+                            value={resourceFormData.resource.resourceSummary}
+                            onChange={(e) => setResourceFormData(prev => ({
+                                ...prev, // 复制顶层所有属性
+                                resource: {
+                                    ...prev.resource, // 复制resource对象的所有属性
+                                    resourceSummary: e.target.value
+                                }
+                            }))}
+                            placeholder="请输入资源简介(一句话)"
+                            className="w-full"
+                            required
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <label htmlFor="detail">资源介绍</label>
+                        </div>
+                        <InputTextarea
+                            id="detail"
+                            value={resourceFormData.resource.resourceDetail}
+                            onChange={(e) => setResourceFormData(prev => ({
+                                ...prev, // 复制顶层所有属性
+                                resource: {
+                                    ...prev.resource, // 复制resource对象的所有属性
+                                    resourceDetail: e.target.value
+                                }
+                            }))}
+                            rows={5}
+                            placeholder="请输入资源介绍"
+                            className="w-full"
+                            required
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label htmlFor="price">价格</label>
+                        </div>
+                        <InputText
+                            id="price"
+                            value={resourceFormData.resource.price}
+                            onChange={(e) => setResourceFormData(prev => ({
+                                ...prev, // 复制顶层所有属性
+                                resource: {
+                                    ...prev.resource, // 复制resource对象的所有属性
+                                    price: e.target.value
+                                }
+                            }))}
+                            placeholder="请输入资源价格"
+                            className="w-full"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label htmlFor="classify">资源分类(请选择一项)</label>
+                        </div>
+                        <div className="form-field-classify">
+                            <div className="flex align-items-center">
+                                <RadioButton
+                                    inputId="ingredient1"
+                                    name="pizza"
+                                    value="resourcePack"
+                                    onChange={(e: RadioButtonChangeEvent) => {
+                                        setResourceFormData(prev => ({
+                                            ...prev, // 复制顶层所有属性
+                                            resource: {
+                                                ...prev.resource, // 复制resource对象的所有属性
+                                                classify: e.target.value
+                                            }
+                                        }));
+                                        setIngredient(e.value);
+                                        console.log(ingredient);
+                                        // console.log(resourceFormData.resource.classify);
+                                    }}
+                                    checked={ingredient === 'resourcePack'}
+                                />
+                                <label htmlFor="ingredient1" className="ml-2">材质包</label>
+                            </div>
+                            <div className="flex align-items-center">
+                                <RadioButton
+                                    inputId="ingredient2"
+                                    name="pizza"
+                                    value="modPack"
+                                    onChange={(e: RadioButtonChangeEvent) => {
+                                        setResourceFormData(prev => ({
+                                            ...prev, // 复制顶层所有属性
+                                            resource: {
+                                                ...prev.resource, // 复制resource对象的所有属性
+                                                classify: e.target.value
+                                            }
+                                        }));
+                                        setIngredient(e.value);
+                                    }}
+                                    // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
+                                    checked={ingredient === 'modPack'}
+                                />
+                                <label htmlFor="ingredient2" className="ml-2">整合包</label>
+                            </div>
+                            <div className="flex align-items-center">
+                                <RadioButton
+                                    inputId="ingredient3"
+                                    name="pizza"
+                                    value="mod"
+                                    onChange={(e: RadioButtonChangeEvent) => {
+                                        setResourceFormData(prev => ({
+                                            ...prev, // 复制顶层所有属性
+                                            resource: {
+                                                ...prev.resource, // 复制resource对象的所有属性
+                                                classify: e.target.value
+                                            }
+                                        }));
+                                        setIngredient(e.value);
+                                    }}
+                                    // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
+                                    checked={ingredient === 'mod'}
+                                />
+                                <label htmlFor="ingredient3" className="ml-2">模组</label>
+                            </div>
+                            <div className="flex align-items-center">
+                                <RadioButton
+                                    inputId="ingredient4"
+                                    name="pizza"
+                                    value="map"
+                                    onChange={(e: RadioButtonChangeEvent) => {
+                                        setResourceFormData(prev => ({
+                                            ...prev, // 复制顶层所有属性
+                                            resource: {
+                                                ...prev.resource, // 复制resource对象的所有属性
+                                                classify: e.target.value
+                                            }
+                                        }));
+                                        setIngredient(e.value);
+                                    }}
+                                    // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
+                                    checked={ingredient === 'map'}
+                                />
+                                <label htmlFor="ingredient4" className="ml-2">地图</label>
+                            </div>
+                        </div>
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label htmlFor="gameplayList">资源标签</label>
+                        </div>
+                        <MultiSelect
+                            value={selectedGameplay}
+                            onChange={(e: MultiSelectChangeEvent) => {
+                                const selectedOptions = e.value as GameplayOption[];
+                                // 提取选中项的 name 属性组成字符串数组
+                                const selectedNames = selectedOptions.map(item => item.name);
+
+                                setResourceFormData(prev => ({
+                                    ...prev,
+                                    gameplayList: selectedNames
+                                }));
+                                setSelectedGameplay(selectedOptions);
+                            }}
+                            options={gameplayOptions}
+                            display="chip"
+                            optionLabel="name"
+                            placeholder="请选择资源标签"
+                            // maxSelectedLabels={3}
+                            className="w-full md:w-20rem"
+                        />
+                    </div>
+                    <div className="form-field">
+                        <div className="form-field-header">
+                            <span className="form-field-sign">*</span>
+                            <label>封面图片</label>
+                        </div>
+                        <FileUpload
+                            mode="basic"
+                            name="resource-image"
+                            url={process.env.PUBLIC_URL +"/file"} // 与后端交互的URL
+                            accept="image/*"
+                            maxFileSize={10000000000}
+                            chooseLabel="选择资源封面"
+                            className="w-full"
+                            onUpload={onUpload}
+                        />
+                    </div>
+                </div>
+            </Dialog>
+
         </div>
     );
 };