diff --git a/backend/src/core/config.py b/backend/src/core/config.py
index 482dbea..f3adc7f 100644
--- a/backend/src/core/config.py
+++ b/backend/src/core/config.py
@@ -139,7 +139,12 @@ def ensure_directories():
settings.generated_images_dir,
os.path.dirname(settings.log_file),
]
-
+
+ # SQLite 数据库目录
+ if not is_postgresql_database():
+ db_path = settings.database_url.replace("sqlite:///", "")
+ directories.append(os.path.dirname(db_path))
+
for directory in directories:
Path(directory).mkdir(parents=True, exist_ok=True)
diff --git a/env.example b/env.example
index 7308477..6494f7f 100644
--- a/env.example
+++ b/env.example
@@ -51,6 +51,7 @@ LOG_FILE=../runtime/logs/app.log
# 前端配置
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
+NEXT_PUBLIC_API_URL=http://localhost:8000
NEXTAUTH_SECRET=your-nextauth-secret-change-in-production
NEXTAUTH_URL=http://localhost:8001
diff --git a/web/src/app/globals.css b/web/src/app/globals.css
index 145088a..5ba42de 100644
--- a/web/src/app/globals.css
+++ b/web/src/app/globals.css
@@ -19,17 +19,6 @@
}
}
- --animate-spotlight: spotlight 2s ease 0.75s 1 forwards;
- @keyframes spotlight {
- 0% {
- opacity: 0;
- transform: translate(-72%, -62%) scale(0.5);
- }
- to {
- opacity: 1;
- transform: translate(-50%, -40%) scale(1);
- }
- }
}
@theme inline {
@@ -175,13 +164,15 @@
/* MIT 风格的字体层次 */
h1 {
+ font-family: var(--font-serif), 'Noto Serif SC', Georgia, serif;
font-size: 2.5rem;
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.025em;
}
-
+
h2 {
+ font-family: var(--font-serif), 'Noto Serif SC', Georgia, serif;
font-size: 2rem;
font-weight: 600;
line-height: 1.3;
@@ -330,3 +321,12 @@ textarea {
button {
cursor: pointer;
}
+
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx
index e5ce819..60aed4d 100644
--- a/web/src/app/layout.tsx
+++ b/web/src/app/layout.tsx
@@ -1,10 +1,15 @@
import type { Metadata, Viewport } from "next";
-import { Inter } from "next/font/google";
+import { Inter, Noto_Serif_SC } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { Toaster } from "sonner";
import "./globals.css";
-const inter = Inter({ subsets: ["latin"] });
+const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
+const notoSerifSC = Noto_Serif_SC({
+ subsets: ["latin"],
+ weight: ["600", "700"],
+ variable: "--font-serif",
+});
export const metadata: Metadata = {
title: "国土空间规划课程智能体",
@@ -25,7 +30,7 @@ export default function RootLayout({
}) {
return (
-
+
-
-
-
- {isAuthenticated ? "功能模块" : "核心功能"}
-
-
- {isAuthenticated ? "选择您需要的功能" : "强大的AI学习助手"}
-
-
- {isAuthenticated
- ? "点击下方卡片开始使用各项功能"
- : "基于先进的大模型技术,为您提供专业的国土空间规划学习体验"
- }
-
-
-
-
-
- {features.map((feature) => {
- if (isAuthenticated) {
- // 登录状态:使用自定义卡片
- return (
-
-
-
-
-
- {feature.name}
-
-
{feature.description}
- {feature.stats && (
-
-
- {feature.stats.count} {feature.stats.label}
-
-
- )}
-
-
-
-
- {feature.cta}
-
-
-
-
-
-
-
- );
- } else {
- // 未登录状态:使用标准 BentoCard
- return (
-
- );
- }
- })}
-
-
-
-
- );
-}
diff --git a/web/src/components/home/footer.tsx b/web/src/components/home/footer.tsx
deleted file mode 100644
index 0194cd7..0000000
--- a/web/src/components/home/footer.tsx
+++ /dev/null
@@ -1,159 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { BookOpen, Mail, Phone, MapPin, MessageCircle } from "lucide-react";
-
-export default function Footer() {
- const currentYear = new Date().getFullYear();
-
- const footerLinks = {
- quickLinks: [
- { name: "首页", href: "/" },
- { name: "智能问答", href: "/chat" },
- { name: "知识库管理", href: "/knowledge" },
- { name: "空间出图", href: "/spatial" },
- { name: "学习分析", href: "/analytics" },
- ],
- resources: [
- { name: "课程大纲", href: "#" },
- { name: "线上讲座", href: "#" },
- { name: "资料下载", href: "#" },
- { name: "案例分析", href: "#" },
- { name: "交流论坛", href: "#" },
- ],
- };
-
- const contactInfo = [
- { icon: Mail, text: "contact@HIT-agent.com", href: "mailto:contact@HIT-agent.com" },
- { icon: Phone, text: "0451-8641-2114", href: "tel:0451-8641-2114" },
- { icon: MapPin, text: "哈尔滨市南岗区西大直街92号", href: "#" },
- ];
-
- return (
-
- );
-}
-
diff --git a/web/src/components/home/hero-section.tsx b/web/src/components/home/hero-section.tsx
deleted file mode 100644
index cf98282..0000000
--- a/web/src/components/home/hero-section.tsx
+++ /dev/null
@@ -1,130 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { motion } from "framer-motion";
-import { Button } from "@/components/ui/button";
-import { AuroraText } from "@/components/magicui/aurora-text";
-import { User } from "@/types";
-import { MessageSquare, FileText, Image, BarChart3, ArrowRight } from "lucide-react";
-
-interface HeroSectionProps {
- isAuthenticated: boolean;
- user: User | null;
-}
-
-export default function HeroSection({ isAuthenticated, user }: HeroSectionProps) {
- const features = [
- {
- name: "智能问答",
- href: "/chat",
- icon: MessageSquare,
- description: "基于大模型的智能问答系统,专业知识即时解答",
- color: "from-blue-500 to-blue-600"
- },
- {
- name: "知识库管理",
- href: "/knowledge",
- icon: FileText,
- description: "多模态知识库,文档上传与智能检索",
- color: "from-green-500 to-green-600"
- },
- {
- name: "空间出图",
- href: "/spatial",
- icon: Image,
- description: "结合空间规划的AI图像生成与分析",
- color: "from-purple-500 to-purple-600"
- },
- {
- name: "学习分析",
- href: "/analytics",
- icon: BarChart3,
- description: "学习数据统计,追踪您的学习进度",
- color: "from-orange-500 to-orange-600"
- },
- ];
-
- return (
-
-
- {/* 描述区域 */}
-
-
- 基于大模型技术的智能学习平台,提供专业的国土空间规划知识问答、文档管理和智能分析
-
- {!isAuthenticated && (
-
-
-
-
- )}
-
-
- {/* 功能卡片 - 登录后显示 */}
- {isAuthenticated && (
-
- {features.map((feature, index) => (
-
-
- {/* 图标 */}
-
-
-
-
- {/* 标题 */}
-
- {feature.name}
-
-
- {/* 描述 */}
-
- {feature.description}
-
-
- {/* 箭头 */}
-
-
- {/* 装饰性背景 */}
-
-
-
- ))}
-
- )}
-
-
- );
-}
-
-
-
-
-
-
diff --git a/web/src/components/home/home-page-content.tsx b/web/src/components/home/home-page-content.tsx
index 28f5a6d..f405891 100644
--- a/web/src/components/home/home-page-content.tsx
+++ b/web/src/components/home/home-page-content.tsx
@@ -1,50 +1,267 @@
"use client";
-import { useState, useEffect } from "react";
+import { useState, useEffect, useMemo } from "react";
import { useAuthStore } from "@/store/auth";
import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import Navbar from "./navbar";
-import { MessageSquare, Database, Image, BookOpen, Users, Award, ArrowRight, Mail, Phone, MapPin, GraduationCap } from "lucide-react";
+import { BookOpen, Users, ArrowRight, Mail, Phone, MapPin, Search } from "lucide-react";
import Link from "next/link";
import { analyticsAPI } from "@/lib/api";
+const modules = [
+ {
+ title: "课程内容",
+ description: "系统化的国土空间规划课程体系,涵盖总体规划、详细规划、专项规划等核心知识模块",
+ href: "/course-content",
+ tags: ["课程体系"],
+ visual: "course" as const,
+ },
+ {
+ title: "智能问答",
+ description: "基于RAG技术的专业对话系统,精准解答国土空间规划领域的专业问题",
+ href: "/chat",
+ tags: ["RAG"],
+ visual: "chat" as const,
+ },
+ {
+ title: "知识库",
+ description: "多格式文档智能处理与知识管理,构建专业领域的结构化知识体系",
+ href: "/knowledge",
+ tags: ["向量检索"],
+ visual: "knowledge" as const,
+ },
+ {
+ title: "空间设计",
+ description: "AI驱动的空间规划图像生成工具,支持文生图与图生图多种创作模式",
+ href: "/spatial",
+ tags: ["AI绘图"],
+ visual: "spatial" as const,
+ },
+ {
+ title: "论坛社区",
+ description: "课程讨论与学习经验交流平台,促进师生互动与同伴学习",
+ href: "/forum",
+ tags: ["协作"],
+ visual: "forum" as const,
+ },
+];
+
+const visualStyles: Record = {
+ course: { bg: "from-emerald-950 to-emerald-900/80" },
+ chat: { bg: "from-slate-950 to-slate-900/80" },
+ knowledge: { bg: "from-amber-950 to-amber-900/80" },
+ forum: { bg: "from-sky-950 to-sky-900/80" },
+ spatial: { bg: "from-violet-950 to-violet-900/80" },
+};
+
+function ModuleIllustration({ visual }: { visual: string }) {
+ const illustrations: Record = {
+ // 等高线地形图纹理 — 课程体系的系统性层次
+ course: (
+
+ ),
+ // 神经网络/对话流 — AI 问答的连接性
+ chat: (
+
+ ),
+ // 分层知识架构 — 向量检索的结构化组织
+ knowledge: (
+
+ ),
+ // 等高线地形 + 流动曲线 — 空间设计的地形分析
+ spatial: (
+
+ ),
+ // 星座/人际网络 — 论坛社区的连接
+ forum: (
+
+ ),
+ };
+ return <>{illustrations[visual]}>;
+}
+
+const allTags = Array.from(new Set(modules.flatMap((m) => m.tags)));
+
export default function HomePageContent() {
const { isAuthenticated, user } = useAuthStore();
const [stats, setStats] = useState([
- { label: "活跃用户", value: "1,200+" },
- { label: "知识文档", value: "5,000+" },
- { label: "问答对话", value: "50,000+" },
- { label: "生成图像", value: "10,000+" }
+ { label: "活跃用户", value: "—" },
+ { label: "知识文档", value: "—" },
+ { label: "问答对话", value: "—" },
+ { label: "生成图像", value: "—" },
]);
const [isLoadingStats, setIsLoadingStats] = useState(true);
+ const [searchQuery, setSearchQuery] = useState("");
+ const [activeTag, setActiveTag] = useState(null);
+
+ const filteredModules = useMemo(() => {
+ return modules.filter((m) => {
+ const matchesSearch =
+ !searchQuery ||
+ m.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ m.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ m.tags.some((t) => t.toLowerCase().includes(searchQuery.toLowerCase()));
+ const matchesTag = !activeTag || m.tags.includes(activeTag);
+ return matchesSearch && matchesTag;
+ });
+ }, [searchQuery, activeTag]);
useEffect(() => {
const loadPlatformStats = async () => {
try {
setIsLoadingStats(true);
const data = await analyticsAPI.getPlatformStats();
-
- // 格式化数字,添加千分位分隔符
+
const formatNumber = (num: number) => {
- if (num >= 10000) {
- return `${(num / 10000).toFixed(1)}万+`;
- } else if (num >= 1000) {
- return `${(num / 1000).toFixed(1)}千+`;
- }
- return `${num}+`;
+ if (num >= 10000) return `${(num / 10000).toFixed(1)}万+`;
+ if (num >= 1000) return `${(num / 1000).toFixed(1)}千+`;
+ return `${num}`;
};
-
+
setStats([
{ label: "活跃用户", value: formatNumber(data.active_users) },
{ label: "知识文档", value: formatNumber(data.knowledge_documents) },
{ label: "问答对话", value: formatNumber(data.qa_dialogues) },
- { label: "生成图像", value: formatNumber(data.generated_images) }
+ { label: "生成图像", value: formatNumber(data.generated_images) },
]);
- } catch (error: any) {
- console.warn("加载平台统计数据失败,使用默认值:", error?.message || error);
- // 保持默认值,不显示错误给用户
- // 如果后端API不可用,继续显示默认的占位数据
+ } catch {
+ // 后端不可用时保持占位符
} finally {
setIsLoadingStats(false);
}
@@ -53,63 +270,26 @@ export default function HomePageContent() {
loadPlatformStats();
}, []);
- const features = [
- {
- icon: GraduationCap,
- title: "课程内容",
- description: "查看和管理国土空间规划课程内容,获取系统化的学习资源",
- href: "/course-content"
- },
- {
- icon: MessageSquare,
- title: "智能问答",
- description: "基于RAG技术的智能对话系统,提供专业准确的国土空间规划知识解答",
- href: "/chat"
- },
- {
- icon: Database,
- title: "知识库",
- description: "构建和管理专业知识库,支持多种文档格式的智能处理和分析",
- href: "/knowledge"
- },
- {
- icon: Users,
- title: "论坛社区",
- description: "参与系统优化建议与课程反馈的讨论,与同伴交流学习经验",
- href: "/forum"
- },
- {
- icon: Image,
- title: "空间设计",
- description: "AI驱动的空间规划图像生成,支持多种设计风格和规划类型",
- href: "/spatial"
- }
- ];
-
return (
- {/* 导航栏 */}
- {/* Hero 区域 - 全屏背景 */}
+ {/* Hero */}
- {/* 背景图片 - 充满整个屏幕 */}
-

- {/* 渐变遮罩,确保文字可读性 */}
-
+
-
- {/* 内容 */}
+
国土空间规划课程智能体
-
+
基于先进AI技术的智能学习平台,为国土空间规划专业提供全方位的知识服务和实践支持
@@ -134,33 +314,94 @@ export default function HomePageContent() {
- {/* 主要内容 */}
+ {/* 平台模块 — Senseable 风格网格 */}
+
+
+
平台模块
+
集成多种AI技术,提供全面的学习支持
+
- {/* 功能特性 */}
-
-
-
核心功能
-
- 集成多种AI技术,提供全面的学习支持
-
+ {/* 搜索与过滤 */}
+
+
+
+ setSearchQuery(e.target.value)}
+ className="w-full h-10 pl-10 pr-4 rounded-md border border-border bg-background text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
+ />
+
+
+
+ {allTags.map((tag) => (
+
+ ))}
+
-
-
- {features.map((feature, index) => (
-
-
-
-
+
+ {/* 模块卡片网格 */}
+
+ {filteredModules.map((mod) => {
+ const style = visualStyles[mod.visual];
+ return (
+
+ {/* 视觉区域 */}
+
+
-
{feature.title}
-
- {feature.description}
-
-
-
- ))}
+ {/* 信息区域 */}
+
+
{mod.title}
+
+ {mod.description}
+
+
+ {mod.tags.map((tag) => (
+
+ {tag}
+
+ ))}
+
+
+
+ );
+ })}
+
+ {filteredModules.length === 0 && (
+
+ 没有匹配的模块
+
+ )}
@@ -168,16 +409,13 @@ export default function HomePageContent() {
-
平台数据
-
- 持续增长的用户群体和丰富的内容资源
-
+
平台数据
-
+
- {stats.map((stat, index) => (
-
-
+ {stats.map((stat) => (
+
+
{isLoadingStats ? "..." : stat.value}
{stat.label}
@@ -187,23 +425,22 @@ export default function HomePageContent() {
- {/* 统一封底区域 */}
+ {/* Footer */}