修改好友动态、发布动态、促销模块、创建帖子,Resolve review.
Change-Id: I84a2460dd1208bc703b0527d98225204d03e5efc
diff --git a/src/pages/AuthPage/AuthPage.css b/src/pages/AuthPage/AuthPage.css
index 5073ce3..cb9e470 100644
--- a/src/pages/AuthPage/AuthPage.css
+++ b/src/pages/AuthPage/AuthPage.css
@@ -4,7 +4,7 @@
justify-content: flex-end; /* 使卡片靠右 */
min-height: 100vh;
font-family: Arial, sans-serif;
- background-color: #5F4437; /* 设置背景颜色 */
+ background: linear-gradient(180deg, #5F4437, #823c3c);
padding: 0 2rem; /* 添加左右内边距 */
}
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.css b/src/pages/Forum/posts-detail/PostDetailPage.css
index 65584af..780492b 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.css
+++ b/src/pages/Forum/posts-detail/PostDetailPage.css
@@ -1,7 +1,5 @@
.post-detail-page {
- background-color: #4b322b;
- min-height: 100vh;
- padding: 32px 0;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
font-family: 'Helvetica Neue', sans-serif;
color: #333;
}
@@ -20,7 +18,7 @@
.post-detail h1 {
font-size: 24px;
margin-bottom: 16px;
- color: #4b322b;
+ color: #4A3B34;
}
.post-meta {
@@ -35,7 +33,7 @@
font-size: 20px;
line-height: 1.7;
margin-bottom: 20px;
- color: #4b322b;
+ color: #4A3B34;
}
/* 多图排列 */
@@ -60,7 +58,7 @@
border: none;
background: none;
cursor: pointer;
- color: #4b322b;
+ color: #4A3B34;
transition: transform 0.2s ease;
}
@@ -80,7 +78,7 @@
.comments-section h3 {
margin-bottom: 16px;
font-size: 20px;
- color: #4b322b;
+ color: #4A3B34;
background-color: #c4b3a3;
padding: 6px 12px;
border-radius: 8px;
@@ -168,7 +166,7 @@
}
.comment-options button:hover {
- background-color: #6d4e37;
+ background-color: #5F4437;
}
.error-text {
diff --git a/src/pages/Forum/posts-main/ForumPage.css b/src/pages/Forum/posts-main/ForumPage.css
index db3a654..8a7ae4c 100644
--- a/src/pages/Forum/posts-main/ForumPage.css
+++ b/src/pages/Forum/posts-main/ForumPage.css
@@ -1,6 +1,9 @@
.forum-page {
color: #fff;
- background-color: #5F4437;
+ /* background-color: #5F4437; */
+ /* background: linear-gradient(180deg, #5F4437, #9c737b); */
+ background: linear-gradient(180deg, #5F4437, #823c3c);
+ /* background-color: #5F4437; */
min-height: 100vh;
font-family: Arial, sans-serif;
}
@@ -97,8 +100,6 @@
.toolbar {
display: flex;
- /* justify-content: space-between;
- align-items: center; */
padding: 16px 20px;
}
diff --git a/src/pages/Forum/posts-main/ForumPage.jsx b/src/pages/Forum/posts-main/ForumPage.jsx
index 577d336..f3866ff 100644
--- a/src/pages/Forum/posts-main/ForumPage.jsx
+++ b/src/pages/Forum/posts-main/ForumPage.jsx
@@ -5,6 +5,7 @@
import CreatePostButton from './components/CreatePostButton';
import PostList from './components/PostList';
import './ForumPage.css';
+import Promotion from '../promotion-part/Promotion';
const ForumPage = () => {
const [searchQuery, setSearchQuery] = useState('');
@@ -16,6 +17,7 @@
return (
<div className="forum-page">
<Header />
+ <Promotion />
<div className="toolbar">
<CreatePostButton />
<SearchBar onSearch={handleSearch} />
diff --git a/src/pages/Forum/posts-main/components/CreatePostButton.css b/src/pages/Forum/posts-main/components/CreatePostButton.css
index b40b9e7..225ddde 100644
--- a/src/pages/Forum/posts-main/components/CreatePostButton.css
+++ b/src/pages/Forum/posts-main/components/CreatePostButton.css
@@ -1,19 +1,127 @@
.create-post {
- display: flex;
- justify-content: center;
- margin: 20px 0;
- }
-
- .create-btn {
- background-color: #BA929A;
- color: white;
- padding: 10px 20px;
- border-radius: 8px;
- border: none;
- cursor: pointer;
- font-size: 16px;
- transition: background-color 0.3s ease;
- }
+ display: flex;
+ justify-content: center;
+ margin: 20px 0;
+}
-
-
\ No newline at end of file
+.create-btn {
+ background-color: #BA929A;
+ color: white;
+ padding: 10px 20px;
+ border-radius: 8px;
+ border: none;
+ cursor: pointer;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ transition: background-color 0.3s ease;
+}
+
+.create-btn:hover {
+ background-color: #a17b83;
+}
+
+/* Modal 样式 */
+.cp-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0,0,0,0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+}
+
+.cp-modal-dialog {
+ background: #e9ded2;
+ padding: 20px;
+ width: 35%;
+ max-width: 500px;
+ border-radius: 8px;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+/* 标题 */
+.cp-modal-dialog h3 {
+ margin: 0;
+ color : #4A3B34;
+}
+
+/* 文本输入和文本域 —— 宽度保持 97%,一致感更强 */
+.cp-modal-dialog input[type="text"],
+.cp-modal-dialog textarea,
+.cp-modal-dialog input[type="file"] {
+ width: 97%;
+ padding: 8px;
+ font-size: 14px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+
+/* 文本域高度 */
+.cp-modal-dialog textarea {
+ resize: vertical;
+ min-height: 80px;
+}
+
+/* 文件选择按钮保持 label 方式,不变 */
+.file-label {
+ display: inline-block;
+ padding: 6px 10px;
+ background: #BA929A;
+ color: #fff;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+ user-select: none;
+ width : 12%;
+}
+
+.file-label:hover {
+ background: #a17b83;
+}
+
+/* 预览区 */
+.cp-preview {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.cp-preview img {
+ width: 80px;
+ height: 80px;
+ object-fit: cover;
+ border-radius: 4px;
+ border: 1px solid #bbb;
+}
+
+/* 按钮组 —— 同 .modal-actions */
+.cp-actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 10px;
+}
+
+.cp-actions .btn {
+ padding: 6px 12px;
+ font-size: 14px;
+ cursor: pointer;
+ border: none;
+ border-radius: 4px;
+}
+
+.cp-actions .btn.cancel {
+ background: #5F4437;
+ color: #fff;
+}
+
+.cp-actions .btn.submit {
+ background: #BA929A;
+ color: #fff;
+}
diff --git a/src/pages/Forum/posts-main/components/CreatePostButton.jsx b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
index 0632173..0390ee7 100644
--- a/src/pages/Forum/posts-main/components/CreatePostButton.jsx
+++ b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
@@ -1,21 +1,131 @@
-import React from 'react';
-import { useLocation } from 'wouter';
+import React, { useState } from 'react';
+import axios from 'axios';
import { Edit } from '@icon-park/react';
import './CreatePostButton.css';
-const CreatePostButton = () => {
- const [, navigate] = useLocation();
+const API_BASE = process.env.REACT_APP_API_BASE;
+const USER_ID = 456;
- const goToCreatePost = () => {
- navigate('/forum/create-post');
+const CreatePostButton = () => {
+ const [showModal, setShowModal] = useState(false);
+
+ // 表单字段
+ const [title, setTitle] = useState('');
+ const [content, setContent] = useState('');
+ const [previewUrls, setPreviewUrls] = useState([]);
+ const [imageUrls, setImageUrls] = useState([]);
+
+ // 处理文件选中:预览 & 上传
+ const handleImageChange = async (e) => {
+ const files = Array.from(e.target.files);
+ if (!files.length) return;
+ // 本地预览
+ setPreviewUrls(files.map(f => URL.createObjectURL(f)));
+
+ // 并发上传,假设 /upload 接口返回 { url: '...' }
+ try {
+ const uploaded = await Promise.all(
+ files.map(file => {
+ const fd = new FormData();
+ fd.append('file', file);
+ return axios.post(`${API_BASE}/upload`, fd, {
+ headers: { 'Content-Type': 'multipart/form-data' }
+ }).then(res => res.data.url);
+ })
+ );
+ setImageUrls(uploaded);
+ } catch (err) {
+ console.error('图片上传失败:', err);
+ alert('封面图上传失败,请重试');
+ }
+ };
+
+ // 提交发帖
+ const handleSubmit = async () => {
+ if (!title.trim() || !content.trim()) {
+ alert('标题和内容均为必填项');
+ return;
+ }
+
+ try {
+ await axios.post(
+ `${API_BASE}/echo/forum/posts/${USER_ID}/createPost`,
+ {
+ title: title.trim(),
+ post_content: content.trim(),
+ image_url: imageUrls
+ }
+ );
+ // 重置状态并关闭
+ setTitle('');
+ setContent('');
+ setPreviewUrls([]);
+ setImageUrls([]);
+ setShowModal(false);
+ alert('发帖成功');
+ // 如需刷新帖子列表,可在这里触发外部回调
+ } catch (err) {
+ console.error('发帖失败:', err.response?.data || err);
+ alert(err.response?.data?.error || '发帖失败,请稍后重试');
+ }
};
return (
- <div className="create-post">
- <button onClick={goToCreatePost} className="create-btn">
- <Edit theme="outline" size="18" /> 发帖
- </button>
- </div>
+ <>
+ <div className="create-post">
+ <button onClick={() => setShowModal(true)} className="create-btn">
+ <Edit theme="outline" size="18" style={{ marginRight: 6 }} />
+ 发帖
+ </button>
+ </div>
+
+ {showModal && (
+ <div className="cp-modal-overlay" onClick={() => setShowModal(false)}>
+ <div className="cp-modal-dialog" onClick={e => e.stopPropagation()}>
+ <h3>创建新帖子</h3>
+
+ <input
+ type="text"
+ placeholder="帖子标题"
+ value={title}
+ onChange={e => setTitle(e.target.value)}
+ />
+
+ <textarea
+ placeholder="正文内容"
+ value={content}
+ onChange={e => setContent(e.target.value)}
+ />
+
+ <label className="file-label">
+ 选择图片
+ <input
+ type="file"
+ accept="image/*"
+ multiple
+ onChange={handleImageChange}
+ style={{ display: 'none' }}
+ />
+ </label>
+
+ <div className="cp-preview">
+ {previewUrls.map((url, i) => (
+ <img key={i} src={url} alt={`封面预览 ${i}`} />
+ ))}
+ </div>
+
+ <div className="cp-actions">
+ <button className="btn cancel" onClick={() => setShowModal(false)}>
+ 取消
+ </button>
+ <button className="btn submit" onClick={handleSubmit}>
+ 发布
+ </button>
+ </div>
+ </div>
+ </div>
+ )}
+ </>
);
};
diff --git a/src/pages/Forum/posts-main/components/SearchBar.css b/src/pages/Forum/posts-main/components/SearchBar.css
index 60ba679..2a8349d 100644
--- a/src/pages/Forum/posts-main/components/SearchBar.css
+++ b/src/pages/Forum/posts-main/components/SearchBar.css
@@ -11,7 +11,7 @@
margin-right: -3px;
background-color: #e9ded2;
/* 文字颜色 */
- color: #4b322b;
+ color: #4A3B34;
padding: 8px 10px; /* 控制按钮的高度和宽度 */
font-size: 15px; /* 控制文字大小 */
}
diff --git a/src/pages/Forum/posts-main/components/SearchBar.jsx b/src/pages/Forum/posts-main/components/SearchBar.jsx
index 52b873d..281d578 100644
--- a/src/pages/Forum/posts-main/components/SearchBar.jsx
+++ b/src/pages/Forum/posts-main/components/SearchBar.jsx
@@ -16,7 +16,7 @@
type="text"
value={query}
onChange={e => setQuery(e.target.value)}
- placeholder="标题"
+ placeholder="输入要搜索的帖子"
className="search-input"
/>
<button onClick={handleSearch} className="search-btn">搜索</button>
diff --git a/src/pages/Forum/promotion-part/Promotion.css b/src/pages/Forum/promotion-part/Promotion.css
new file mode 100644
index 0000000..2232ba5
--- /dev/null
+++ b/src/pages/Forum/promotion-part/Promotion.css
@@ -0,0 +1,110 @@
+.promotion-container {
+ padding: 20px;
+ margin: 20px 0;
+ border-radius: 8px;
+}
+
+/* 并排两列 */
+.carousel-container {
+ display: flex;
+ gap: 20px;
+}
+
+.carousel-section {
+ flex: 1;
+}
+
+.carousel-section h2 {
+ font-size: 20px;
+ margin-bottom: 15px;
+}
+
+/* 轮播框架 */
+.carousel {
+ position: relative;
+ /* background: #a54747; */
+ /* background: linear-gradient(135deg, #4A3B34, #a54747); */
+ /* background: linear-gradient(135deg, #e38f77, #aa3e3e); */
+ /* 背景渐变 */
+ background: linear-gradient(135deg, #e1cab2, #b68791);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+ border-radius: 6px;
+ padding: 15px;
+ color: #fff;
+ min-height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 左右箭头 */
+.carousel .arrow {
+ background: rgba(0,0,0,0.2);
+ border: none;
+ color: #fff;
+ font-size: 24px;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ cursor: pointer;
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.carousel .arrow.left {
+ left: 10px;
+}
+
+.carousel .arrow.right {
+ right: 10px;
+}
+
+.carousel .arrow:hover {
+ background: rgba(0,0,0,0.4);
+}
+
+/* 每帧内容 */
+.carousel .slide {
+ width: calc(100% - 80px);
+ /* 留出箭头空间 */
+ text-align: left;
+}
+
+/* 冷门资源专用 slide */
+.cold-slide {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+}
+
+/* 资源海报 */
+.resource-poster {
+ width: 80px;
+ height: 100px;
+ object-fit: cover;
+ border-radius: 4px;
+}
+
+/* 文本信息 */
+.resource-info div,
+.slide div {
+ margin-bottom: 6px;
+}
+
+/* 激励徽章 */
+.incentive-badge {
+ background-color: #17a2b8;
+ color: #d13c3c;
+ padding: 2px 8px;
+ margin-right: 6px;
+ font-size: 12px;
+ border-radius: 12px;
+}
+
+/* 空状态 */
+.empty-state {
+ color: #fff;
+ font-size: 16px;
+ text-align: center;
+}
diff --git a/src/pages/Forum/promotion-part/Promotion.jsx b/src/pages/Forum/promotion-part/Promotion.jsx
new file mode 100644
index 0000000..9af56bc
--- /dev/null
+++ b/src/pages/Forum/promotion-part/Promotion.jsx
@@ -0,0 +1,144 @@
+import React, { useEffect, useState, useRef } from 'react';
+import './Promotion.css';
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+
+const Promotion = () => {
+ const [promotions, setPromotions] = useState([]);
+ const [coldResources, setColdResources] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ // 轮播索引
+ const [promoIndex, setPromoIndex] = useState(0);
+ const [coldIndex, setColdIndex] = useState(0);
+
+ // 计时器引用,用于清理
+ const promoTimerRef = useRef(null);
+ const coldTimerRef = useRef(null);
+
+ useEffect(() => {
+ fetchData();
+ }, []);
+
+ // 自动轮播:促销活动
+ useEffect(() => {
+ if (promotions.length === 0) return;
+ // 清理旧的计时器
+ clearInterval(promoTimerRef.current);
+ promoTimerRef.current = setInterval(() => {
+ setPromoIndex(prev => (prev + 1) % promotions.length);
+ }, 5000);
+ return () => clearInterval(promoTimerRef.current);
+ }, [promotions]);
+
+ // 自动轮播:冷门资源
+ useEffect(() => {
+ if (coldResources.length === 0) return;
+ clearInterval(coldTimerRef.current);
+ coldTimerRef.current = setInterval(() => {
+ setColdIndex(prev => (prev + 1) % coldResources.length);
+ }, 5000);
+ return () => clearInterval(coldTimerRef.current);
+ }, [coldResources]);
+
+ const fetchData = async () => {
+ try {
+ const promoResponse = await fetch(`${API_BASE}/echo/promotions/active`);
+ const promoData = await promoResponse.json();
+ setPromotions(promoData);
+
+ const coldResponse = await fetch(`${API_BASE}/echo/resources/cold`);
+ const coldData = await coldResponse.json();
+ setColdResources(coldData);
+ } catch (error) {
+ console.error('获取数据失败:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return <div className="promotion-container">加载中...</div>;
+ }
+
+ // 手动切换
+ const prevPromo = () => setPromoIndex((promoIndex - 1 + promotions.length) % promotions.length);
+ const nextPromo = () => setPromoIndex((promoIndex + 1) % promotions.length);
+ const prevCold = () => setColdIndex((coldIndex - 1 + coldResources.length) % coldResources.length);
+ const nextCold = () => setColdIndex((coldIndex + 1) % coldResources.length);
+
+ const currentPromo = promotions[promoIndex];
+ const currentCold = coldResources[coldIndex];
+
+ return (
+ <div className="promotion-container carousel-container">
+ {/* 促销活动轮播 */}
+ <section className="carousel-section">
+ <h2>当前促销活动</h2>
+ {promotions.length === 0 ? (
+ <div className="empty-state">暂无促销活动</div>
+ ) : (
+ <div
+ className="carousel"
+ onMouseEnter={() => clearInterval(promoTimerRef.current)}
+ onMouseLeave={() => {
+ promoTimerRef.current = setInterval(() => {
+ setPromoIndex(prev => (prev + 1) % promotions.length);
+ }, 3000);
+ }}
+ >
+ <button className="arrow left" onClick={prevPromo}><</button>
+ <div className="slide">
+ <div><strong>种子类型:</strong>{currentPromo.category}</div>
+ <div><strong>促销时间:</strong>
+ {new Date(currentPromo.promotion_start_time).toLocaleString()} ~{' '}
+ {new Date(currentPromo.promotion_end_time).toLocaleString()}
+ </div>
+ <div><strong>下载折扣:</strong>{currentPromo.download_discount ?? '无'}</div>
+ <div><strong>上传奖励:</strong>{currentPromo.upload_reward ?? '无'}</div>
+ {currentPromo.description && (
+ <div><strong>详细描述:</strong>{currentPromo.description}</div>
+ )}
+ </div>
+ <button className="arrow right" onClick={nextPromo}>></button>
+ </div>
+ )}
+ </section>
+
+ {/* 冷门资源轮播 */}
+ <section className="carousel-section">
+ <h2>冷门资源推荐</h2>
+ {coldResources.length === 0 ? (
+ <div className="empty-state">暂无冷门资源推荐</div>
+ ) : (
+ <div
+ className="carousel"
+ onMouseEnter={() => clearInterval(coldTimerRef.current)}
+ onMouseLeave={() => {
+ coldTimerRef.current = setInterval(() => {
+ setColdIndex(prev => (prev + 1) % coldResources.length);
+ }, 3000);
+ }}
+ >
+ <button className="arrow left" onClick={prevCold}><</button>
+ <div className="slide cold-slide">
+ <img src={currentCold.poster} alt={currentCold.title} className="resource-poster" />
+ <div className="resource-info">
+ <div><strong>标题:</strong>{currentCold.title}</div>
+ <div><strong>下载量:</strong>{currentCold.download_count} | <strong>种子数:</strong>{currentCold.seed_count}</div>
+ <div><strong>激励:</strong>
+ {currentCold.incentives?.download_exempt && <span className="incentive-badge">免下载量</span>}
+ {currentCold.incentives?.extra_seed_bonus && <span className="incentive-badge">做种加成</span>}
+ {!(currentCold.incentives?.download_exempt || currentCold.incentives?.extra_seed_bonus) && '无'}
+ </div>
+ </div>
+ </div>
+ <button className="arrow right" onClick={nextCold}>></button>
+ </div>
+ )}
+ </section>
+ </div>
+ );
+};
+
+export default Promotion;
diff --git a/src/pages/FriendMoments/CreateMoment.css b/src/pages/FriendMoments/CreateMoment.css
new file mode 100644
index 0000000..ddbaf7b
--- /dev/null
+++ b/src/pages/FriendMoments/CreateMoment.css
@@ -0,0 +1,63 @@
+ /* .create-feed-page {
+ margin: 0 auto;
+ padding-bottom: 40px;
+ }
+
+ .cf-header {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-top: 20px;
+
+ }
+
+ .cf-header h3 {
+ margin: 0;
+ }
+
+ .cf-form {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ }
+
+ .cf-form input[type="text"],
+ .cf-form textarea {
+ width: 100%;
+ padding: 8px;
+ font-size: 14px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ }
+
+ .cf-form textarea {
+ min-height: 100px;
+ resize: vertical;
+ }
+
+ .cf-form input[type="file"] {
+ font-size: 14px;
+ }
+
+ .cf-preview {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ }
+
+ .cf-preview img {
+ width: 80px;
+ height: 80px;
+ object-fit: cover;
+ border-radius: 4px;
+ border: 1px solid #bbb;
+ }
+
+ .cf-submit-btn {
+ align-self: flex-end;
+ padding: 8px 16px;
+ font-size: 14px;
+ cursor: pointer;
+ background: #BA929A;
+ }
+ */
\ No newline at end of file
diff --git a/src/pages/FriendMoments/CreateMoment.jsx b/src/pages/FriendMoments/CreateMoment.jsx
new file mode 100644
index 0000000..4aca455
--- /dev/null
+++ b/src/pages/FriendMoments/CreateMoment.jsx
@@ -0,0 +1,206 @@
+// // import React, { useState } from 'react';
+// // import axios from 'axios';
+// // import { useNavigate } from 'react-router-dom';
+// // import './CreateMoment.css';
+// // import Header from '../../components/Header';
+
+// // const API_BASE = process.env.REACT_APP_API_BASE;
+// // const USER_ID = 456;
+
+// // const CreateMoment = () => {
+// // const [title, setTitle] = useState('');
+// // const [content, setContent] = useState('');
+// // const [previewUrls, setPreviewUrls] = useState([]);
+// // const [images, setImages] = useState([]);
+// // const navigate = useNavigate();
+
+// // const handleImageChange = async (e) => {
+// // const files = Array.from(e.target.files);
+// // if (!files.length) return;
+
+// // setPreviewUrls(files.map(f => URL.createObjectURL(f)));
+
+// // try {
+// // const uploaded = await Promise.all(
+// // files.map(file => uploadImageToServer(file))
+// // );
+// // setImages(uploaded);
+// // } catch (err) {
+// // console.error('图片上传失败:', err);
+// // alert('有图片上传失败,请重试');
+// // }
+// // };
+
+// // const uploadImageToServer = async (file) => {
+// // const formData = new FormData();
+// // formData.append('file', file);
+// // const res = await axios.post(`${API_BASE}/upload`, formData, {
+// // headers: {'Content-Type': 'multipart/form-data'}
+// // });
+// // return res.data.url;
+// // };
+
+// // const handleSubmit = async () => {
+// // if (!content.trim()) {
+// // alert('内容不能为空');
+// // return;
+// // }
+// // try {
+// // await axios.post(
+// // `${API_BASE}/echo/users/${USER_ID}/CreateMoment`,
+// // {
+// // title: title.trim() || undefined,
+// // friend_content: content.trim(),
+// // images
+// // }
+// // );
+// // navigate('/friend-moments');
+// // } catch (err) {
+// // console.error('发布失败:', err);
+// // alert('发布失败,请稍后重试');
+// // }
+// // };
+
+// // return (
+// // <div className="create-feed-page">
+// // <Header/>
+// // <div className="cf-header">
+// // <button onClick={() => navigate(-1)} style={{padding : '5px 10px', backgroundColor: '#BA929A', color: 'white'}}>返回</button>
+// // <h3>发布新动态</h3>
+// // </div>
+
+// // <div className="cf-form">
+// // <input
+// // type="text"
+// // placeholder="标题"
+// // value={title}
+// // onChange={e => setTitle(e.target.value)}
+// // />
+// // <textarea
+// // placeholder="写下你的内容..."
+// // value={content}
+// // onChange={e => setContent(e.target.value)}
+// // />
+// // <input
+// // type="file"
+// // accept="image/*"
+// // multiple
+// // onChange={handleImageChange}
+// // />
+// // <div className="cf-preview">
+// // {previewUrls.map((url, i) => (
+// // <img key={i} src={url} alt={`预览 ${i}`} />
+// // ))}
+// // </div>
+// // <button className="cf-submit-btn" onClick={handleSubmit}>
+// // 发布
+// // </button>
+// // </div>
+// // </div>
+// // );
+// // };
+
+// // export default CreateMoment;
+// import React, { useState } from 'react';
+// import axios from 'axios';
+// import { useNavigate } from 'react-router-dom';
+// import './CreateMoment.css';
+// import Header from '../../components/Header';
+
+// const API_BASE = process.env.REACT_APP_API_BASE;
+// const USER_ID = 456;
+
+// const CreateMoment = ({ onClose, fetchFeeds }) => {
+// const [title, setTitle] = useState('');
+// const [content, setContent] = useState('');
+// const [previewUrls, setPreviewUrls] = useState([]);
+// const [images, setImages] = useState([]);
+// const navigate = useNavigate();
+
+// const handleImageChange = async (e) => {
+// const files = Array.from(e.target.files);
+// if (!files.length) return;
+// setPreviewUrls(files.map(f => URL.createObjectURL(f)));
+// try {
+// const uploaded = await Promise.all(
+// files.map(file => uploadImageToServer(file))
+// );
+// setImages(uploaded);
+// } catch (err) {
+// console.error('图片上传失败:', err);
+// alert('有图片上传失败,请重试');
+// }
+// };
+
+// const uploadImageToServer = async (file) => {
+// const formData = new FormData();
+// formData.append('file', file);
+// const res = await axios.post(`${API_BASE}/upload`, formData, {
+// headers: { 'Content-Type': 'multipart/form-data' }
+// });
+// return res.data.url;
+// };
+
+// const handleSubmit = async () => {
+// if (!content.trim()) {
+// alert('内容不能为空');
+// return;
+// }
+// try {
+// await axios.post(
+// `${API_BASE}/echo/users/${USER_ID}/CreateMoment`,
+// {
+// title: title.trim() || undefined,
+// friend_content: content.trim(),
+// images
+// }
+// );
+// onClose();
+// fetchFeeds();
+// } catch (err) {
+// console.error('发布失败:', err);
+// alert('发布失败,请稍后重试');
+// }
+// };
+
+// return (
+// <div className="create-feed-page">
+// <div className="cf-header">
+// <button onClick={onClose} style={{ padding: '5px 10px', backgroundColor: '#BA929A', color: 'white' }}>
+// 返回
+// </button>
+// <h3>发布新动态</h3>
+// </div>
+// <div className="cf-form">
+// <input
+// type="text"
+// placeholder="标题"
+// value={title}
+// onChange={e => setTitle(e.target.value)}
+// />
+// <textarea
+// placeholder="写下你的内容..."
+// value={content}
+// onChange={e => setContent(e.target.value)}
+// />
+// <input
+// type="file"
+// accept="image/*"
+// multiple
+// onChange={handleImageChange}
+// />
+// <div className="cf-preview">
+// {previewUrls.map((url, i) => (
+// <img key={i} src={url} alt={`预览 ${i}`} />
+// ))}
+// </div>
+// <button className="cf-submit-btn" onClick={handleSubmit}>
+// 发布
+// </button>
+// </div>
+// </div>
+// );
+// };
+
+// export default CreateMoment;
+
diff --git a/src/pages/FriendMoments/FriendMoments.css b/src/pages/FriendMoments/FriendMoments.css
index c95bdcf..a69d919 100644
--- a/src/pages/FriendMoments/FriendMoments.css
+++ b/src/pages/FriendMoments/FriendMoments.css
@@ -1,88 +1,171 @@
-/* .friend-moments {
- background-color: #5F4437;
- color: white;
- }
- .header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10px;
- }
- .logo-and-name {
- display: flex;
- align-items: center;
- }
- .logo {
- height: 30px;
- margin-right: 10px;
- }
- .site-name {
- font-size: 24px;
- }
- .user-and-message {
- display: flex;
- align-items: center;
- }
- .user-avatar {
- height: 40px;
- margin-right: 10px;
- }
- .message-center {
- font-size: 16px;
- }
- .nav {
- background-color: #dab8c2;
- display: flex;
- justify-content: center;
- }
- .nav-item {
- color: white;
- text-decoration: none;
- padding: 10px 20px;
- }
- .active {
- background-color: #996633;
- }
- .content {
- padding: 20px;
- }
- .user-post {
- border-bottom: 1px solid white;
- margin-bottom: 20px;
- padding-bottom: 20px;
- }
- .user-info {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- }
- .user-avatar-small {
- height: 30px;
- margin-right: 10px;
- }
- .username {
- font-size: 16px;
- }
- .post-content {
- margin-bottom: 10px;
- }
- .post-actions {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- }
- .like-icon,
- .comment-icon {
- margin-right: 5px;
- }
- .like-count,
- .comment-count {
- margin-left: 5px;
- }
- .post-image {
- float: right;
- width: 150px;
- height: 150px;
- background-color: #ddd;
- margin-left: 10px;
- } */
\ No newline at end of file
+.friend-moments-container {
+ margin: 0 auto;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
+ padding-bottom: 40px;
+}
+
+.fm-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 2%;
+}
+
+
+.f-search-bar {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+}
+
+.search-input {
+ padding: 6px 8px;
+ font-size: 14px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+
+.search-btn {
+ padding: 6px 12px;
+ font-size: 14px;
+ cursor: pointer;
+ background: #fff;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+
+.feed-list .feed-item {
+ padding: 1% 1.5%;
+ margin: 1% 2%;
+ border-radius: 6px;
+ /*设置item之间的间隔*/
+ margin-bottom: 2%;
+ background-color: #e9ded2;
+}
+
+.feed-item h4 {
+ margin: 0 0 5px;
+}
+
+.feed-item p {
+ margin: 0 0 10px;
+ line-height: 1.4;
+}
+
+.feed-images {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+ margin-bottom: 10px;
+}
+
+.feed-images img {
+ width: 100px;
+ height: 100px;
+ object-fit: cover;
+ border-radius: 4px;
+ border: 1px solid #ddd;
+}
+
+.feed-footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 12px;
+ color: #666;
+}
+
+.delete-btn {
+ background: none;
+ border: none;
+ color: #f44;
+ cursor: pointer;
+ font-size: 12px;
+}
+
+/* Modal 样式 */
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0,0,0,0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+}
+
+.modal-dialog {
+ background: #e9ded2;
+ padding: 20px;
+ width: 35%;
+ border-radius: 8px;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+/* 标题 */
+.modal-dialog h3 {
+ margin: 0;
+ color : #4A3B34;
+}
+
+.modal-dialog input[type="text"],
+.modal-dialog textarea {
+ width: 97%;
+ padding: 8px;
+ font-size: 14px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+
+.modal-dialog input[type="file"] {
+ width: 97%;
+ font-size: 14px;
+ border-radius: 4px;
+}
+
+.modal-dialog textarea {
+ resize: vertical;
+ min-height: 80px;
+}
+
+.cf-preview {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.cf-preview img {
+ width: 80px;
+ height: 80px;
+ object-fit: cover;
+ border-radius: 4px;
+ border: 1px solid #bbb;
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 10px;
+}
+
+.modal-actions .btn {
+ padding: 6px 12px;
+ font-size: 14px;
+ cursor: pointer;
+ border: none;
+ border-radius: 4px;
+}
+
+.modal-actions .btn.cancel {
+ background: #5F4437;
+}
+
+.modal-actions .btn.submit {
+ background: #BA929A;
+ color: #fff;
+}
diff --git a/src/pages/FriendMoments/FriendMoments.jsx b/src/pages/FriendMoments/FriendMoments.jsx
index 4e1a704..fdf101c 100644
--- a/src/pages/FriendMoments/FriendMoments.jsx
+++ b/src/pages/FriendMoments/FriendMoments.jsx
@@ -1,55 +1,210 @@
-// import React from 'react';
-// import './FriendMoments.css';
-// import { Link } from 'wouter';
-// import logo from '../../assets/logo.png';
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+import './FriendMoments.css';
+import Header from '../../components/Header';
+import { Edit } from '@icon-park/react';
-// const FriendMoments = () => {
-// return (
-// <div className="friend-moments">
-// {/* 顶部栏 */}
-// <header className="header">
-// {/* 左侧 logo 和网站名称 */}
-// <div className="logo-and-name">
-// {/* 确保此处没有语法错误 */}
-// <img src={logo} alt="网站 logo" className="logo" />
-// <span className="site-name">Echo</span>
-// </div>
-// {/* 右侧用户头像和消息中心 */}
-// <div className="user-and-message">
-// <img src="user-avatar.png" alt="用户头像" className="user-avatar" />
-// <span className="message-center">消息</span>
-// </div>
-// </header>
-// {/* 导航栏 */}
-// <nav className="nav">
-// <Link to="/friend-moments" className="nav-item active">好友动态</Link>
-// <Link to="/forum" className="nav-item">论坛</Link>
-// <Link to="/interest-groups" className="nav-item">兴趣小组</Link>
-// <Link to="/seed-list" className="nav-item">种子列表</Link>
-// <Link to="/publish-seed" className="nav-item">发布种子</Link>
-// </nav>
-// {/* 好友动态内容区域 */}
-// <div className="content">
-// {/* 用户动态示例,可从后端获取数据循环展示 */}
-// <div className="user-post">
-// <div className="user-info">
-// <img src="user1-avatar.png" alt="用户头像" className="user-avatar-small" />
-// <span className="username">user1</span>
-// </div>
-// <div className="post-content">
-// <p>动态内容...</p>
-// </div>
-// <div className="post-actions">
-// {/* <GoodTwo theme="outline" size="24" fill="#fff" /> */}
-// <span className="like-count">21</span>
-// {/* <Comment theme="outline" size="24" fill="#fff"/> */}
-// <span className="comment-count">2</span>
-// </div>
-// <img src="image1.png" alt="动态图片" className="post-image" />
-// </div>
-// </div>
-// </div>
-// );
-// };
+const API_BASE = process.env.REACT_APP_API_BASE;
+const USER_ID = 456;
-// export default FriendMoments;
\ No newline at end of file
+const FriendMoments = () => {
+ const [feeds, setFeeds] = useState([]);
+ const [filteredFeeds, setFilteredFeeds] = useState([]);
+ const [query, setQuery] = useState('');
+
+ // Modal state & form fields
+ const [showModal, setShowModal] = useState(false);
+ const [title, setTitle] = useState('');
+ const [content, setContent] = useState('');
+ const [previewUrls, setPreviewUrls] = useState([]);
+ const [images, setImages] = useState([]);
+
+ // 拉取好友动态列表
+ const fetchFeeds = async () => {
+ try {
+ const res = await axios.get(`${API_BASE}/echo/users/${USER_ID}/feeds`);
+ setFeeds(res.data.feeds);
+ setFilteredFeeds(res.data.feeds);
+ } catch (err) {
+ console.error('获取动态列表失败:', err);
+ }
+ };
+
+ useEffect(() => {
+ fetchFeeds();
+ }, []);
+
+ // 搜索处理
+ const handleSearch = () => {
+ const q = query.trim().toLowerCase();
+ if (!q) return;
+ setFilteredFeeds(
+ feeds.filter(f => (f.title || '').toLowerCase().includes(q))
+ );
+ };
+ const handleReset = () => {
+ setQuery('');
+ setFilteredFeeds(feeds);
+ };
+
+ // 对话框内:本地预览 & 上传
+ const handleImageChange = async (e) => {
+ const files = Array.from(e.target.files);
+ if (!files.length) return;
+ setPreviewUrls(files.map(f => URL.createObjectURL(f)));
+ try {
+ const uploaded = await Promise.all(files.map(f => uploadImageToServer(f)));
+ setImages(uploaded);
+ } catch (err) {
+ console.error('图片上传失败', err);
+ alert('图片上传失败,请重试');
+ }
+ };
+ const uploadImageToServer = async (file) => {
+ const fd = new FormData();
+ fd.append('file', file);
+ const res = await axios.post(`${API_BASE}/upload`, fd, {
+ headers: {'Content-Type':'multipart/form-data'}
+ });
+ return res.data.url;
+ };
+
+ // 对话框内:提交新动态
+ const handleSubmit = async () => {
+ if (!content.trim()) {
+ alert('内容不能为空');
+ return;
+ }
+ try {
+ await axios.post(
+ `${API_BASE}/echo/users/${USER_ID}/createFeed`,
+ { title: title.trim() || undefined, friend_content: content.trim(), images }
+ );
+ // 重置表单
+ setTitle('');
+ setContent('');
+ setImages([]);
+ setPreviewUrls([]);
+ setShowModal(false);
+ fetchFeeds();
+ } catch (err) {
+ console.error('发布失败', err);
+ alert('发布失败,请稍后重试');
+ }
+ };
+
+ // 删除动态
+ const handleDelete = async (feedId) => {
+ if (!window.confirm('确定要删除这条动态吗?')) return;
+ try {
+ await axios.delete(`${API_BASE}/echo/users/me/feed/${feedId}`);
+ fetchFeeds();
+ } catch (err) {
+ console.error('删除失败', err);
+ alert('删除失败');
+ }
+ };
+
+ return (
+ <div className="friend-moments-container">
+ <Header />
+ <div className="fm-header">
+ <button className="create-btn" onClick={() => setShowModal(true)}>
+ <Edit theme="outline" size="18" style={{ marginRight: '6px' }} />
+ 创建动态
+ </button>
+ <div className="f-search-bar">
+ <input
+ className="search-input"
+ type="text"
+ value={query}
+ onChange={e => setQuery(e.target.value)}
+ placeholder="输入要搜索的动态"
+ />
+ <button className="search-btn" onClick={handleSearch}>搜索</button>
+ <button className="search-btn" onClick={handleReset}>重置</button>
+ </div>
+ </div>
+
+ <div className="feed-list">
+ {filteredFeeds.map(feed => (
+ <div className="feed-item" key={feed.feed_id}>
+ {feed.title && <h4>{feed.title}</h4>}
+ <p>{feed.friend_content}</p>
+
+ {feed.images?.length > 0 && (
+ <div className="feed-images">
+ {feed.images.map((url, i) => (
+ <img key={i} src={url} alt={`动态图${i}`} />
+ ))}
+ </div>
+ )}
+
+ <div className="feed-footer">
+ <span className="feed-date">
+ {new Date(feed.created_at).toLocaleString()}
+ </span>
+ {feed.is_mine && (
+ <button className="delete-btn" onClick={() => handleDelete(feed.feed_id)}>
+ 删除
+ </button>
+ )}
+ </div>
+ </div>
+ ))}
+ </div>
+
+ {/* Modal 对话框 */}
+ {showModal && (
+ <div className="modal-overlay" onClick={() => setShowModal(false)}>
+ <div className="modal-dialog" onClick={e => e.stopPropagation()}>
+ <h3>发布新动态</h3>
+ <input
+ type="text"
+ placeholder="标题"
+ value={title}
+ onChange={e => setTitle(e.target.value)}
+ />
+ <textarea
+ placeholder="写下你的内容..."
+ value={content}
+ onChange={e => setContent(e.target.value)}
+ />
+ {/* <input
+ type="file"
+ accept="image/*"
+ multiple
+ onChange={handleImageChange}
+ /> */}
+ <label className="file-label">
+ 选择图片
+ <input
+ type="file"
+ accept="image/*"
+ multiple
+ onChange={handleImageChange}
+ style={{ display: 'none' }}
+ />
+ </label>
+ <div className="cf-preview">
+ {previewUrls.map((url, i) => (
+ <img key={i} src={url} alt={`预览${i}`} />
+ ))}
+ </div>
+ <div className="modal-actions">
+ <button className="btn cancel" onClick={() => setShowModal(false)}>
+ 取消
+ </button>
+ <button className="btn submit" onClick={handleSubmit}>
+ 发布
+ </button>
+ </div>
+ </div>
+ </div>
+ )}
+ </div>
+ );
+};
+
+export default FriendMoments;
+
diff --git a/src/pages/InterestGroup/InterestGroup.css b/src/pages/InterestGroup/InterestGroup.css
index 1de6510..35d3c4d 100644
--- a/src/pages/InterestGroup/InterestGroup.css
+++ b/src/pages/InterestGroup/InterestGroup.css
@@ -1,6 +1,6 @@
/* 设置整个兴趣小组页面的背景色和布局 */
.interest-group-container {
- background-color: #5F4437;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
width: 100%;
height: 2000px;
}
diff --git a/src/pages/MessagePage/MessagePage.css b/src/pages/MessagePage/MessagePage.css
new file mode 100644
index 0000000..77ea80a
--- /dev/null
+++ b/src/pages/MessagePage/MessagePage.css
@@ -0,0 +1,44 @@
+/* ./pages/MessagePage/MessagePage.css */
+
+.message-page {
+ padding: 20px;
+ background-color: #f8f9fa;
+ min-height: calc(100vh - 120px);
+ }
+
+ .message-page h2 {
+ font-size: 24px;
+ margin-bottom: 20px;
+ }
+
+ .message-list {
+ list-style: none;
+ padding: 0;
+ }
+
+ .message-item {
+ background: #ffffff;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ padding: 15px;
+ margin-bottom: 15px;
+ }
+
+ .message-header {
+ font-size: 16px;
+ margin-bottom: 10px;
+ color: #343a40;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .message-time {
+ font-size: 14px;
+ color: #6c757d;
+ }
+
+ .message-content {
+ font-size: 15px;
+ color: #495057;
+ }
+
\ No newline at end of file
diff --git a/src/pages/MessagePage/MessagePage.jsx b/src/pages/MessagePage/MessagePage.jsx
new file mode 100644
index 0000000..ae95dca
--- /dev/null
+++ b/src/pages/MessagePage/MessagePage.jsx
@@ -0,0 +1,92 @@
+import React, { useEffect, useState } from 'react';
+import './MessagePage.css';
+import { useUser } from '../../context/UserContext';
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+
+const mockMessages = [
+ {
+ message_id: 1,
+ sender_username: 'Alice',
+ timestamp: Date.now() - 100000,
+ content: '你好,这是测试消息。',
+ },
+ {
+ message_id: 2,
+ sender_username: 'Bob',
+ timestamp: Date.now() - 50000,
+ content: '欢迎使用我们的平台!',
+ },
+];
+
+const MessagePage = () => {
+ const { user } = useUser(); // 从上下文中获取用户
+ const currentUserId = user?.id;
+
+ const [messages, setMessages] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (currentUserId) {
+ fetchMessages();
+ }
+ }, [currentUserId]);
+
+ const fetchMessages = async () => {
+ setLoading(true);
+ try {
+ if (process.env.NODE_ENV === 'development') {
+ await new Promise((r) => setTimeout(r, 500)); // 模拟延迟
+ setMessages(mockMessages);
+ } else {
+ const response = await fetch(`${API_BASE}/echo/messages/${currentUserId}`);
+ const data = await response.json();
+ if (data.status === 'success') {
+ setMessages(data.messages);
+ } else {
+ setMessages([]);
+ }
+ }
+ } catch (error) {
+ console.error('加载消息失败:', error);
+ setMessages([]);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (!currentUserId) {
+ return <div className="message-page">未登录,无法加载消息。</div>;
+ }
+
+ if (loading) {
+ return <div className="message-page">加载中...</div>;
+ }
+
+ return (
+ <div className="message-page">
+ <h2>我的消息</h2>
+ {messages.length === 0 ? (
+ <div>暂无消息记录</div>
+ ) : (
+ <ul className="message-list">
+ {messages.map((msg) => (
+ <li key={msg.message_id} className="message-item">
+ <div className="message-header">
+ 来自:<strong>{msg.sender_username}</strong>
+ <span className="message-time">
+ {new Date(msg.timestamp).toLocaleString()}
+ </span>
+ </div>
+ <div className="message-content">
+ {msg.content}
+ </div>
+ </li>
+ ))}
+ </ul>
+ )}
+ </div>
+ );
+};
+
+export default MessagePage;
diff --git a/src/pages/PublishSeed/PublishSeed.css b/src/pages/PublishSeed/PublishSeed.css
index 5f83d89..1cc4804 100644
--- a/src/pages/PublishSeed/PublishSeed.css
+++ b/src/pages/PublishSeed/PublishSeed.css
@@ -70,7 +70,7 @@
}
.publish-seed-container {
- background-color: #5F4437;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
color: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
@@ -78,4 +78,17 @@
.upload-button {
width: 100%;
+}
+
+/* 文件选择按钮保持 label 方式,不变 */
+.seed-file-label {
+ display: inline-block;
+ padding: 6px 8px;
+ border: 1px solid #e0c4a1;
+ background-color: #fff5f5;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+ user-select: none;
+ width : 9%;
}
\ No newline at end of file
diff --git a/src/pages/PublishSeed/PublishSeed.jsx b/src/pages/PublishSeed/PublishSeed.jsx
index c61440f..c57242a 100644
--- a/src/pages/PublishSeed/PublishSeed.jsx
+++ b/src/pages/PublishSeed/PublishSeed.jsx
@@ -107,11 +107,14 @@
<div className="seed-file">
<label>种子文件</label>
- <input
- type="file"
- onChange={handleFileChange}
- required
- />
+ <label className="seed-file-label">
+ 点击选择文件
+ <input
+ type="file"
+ onChange={handleFileChange}
+ style={{ display: 'none' }}
+ />
+ </label>
</div>
<div className="form-group">
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.css b/src/pages/SeedList/SeedDetail/SeedDetail.css
index 242fd83..641a4be 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.css
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.css
@@ -1,7 +1,5 @@
.seed-detail-page {
- background-color: #4b322b;
- min-height: 100vh;
- padding: 32px 0;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
font-family: 'Helvetica Neue', sans-serif;
color: #333;
}
@@ -19,7 +17,7 @@
font-size: 24px;
font-weight: bold;
margin-bottom: 16px;
- color: #4b322b;
+ color: #4A3B34;
}
.seed-header-container {
@@ -70,7 +68,7 @@
}
.btn:hover {
- background-color: #6d4e37;
+ background-color: #5F4437;
}
.comments-section {
@@ -80,7 +78,7 @@
.comments-section h3 {
margin-bottom: 10px;
font-size: 20px;
- color: #4b322b;
+ color: #4A3B34;
}
.comments-list {
diff --git a/src/pages/SeedList/SeedList.css b/src/pages/SeedList/SeedList.css
index 724411c..aff93c3 100644
--- a/src/pages/SeedList/SeedList.css
+++ b/src/pages/SeedList/SeedList.css
@@ -1,7 +1,6 @@
- .main-page {
- background-color: #5F4437;
- color: white;
+ .seed-list-container {
+ background: linear-gradient(180deg, #5F4437, #823c3c);
}
/* 搜索、排序控件 */
@@ -232,8 +231,5 @@
border-radius: 8px;
margin-bottom: 12px;
}
- .friend-moments {
- background-color: #5F4437;
- color: white;
- }
+
\ No newline at end of file
diff --git a/src/pages/SeedList/SeedList.jsx b/src/pages/SeedList/SeedList.jsx
index 2831434..09ea5dd 100644
--- a/src/pages/SeedList/SeedList.jsx
+++ b/src/pages/SeedList/SeedList.jsx
@@ -157,7 +157,7 @@
};
return (
- <div className="main-page">
+ <div className="seed-list-container">
<Header /> {/* 引用 Header 组件 */}
<div className="controls">
diff --git a/src/pages/UserCenter/UserNav/UserNav.css b/src/pages/UserCenter/UserNav/UserNav.css
index 0c7ed6f..6a1b405 100644
--- a/src/pages/UserCenter/UserNav/UserNav.css
+++ b/src/pages/UserCenter/UserNav/UserNav.css
@@ -3,7 +3,6 @@
margin-right: -5%;
margin-left: 5%;
width: 150px; /* 增加容器宽度 */
- background-color: #5F4437;
padding-top: 20px;
height: 100%; /* 让容器填充整个父容器高度 */
display: flex;
diff --git a/src/pages/UserCenter/UserProfile.css b/src/pages/UserCenter/UserProfile.css
index 988c1c8..bcb1a2d 100644
--- a/src/pages/UserCenter/UserProfile.css
+++ b/src/pages/UserCenter/UserProfile.css
@@ -4,7 +4,7 @@
font-family: Arial, sans-serif;
display: flex;
gap: 10%;
- background-color: #5F4437;
+ background: linear-gradient(180deg, #5F4437, #823c3c);
}