Docker

Change-Id: I2aefd96a43bcf3a3c41c079ecfc04a3fee48bed6
diff --git a/src/views/upload/upload.module.css b/src/views/upload/upload.module.css
new file mode 100644
index 0000000..5a9952a
--- /dev/null
+++ b/src/views/upload/upload.module.css
@@ -0,0 +1,150 @@
+.container {
+  background-color: var(--card-bg);
+  padding: 32px;
+  border-radius: 12px;
+  width: 100%;
+  height: 100%;
+  margin: auto;
+  border: 1px solid var(--border-color);
+  color: var(--text-color);
+}
+
+.formGroup {
+  margin-bottom: 20px;
+}
+
+.input,
+.select,
+.textarea {
+  width: 100%;
+  padding: 8px 12px;
+  margin-top: 4px;
+  border: 1px solid var(--border-color);
+  border-radius: 8px;
+  background-color: var(--bg-color);
+  color: var(--text-color);
+}
+
+.upload {
+  margin-top: 8px;
+}
+
+.textarea {
+  height: 100px;
+  resize: none;
+}
+
+.charCount {
+  text-align: right;
+  font-size: 12px;
+  color: var(--text-color);
+}
+
+.requirement {
+  font-size: 14px;
+  color: var(--primary-color);
+  margin-bottom: 12px;
+}
+
+.checkbox {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 20px;
+}
+
+.submitBtn {
+  background-color: var(--primary-color);
+  color: white;
+  border: none;
+  padding: 10px 20px;
+  border-radius: 8px;
+  cursor: pointer;
+  transition: background-color 0.3s ease;
+}
+
+.submitBtn:hover {
+  background-color: var(--primary-hover);
+}
+
+
+.wrapper {
+  display: flex;
+  justify-content: center;
+  margin-top: 50px;
+}
+
+.form {
+  width: 400px;
+  background: #ffffff;
+  border: 1px solid #ddd;
+  border-radius: 12px;
+  padding: 24px;
+  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
+}
+
+.title {
+  font-size: 22px;
+  margin-bottom: 20px;
+  text-align: center;
+}
+
+.input,
+.textarea {
+  width: 100%;
+  padding: 10px;
+  margin-bottom: 16px;
+  border-radius: 6px;
+  border: 1px solid #ccc;
+  font-size: 14px;
+}
+
+.textarea {
+  resize: vertical;
+  height: 100px;
+}
+
+.uploadArea {
+  padding: 12px;
+  border: 2px dashed #999;
+  border-radius: 8px;
+  text-align: center;
+  cursor: pointer;
+  background: #f9f9f9;
+  margin-bottom: 16px;
+  transition: all 0.2s;
+}
+
+.uploadArea:hover {
+  background: #f0f0f0;
+  border-color: #666;
+}
+
+.fileName {
+  margin-top: 8px;
+  font-size: 14px;
+  color: #333;
+}
+
+.error {
+  color: red;
+  margin-bottom: 10px;
+  font-size: 14px;
+  text-align: center;
+}
+
+.uploadButton {
+  width: 100%;
+  padding: 10px;
+  background-color: #409eff;
+  color: white;
+  border: none;
+  border-radius: 6px;
+  font-size: 16px;
+  cursor: pointer;
+  transition: background-color 0.3s;
+}
+
+.uploadButton:hover {
+  background-color: #317ee7;
+}
diff --git a/src/views/upload/upload.tsx b/src/views/upload/upload.tsx
new file mode 100644
index 0000000..4a60330
--- /dev/null
+++ b/src/views/upload/upload.tsx
@@ -0,0 +1,123 @@
+import instance from '@/utils/axios';
+import React, { useState } from 'react';
+import styles from './upload.module.css';
+import { Upload } from '@/api/upload';
+import { useNavigate } from 'react-router-dom'; // 用于跳转
+
+const PostDetails = () => {
+  const [postTitle, setPostTitle] = useState('');
+  const [postType, setPostType] = useState('');
+  const [postContent, setPostContent] = useState('');
+  const [isChecked, setIsChecked] = useState(false);
+
+  const navigate = useNavigate();
+
+  const handleSubmit = async () => {
+    if (!postTitle.trim() || !postType || !postContent.trim()) {
+      alert('请填写完整内容(资源名、类型、内容介绍)');
+      return;
+    }
+
+    if (!isChecked) {
+      alert('请先确认您已知晓以上内容');
+      return;
+    }
+
+    const payload = {
+      post: {
+        postId: 0,
+        userId: 0,
+        postTitle,
+        postContent,
+        createdAt: Date.now(),
+        postType,
+        viewCount: 0,
+        hotScore: 5,
+        lastCalculated: Date.now()
+      },
+      tagIds: [0]
+    };
+
+    try {
+      const res = await instance.post(Upload, payload);
+
+      console.log('mock返回内容:', res.code);
+
+      // 判断返回内容是否成功(根据你 mock 接口返回的 code 字段)
+      if (res.code !== 0) throw new Error('发布失败');
+
+      alert('发布成功!');
+      navigate(-1); // 返回上一页(homepage)
+    } catch (error) {
+      alert('发布失败,请稍后重试');
+      console.error(error);
+    }
+  };
+
+  return (
+    <div className={styles.container}>
+      <div className={styles.formGroup}>
+        <label>资源名:</label>
+        <input
+          type="text"
+          value={postTitle}
+          placeholder="请输入文本"
+          onChange={(e) => setPostTitle(e.target.value)}
+          className={styles.input}
+        />
+      </div>
+
+      <div className={styles.formGroup}>
+        <label>类型选择:</label>
+        <select
+          value={postType}
+          onChange={(e) => setPostType(e.target.value)}
+          className={styles.select}
+        >
+          <option value="">下拉选择</option>
+          <option value="type1">类型一</option>
+          <option value="type2">类型二</option>
+        </select>
+      </div>
+
+      {/* 暂时移除上传文件表单 */}
+      {/* <div className={styles.formGroup}>
+        <label>上传资源:</label>
+        <input
+          type="file"
+          onChange={(e) => setFile(e.target.files?.[0] || null)}
+          className={styles.upload}
+        />
+      </div> */}
+
+      <div className={styles.formGroup}>
+        <label>内容介绍:</label>
+        <textarea
+          placeholder="请输入内容介绍"
+          value={postContent}
+          onChange={(e) => setPostContent(e.target.value)}
+          maxLength={200}
+          className={styles.textarea}
+        />
+        <div className={styles.charCount}>{postContent.length}/200</div>
+      </div>
+
+      <div className={styles.requirement}>【发布内容要求】</div>
+
+      <div className={styles.checkbox}>
+        <input
+          type="checkbox"
+          checked={isChecked}
+          onChange={() => setIsChecked(!isChecked)}
+        />
+        <span>我已知晓以上内容</span>
+      </div>
+
+      <button onClick={handleSubmit} className={styles.submitBtn}>
+        我已知晓
+      </button>
+    </div>
+  );
+};
+
+export default PostDetails;