diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..96df330 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,101 @@ +# name: Deploy to Server + +# on: +# push: +# branches: +# - main + +# jobs: +# build-and-deploy: +# runs-on: ubuntu-latest +# steps: +# - name: Checkout code +# uses: actions/checkout@v4 + +# - name: Build Docker Images +# run: | +# echo "Building Backend Image..." +# docker build -t market-backend:latest ./backend + +# echo "Building Frontend Image..." +# # 注意:这里我们传入了服务器的 IP 地址作为 API URL +# # 如果你的后端端口不是 8000,请修改这里 +# docker build -t market-frontend:latest \ +# --build-arg VITE_API_URL=http://47.101.218.42:8000/api \ +# ./frontend + +# - name: Save Docker Images +# run: | +# echo "Saving images to tarball..." +# docker save market-backend:latest market-frontend:latest | gzip > market-images.tar.gz + +# - name: Generate Production Compose File +# run: | +# # 生成生产环境专用的 docker-compose.prod.yml +# # 1. 使用构建好的镜像 (image) 替代构建指令 (build) +# # 2. 移除代码挂载 (volumes),确保使用镜像内的代码 +# cat > docker-compose.prod.yml < { const { id } = useParams(); const navigate = useNavigate(); const { user } = useAuth(); + const screens = useBreakpoint(); + const isMobile = !screens.md; const [loading, setLoading] = useState(true); const [topic, setTopic] = useState(null); @@ -156,7 +159,7 @@ const ForumDetail = () => { }; return ( -
+
- {/* Debug Info: Remove in production */} - {/*
- User ID: {user?.id} ({typeof user?.id})
- Topic Author: {topic.author} ({typeof topic.author})
- Match: {String(topic.author) === String(user?.id) ? 'Yes' : 'No'} -
*/} - {user && String(topic.author) === String(user.id) && ( )}
@@ -194,17 +191,17 @@ const ForumDetail = () => { backdropFilter: 'blur(10px)', marginBottom: 30 }} - styles={{ body: { padding: '30px' } }} + styles={{ body: { padding: isMobile ? '15px' : '30px' } }} >
{topic.is_pinned && 置顶} {topic.product_info && {topic.product_info.name}} - {topic.title} + {topic.title} - + - } /> - {topic.author_info?.nickname} + } size={isMobile ? 'small' : 'default'} /> + {topic.author_info?.nickname} {topic.is_verified_owner && ( @@ -213,11 +210,11 @@ const ForumDetail = () => { - {new Date(topic.created_at).toLocaleString()} + {new Date(topic.created_at).toLocaleString()} - {topic.view_count} 阅读 + {topic.view_count} 阅读
@@ -253,7 +250,7 @@ const ForumDetail = () => { {/* Replies List */}
- + <Title level={isMobile ? 5 : 4} style={{ color: '#fff', marginBottom: 20 }}> {topic.replies?.length || 0} 条回复 @@ -266,18 +263,19 @@ const ForumDetail = () => { marginBottom: 16, borderRadius: 8 }} + styles={{ body: { padding: isMobile ? '15px' : '24px' } }} > -
- } /> +
+ } size={isMobile ? 'small' : 'default'} />
- - {reply.author_info?.nickname} + + {reply.author_info?.nickname} {new Date(reply.created_at).toLocaleString()} - #{index + 1} + #{index + 1}
-
+
{ background: 'rgba(20,20,20,0.8)', border: '1px solid rgba(255,255,255,0.1)' }} + styles={{ body: { padding: isMobile ? '15px' : '24px' } }} > 发表回复 {user ? ( @@ -309,7 +308,7 @@ const ForumDetail = () => { placeholder="友善回复,分享你的见解... (支持 Markdown)" style={{ marginBottom: 16, background: '#111', border: '1px solid #333', color: '#fff' }} /> -
+
{ style={{ color: '#fff', background: 'rgba(255,255,255,0.1)', - border: '1px solid rgba(255,255,255,0.2)' + border: '1px solid rgba(255,255,255,0.2)', + width: isMobile ? '100%' : 'auto' }} > 插入图片/视频 -
diff --git a/frontend/src/pages/ForumList.jsx b/frontend/src/pages/ForumList.jsx index b70769d..a029c39 100644 --- a/frontend/src/pages/ForumList.jsx +++ b/frontend/src/pages/ForumList.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; -import { Typography, Input, Button, List, Tag, Avatar, Card, Space, Spin, message, Badge, Tooltip, Tabs, Row, Col } from 'antd'; -import { SearchOutlined, PlusOutlined, UserOutlined, MessageOutlined, EyeOutlined, CheckCircleFilled, FireOutlined, StarFilled, QuestionCircleOutlined, ShareAltOutlined, SoundOutlined } from '@ant-design/icons'; +import { Typography, Input, Button, List, Tag, Avatar, Card, Space, Spin, message, Badge, Tooltip, Tabs, Row, Col, Grid, Carousel } from 'antd'; +import { SearchOutlined, PlusOutlined, UserOutlined, MessageOutlined, EyeOutlined, CheckCircleFilled, FireOutlined, StarFilled, QuestionCircleOutlined, ShareAltOutlined, SoundOutlined, RightOutlined } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { getTopics, getStarUsers, getAnnouncements } from '../api'; @@ -9,8 +9,11 @@ import CreateTopicModal from '../components/CreateTopicModal'; import LoginModal from '../components/LoginModal'; const { Title, Text, Paragraph } = Typography; +const { useBreakpoint } = Grid; const ForumList = () => { + const screens = useBreakpoint(); + const isMobile = !screens.md; // roughly checks if screen is smaller than medium const navigate = useNavigate(); const { user } = useAuth(); @@ -108,7 +111,7 @@ const ForumList = () => { {/* Hero Section */}
{ animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6 }} > - + <Title level={isMobile ? 2 : 1} style={{ color: '#fff', fontFamily: "'Orbitron', sans-serif", marginBottom: 10 }}> <span style={{ color: '#00b96b' }}>Quant Speed</span> Developer Community - + 技术交流 · 硬件开发 · 官方支持 · 量迹生态 -
+
} style={{ borderRadius: 8, background: 'rgba(255,255,255,0.1)', border: '1px solid #333', color: '#fff' }} @@ -135,10 +144,10 @@ const ForumList = () => { /> @@ -146,14 +155,54 @@ const ForumList = () => {
{/* Content Section */} -
+
+ {isMobile && ( + + {/* Mobile Announcements */} +
+ +
+ + {announcements.length > 0 ? announcements.map(item => ( +
+ + {item.title} + +
+ )) : ( +
暂无公告
+ )} +
+
+
+ + {/* Mobile Experts */} +
+ {starUsers.map(u => ( +
+ } offset={[-5, 5]}> + } style={{ border: '2px solid rgba(255, 215, 0, 0.3)' }} /> + +
+ {u.nickname} +
+
+ ))} +
+
+ )} + { backdropFilter: 'blur(10px)', boxShadow: item.is_pinned ? '0 0 10px rgba(0, 185, 107, 0.1)' : 'none' }} - bodyStyle={{ padding: '20px 24px' }} + bodyStyle={{ padding: isMobile ? '15px' : '20px 24px' }} onClick={() => navigate(`/forum/${item.id}`)} >
-
- {item.is_pinned && }>置顶} - +
+ {item.is_pinned && }>{isMobile ? '顶' : '置顶'}} + {getCategoryLabel(item.category)} {item.is_verified_owner && ( - } color="#00b96b" style={{ margin: 0 }}>认证用户 + } color="#00b96b" style={{ margin: 0 }}>{isMobile ? '认证' : '认证用户'} )} - + {item.title}
{item.content.replace(/!\[.*?\]\(.*?\)/g, '[图片]').replace(/[#*`]/g, '')} {/* Simple markdown strip */} @@ -211,10 +260,10 @@ const ForumList = () => {
)} - - + + } size="small" /> - + {item.author_info?.nickname || '匿名用户'} {item.author_info?.is_star && ( @@ -223,22 +272,22 @@ const ForumList = () => { )} - + {!isMobile && } {new Date(item.created_at).toLocaleDateString()} {item.product_info && ( - {item.product_info.name} + {item.product_info.name} )}
-
+
- -
{item.replies?.length || 0}
+ +
{item.replies?.length || 0}
-
- -
{item.view_count || 0}
+
+ +
{item.view_count || 0}
diff --git a/frontend/src/pages/MyOrders.jsx b/frontend/src/pages/MyOrders.jsx index 0ee9250..14c2f3e 100644 --- a/frontend/src/pages/MyOrders.jsx +++ b/frontend/src/pages/MyOrders.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Form, Input, Button, Card, List, Tag, Typography, message, Space, Statistic, Divider, Modal, Descriptions, Tabs } from 'antd'; import { MobileOutlined, LockOutlined, SearchOutlined, CarOutlined, InboxOutlined, SafetyCertificateOutlined, CheckCircleOutlined, ClockCircleOutlined, CloseCircleOutlined, UserOutlined, EnvironmentOutlined, PhoneOutlined, CalendarOutlined } from '@ant-design/icons'; import { getMySignups } from '../api'; +import { motion } from 'framer-motion'; import LoginModal from '../components/LoginModal'; import { useAuth } from '../context/AuthContext'; import { useNavigate } from 'react-router-dom'; @@ -74,13 +75,6 @@ const MyOrders = () => { } }; - const getOrderTypeTag = (order) => { - if (order.config) return 硬件; - if (order.course) return VC课程; - if (order.activity) return 活动; - return 其他; - }; - const getOrderTitle = (order) => { if (order.config_name) return order.config_name; if (order.course_title) return order.course_title; @@ -113,7 +107,7 @@ const MyOrders = () => {
) : ( -
+
当前登录用户: {user.nickname}
+
)} { {currentOrder.id} - {getOrderTypeTag(currentOrder)} {getOrderTitle(currentOrder)} {new Date(currentOrder.created_at).toLocaleString()} {new Date(currentOrder.updated_at).toLocaleString()}