diff --git a/scripts/cleanup-old-forums.mjs b/scripts/cleanup-old-forums.mjs new file mode 100644 index 0000000..0582946 --- /dev/null +++ b/scripts/cleanup-old-forums.mjs @@ -0,0 +1,73 @@ +import { PrismaClient } from "@prisma/client"; +import { PrismaMariaDb } from "@prisma/adapter-mariadb"; +import "dotenv/config"; + +const base = process.env.DATABASE_URL.replace("mysql://", "mariadb://"); +const sep = base.includes("?") ? "&" : "?"; +const connectionString = `${base}${sep}connection_limit=5&pool_timeout=10`; +const adapter = new PrismaMariaDb(connectionString); +const prisma = new PrismaClient({ adapter }); + +const INDUSTRY_SLUGS = [ + "ecommerce", "ai-tech", "content", "finance", "cross-border", + "real-estate", "food", "local-life", "health", "education", +]; + +const INDUSTRY_CHILD_SLUGS = [ + "ec-platform", "ec-livestream", "ec-private", "ec-group", "ec-dtc", "ec-supply", + "ai-tools-app", "ai-startup-forum", "ai-saas", "ai-hardware", "ai-llm", + "ct-short-video", "ct-live", "ct-writing", "ct-mcn", "ct-podcast", + "fi-stock", "fi-crypto", "fi-insurance", "fi-pe", "fi-forex", + "cb-ecommerce", "cb-factory", "cb-logistics", "cb-payment", "cb-brand", + "re-residential", "re-commercial", "re-renovation", "re-property", + "fd-restaurant", "fd-tea", "fd-prepared", "fd-supply", "fd-delivery", + "ll-beauty", "ll-fitness", "ll-pet", "ll-housekeeping", "ll-repair", "ll-edu-local", + "hl-cosmetic", "hl-wellness", "hl-elderly", "hl-rehab", "hl-mental", + "edu-skills", "edu-knowledge", "edu-abroad", "edu-corporate", "edu-k12", +]; + +const KEEP_SLUGS = new Set(["industry", ...INDUSTRY_SLUGS, ...INDUSTRY_CHILD_SLUGS]); + +async function main() { + console.log("Cleaning up old forum categories..."); + + const allCategories = await prisma.forumCategory.findMany({ + include: { _count: { select: { topics: true } } }, + }); + + let deleted = 0; + let kept = 0; + + for (const cat of allCategories) { + if (KEEP_SLUGS.has(cat.slug)) { + kept++; + continue; + } + + const topicsCount = cat._count.topics; + console.log(` Deleting: ${cat.slug} "${cat.name}" (${topicsCount} topics)`); + + if (topicsCount > 0) { + await prisma.forumTopic.deleteMany({ where: { categoryId: cat.id } }); + } + + await prisma.forumCategory.updateMany({ + where: { parentId: cat.id }, + data: { parentId: null }, + }); + + await prisma.forumCategory.delete({ where: { id: cat.id } }); + deleted++; + } + + console.log(`Done: ${deleted} deleted, ${kept} kept.`); +} + +main() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); \ No newline at end of file diff --git a/scripts/seed-bot-forum.mjs b/scripts/seed-bot-forum.mjs index ce042ff..405922e 100644 --- a/scripts/seed-bot-forum.mjs +++ b/scripts/seed-bot-forum.mjs @@ -16,102 +16,113 @@ const BOT_DATA_PATH = resolve(__dirname, "..", "data", "bot-characters.json"); const INDUSTRY_CATEGORIES = [ { name: "电商零售", slug: "ecommerce", icon: "🛒", sortOrder: 1, - description: "电商平台运营、选品策略、流量玩法与变现", + description: "平台运营、直播带货、私域与供应链", children: [ - { name: "平台电商", slug: "ec-platform", icon: "🏪", description: "淘宝/天猫/京东/拼多多/唯品会" }, - { name: "直播带货", slug: "ec-livestream", icon: "📱", description: "抖音/快手/视频号直播运营" }, + { name: "平台电商", slug: "ec-platform", icon: "🏪", description: "淘宝/天猫/京东/拼多多运营" }, + { name: "直播带货", slug: "ec-livestream", icon: "📱", description: "抖音/快手/视频号直播" }, { name: "私域电商", slug: "ec-private", icon: "🔗", description: "微信生态/社群/小程序电商" }, { name: "社区团购", slug: "ec-group", icon: "🏘️", description: "社区团购/买菜/本地配送" }, + { name: "独立站/DTC", slug: "ec-dtc", icon: "🏷️", description: "Shopify/品牌官网自建站" }, + { name: "选品与供应链", slug: "ec-supply", icon: "📦", description: "选品策略/货源/库存管理" }, ], }, { name: "AI智能科技", slug: "ai-tech", icon: "🤖", sortOrder: 2, - description: "AI技术应用、创业机会与产品出海", + description: "AI工具、创业、SaaS与开源大模型", children: [ - { name: "AI工具应用", slug: "ai-tools", icon: "🔧", description: "AI工具推荐、评测与变现" }, - { name: "AI创业", slug: "ai-startup", icon: "💡", description: "AI创业方向与商业模式" }, + { name: "AI工具与应用", slug: "ai-tools-app", icon: "🔧", description: "ChatGPT/Claude/Midjourney类工具" }, + { name: "AI创业", slug: "ai-startup-forum", icon: "💡", description: "AI创业方向与商业模式" }, { name: "SaaS出海", slug: "ai-saas", icon: "🚀", description: "SaaS产品开发与全球化" }, - { name: "智能硬件", slug: "ai-hardware", icon: "🔌", description: "AI硬件产品与IoT创业" }, + { name: "智能硬件", slug: "ai-hardware", icon: "🔌", description: "AI硬件/IoT/可穿戴设备" }, + { name: "大模型与开源", slug: "ai-llm", icon: "🧠", description: "LLM/开源模型/微调/RAG" }, ], }, { - name: "房地产", slug: "real-estate", icon: "🏠", sortOrder: 3, - description: "房产买卖、投资分析、装修与物业管理", + name: "自媒体内容", slug: "content", icon: "🎬", sortOrder: 3, + description: "短视频、直播、图文与MCN运营", children: [ - { name: "住宅买卖", slug: "re-residential", icon: "🏡", description: "刚需/改善/学区房交易" }, - { name: "商业地产", slug: "re-commercial", icon: "🏢", description: "商铺/写字楼/产业园投资" }, - { name: "装修家居", slug: "re-renovation", icon: "🛋️", description: "装修设计/建材/智能家居" }, - { name: "物业运营", slug: "re-property", icon: "🏗️", description: "物业管理/租赁运营/资产托管" }, + { name: "短视频创作", slug: "ct-short-video", icon: "📱", description: "抖音/快手/B站/视频号创作" }, + { name: "直播运营", slug: "ct-live", icon: "🎥", description: "带货直播/秀场/知识直播" }, + { name: "图文内容", slug: "ct-writing", icon: "✍️", description: "公众号/小红书/知乎/头条" }, + { name: "MCN机构", slug: "ct-mcn", icon: "🏢", description: "达人孵化/商务变现/MCN运营" }, + { name: "播客与音频", slug: "ct-podcast", icon: "🎙️", description: "小宇宙/喜马拉雅/音频创作" }, ], }, { name: "金融投资", slug: "finance", icon: "📈", sortOrder: 4, - description: "股票基金、加密货币、保险理财与股权投资", + description: "股票基金、加密货币、PE/VC与理财", children: [ - { name: "股票基金", slug: "fi-stock", icon: "📊", description: "A股/港股/美股/基金定投" }, - { name: "加密货币", slug: "fi-crypto", icon: "₿", description: "比特币/以太坊/Web3" }, - { name: "保险理财", slug: "fi-insurance", icon: "🛡️", description: "保险配置/理财规划" }, - { name: "私募股权", slug: "fi-pe", icon: "💼", description: "PE/VC/天使投资" }, + { name: "股票与基金", slug: "fi-stock", icon: "📊", description: "A股/港股/美股/基金定投" }, + { name: "加密货币/Web3", slug: "fi-crypto", icon: "₿", description: "比特币/以太坊/DeFi/NFT" }, + { name: "保险与理财", slug: "fi-insurance", icon: "🛡️", description: "保险配置/理财规划/资产配置" }, + { name: "PE与VC", slug: "fi-pe", icon: "💼", description: "PE/VC/天使投资/项目评估" }, + { name: "外汇与期货", slug: "fi-forex", icon: "💱", description: "外汇/黄金/大宗商品/期货" }, ], }, { - name: "餐饮食品", slug: "food", icon: "🍜", sortOrder: 5, - description: "餐饮创业、茶饮咖啡、预制菜与食品供应链", + name: "外贸跨境", slug: "cross-border", icon: "🌏", sortOrder: 5, + description: "跨境电商、外贸工厂、物流与品牌出海", + children: [ + { name: "跨境电商平台", slug: "cb-ecommerce", icon: "🛒", description: "Amazon/Temu/TikTok Shop/Shopee" }, + { name: "外贸工厂/B2B", slug: "cb-factory", icon: "🏭", description: "代工转品牌/工贸一体/展会" }, + { name: "海外仓与物流", slug: "cb-logistics", icon: "📦", description: "海外仓/FBA/跨境物流/清关" }, + { name: "跨境支付合规", slug: "cb-payment", icon: "💳", description: "收付款/汇率/税务合规" }, + { name: "品牌出海/DTC", slug: "cb-brand", icon: "🚩", description: "独立站/品牌全球化/本地化" }, + ], + }, + { + name: "房地产", slug: "real-estate", icon: "🏠", sortOrder: 6, + description: "房产买卖、商业地产、装修与物业", + children: [ + { name: "住宅买卖", slug: "re-residential", icon: "🏡", description: "刚需/改善/学区房/公寓" }, + { name: "商业地产", slug: "re-commercial", icon: "🏢", description: "商铺/写字楼/产业园/酒店" }, + { name: "装修与家居", slug: "re-renovation", icon: "🛋️", description: "装修设计/建材/智能家居" }, + { name: "物业与租赁", slug: "re-property", icon: "🏗️", description: "物业管理/租赁运营/资产托管" }, + ], + }, + { + name: "餐饮食品", slug: "food", icon: "🍜", sortOrder: 7, + description: "餐饮创业、茶饮咖啡、预制菜与供应链", children: [ { name: "餐饮开店", slug: "fd-restaurant", icon: "🍽️", description: "餐厅选址/运营/连锁加盟" }, - { name: "茶饮咖啡", slug: "fd-tea", icon: "🧋", description: "新茶饮/咖啡/饮品创业" }, - { name: "预制菜", slug: "fd-prepared", icon: "📦", description: "预制菜/半成品/食品加工" }, - { name: "食品供应链", slug: "fd-supply", icon: "🚚", description: "食材采购/冷链/中央厨房" }, + { name: "茶饮与咖啡", slug: "fd-tea", icon: "🧋", description: "新茶饮/咖啡品牌/饮品创业" }, + { name: "预制菜加工", slug: "fd-prepared", icon: "📦", description: "预制菜/半成品/中央厨房" }, + { name: "食品供应链", slug: "fd-supply", icon: "🚚", description: "食材采购/冷链/仓储配送" }, + { name: "外卖运营", slug: "fd-delivery", icon: "🛵", description: "美团/饿了么/外卖代运营" }, ], }, { - name: "自媒体内容", slug: "content", icon: "🎬", sortOrder: 6, - description: "短视频、直播、图文创作与MCN机构运营", + name: "本地生活", slug: "local-life", icon: "🏪", sortOrder: 8, + description: "美业、健身、宠物、家政等本地服务", children: [ - { name: "短视频创作", slug: "ct-short-video", icon: "📱", description: "抖音/快手/B站内容创作" }, - { name: "直播运营", slug: "ct-livestream", icon: "🎥", description: "带货直播/娱乐直播/知识直播" }, - { name: "图文内容", slug: "ct-writing", icon: "✍️", description: "公众号/小红书/知乎/头条" }, - { name: "MCN机构", slug: "ct-mcn", icon: "🏢", description: "MCN运营/达人孵化/商务变现" }, + { name: "美容美发", slug: "ll-beauty", icon: "💇", description: "美发/美甲/美容/皮肤管理" }, + { name: "健身运动", slug: "ll-fitness", icon: "🏋️", description: "健身房/瑜伽/私教/运动馆" }, + { name: "宠物经济", slug: "ll-pet", icon: "🐾", description: "宠物店/食品/医疗/寄养" }, + { name: "家政服务", slug: "ll-housekeeping", icon: "🏠", description: "保洁/月嫂/搬家/收纳" }, + { name: "维修与数码", slug: "ll-repair", icon: "🔧", description: "手机维修/家电清洗/开锁" }, + { name: "本地教培", slug: "ll-edu-local", icon: "🎓", description: "托管/艺术培训/体育培训" }, ], }, { - name: "本地生活", slug: "local-life", icon: "🏪", sortOrder: 7, - description: "美业、健身、宠物、家政等本地服务创业", - children: [ - { name: "美容美发", slug: "ll-beauty", icon: "💇", description: "美发/美甲/美容/医美" }, - { name: "健身运动", slug: "ll-fitness", icon: "🏋️", description: "健身房/瑜伽/私教/运动康复" }, - { name: "宠物经济", slug: "ll-pet", icon: "🐾", description: "宠物店/宠物食品/宠物医疗" }, - { name: "家政服务", slug: "ll-housekeeping", icon: "🏠", description: "保洁/月嫂/搬家/维修" }, - ], - }, - { - name: "大健康", slug: "health", icon: "💊", sortOrder: 8, - description: "医疗美容、健康管理、养老服务与运动康复", + name: "大健康", slug: "health", icon: "💊", sortOrder: 9, + description: "医疗美容、健康管理、养老与康复", children: [ { name: "医疗美容", slug: "hl-cosmetic", icon: "💉", description: "轻医美/微整形/皮肤管理" }, - { name: "健康管理", slug: "hl-wellness", icon: "🫀", description: "体检/慢病管理/保健品" }, - { name: "养老服务", slug: "hl-elderly", icon: "👴", description: "养老院/居家养老/适老化改造" }, - { name: "运动康复", slug: "hl-rehab", icon: "🩹", description: "运动损伤/产后康复/中医理疗" }, + { name: "健康管理", slug: "hl-wellness", icon: "🫀", description: "体检/慢病/保健品/营养" }, + { name: "养老服务", slug: "hl-elderly", icon: "👴", description: "养老院/居家养老/适老化" }, + { name: "运动康复", slug: "hl-rehab", icon: "🩹", description: "运动损伤/产后康复/理疗" }, + { name: "心理健康", slug: "hl-mental", icon: "🧘", description: "心理咨询/情绪管理/冥想" }, ], }, { - name: "教育培训", slug: "education", icon: "📚", sortOrder: 9, + name: "教育培训", slug: "education", icon: "📚", sortOrder: 10, description: "技能培训、知识付费、留学与企业培训", children: [ - { name: "技能培训", slug: "edu-skills", icon: "🛠️", description: "编程/设计/运营等职业技能" }, - { name: "知识付费", slug: "edu-knowledge", icon: "💎", description: "课程制作/社群运营/个人IP" }, - { name: "留学服务", slug: "edu-abroad", icon: "✈️", description: "留学申请/语言培训/海外游学" }, - { name: "企业培训", slug: "edu-corporate", icon: "🏢", description: "企业内训/管理咨询/团队建设" }, - ], - }, - { - name: "外贸跨境", slug: "cross-border", icon: "🌏", sortOrder: 10, - description: "跨境电商、外贸工厂、海外仓与跨境支付", - children: [ - { name: "跨境电商", slug: "cb-ecommerce", icon: "🛒", description: "Amazon/Temu/TikTok Shop/Shopee" }, - { name: "外贸工厂", slug: "cb-factory", icon: "🏭", description: "代工转品牌/工贸一体/B2B" }, - { name: "海外仓物流", slug: "cb-logistics", icon: "📦", description: "海外仓/FBA/跨境物流" }, - { name: "跨境支付", slug: "cb-payment", icon: "💳", description: "收付款/汇率/资金合规" }, + { name: "职业技能", slug: "edu-skills", icon: "🛠️", description: "编程/设计/运营/考证培训" }, + { name: "知识付费", slug: "edu-knowledge", icon: "💎", description: "课程制作/社群/个人IP打造" }, + { name: "留学与语言", slug: "edu-abroad", icon: "✈️", description: "留学申请/语言培训/游学" }, + { name: "企业培训", slug: "edu-corporate", icon: "🏢", description: "企业内训/管理咨询/团建" }, + { name: "K12与家庭", slug: "edu-k12", icon: "👨‍👩‍👧", description: "学科辅导/素质教育/家庭教育" }, ], }, ]; diff --git a/src/app/community/CommunityRankings.tsx b/src/app/community/CommunityRankings.tsx new file mode 100644 index 0000000..5a27623 --- /dev/null +++ b/src/app/community/CommunityRankings.tsx @@ -0,0 +1,104 @@ +"use client"; + +import { useState, useEffect } from "react"; +import Link from "next/link"; +import { getLevelInfo } from "@/lib/level-config"; + +interface UserRanking { + id: number; + name: string | null; + email: string; + avatarUrl: string | null; + level: string; + points: number; + bio?: string | null; +} + +export function CommunityRankings() { + const [monthlyActive, setMonthlyActive] = useState([]); + const [topByPoints, setTopByPoints] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch("/api/user/rankings?type=active&limit=10") + .then((r) => r.json()) + .then((data) => { + setMonthlyActive(data.users || []); + }) + .catch(() => {}); + + fetch("/api/user/rankings?type=points&limit=10") + .then((r) => r.json()) + .then((data) => { + setTopByPoints(data.users || []); + setLoading(false); + }) + .catch(() => { + setLoading(false); + }); + }, []); + + const renderSkeleton = () => + Array.from({ length: 10 }).map((_, i) => ( +
+
+
+
+
+ )); + + const renderUserRow = (user: UserRanking, i: number) => { + const initial = user.name?.charAt(0).toUpperCase() || user.email.charAt(0).toUpperCase() || "?"; + const levelInfo = getLevelInfo(user.points); + return ( + + {i + 1} + {user.avatarUrl ? ( + + ) : ( +
+ {initial} +
+ )} + {user.name || user.email?.split("@")[0]} + {levelInfo && ( + {levelInfo.label} + )} + + ); + }; + + return ( + <> +
+
+ + + + 本月活跃用户 +
+
+ {loading ? renderSkeleton() : monthlyActive.map(renderUserRow)} +
+
+ +
+ +
+
+ + + + 积分总排行 +
+
+ {loading ? renderSkeleton() : topByPoints.map(renderUserRow)} +
+
+ + ); +} \ No newline at end of file diff --git a/src/app/community/CommunitySidebar.tsx b/src/app/community/CommunitySidebar.tsx index ec7ba62..86caf39 100644 --- a/src/app/community/CommunitySidebar.tsx +++ b/src/app/community/CommunitySidebar.tsx @@ -1,147 +1,132 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState } from "react"; import Link from "next/link"; -import { getLevelInfo } from "@/lib/level-config"; +import { usePathname } from "next/navigation"; -const INDUSTRY_FORUMS = [ - { name: "电商零售", slug: "ecommerce", icon: "🛒" }, - { name: "AI智能科技", slug: "ai-tech", icon: "🤖" }, - { name: "房地产", slug: "real-estate", icon: "🏠" }, - { name: "金融投资", slug: "finance", icon: "📈" }, - { name: "餐饮食品", slug: "food", icon: "🍜" }, - { name: "自媒体内容", slug: "content", icon: "🎬" }, - { name: "本地生活", slug: "local-life", icon: "🏪" }, - { name: "大健康", slug: "health", icon: "💊" }, - { name: "教育培训", slug: "education", icon: "📚" }, - { name: "外贸跨境", slug: "cross-border", icon: "🌏" }, -]; - -interface UserRanking { +interface ForumCategoryChild { id: number; - name: string | null; - email: string; - avatarUrl: string | null; - level: string; - points: number; - bio?: string | null; + name: string; + slug: string; + icon: string | null; + description: string | null; + topicCount: number; } -export function CommunitySidebar() { - const [monthlyActive, setMonthlyActive] = useState([]); - const [topByPoints, setTopByPoints] = useState([]); - const [loading, setLoading] = useState(true); +interface ForumCategory { + id: number; + name: string; + slug: string; + icon: string | null; + description: string | null; + topicCount: number; + children: ForumCategoryChild[]; +} - useEffect(() => { - fetch("/api/user/rankings?type=active&limit=10") - .then((r) => r.json()) - .then((data) => { - setMonthlyActive(data.users || []); +interface CommunitySidebarProps { + categories: ForumCategory[]; + totalTopics: number; +} + +export function CommunitySidebar({ categories, totalTopics }: CommunitySidebarProps) { + const pathname = usePathname(); + const [search, setSearch] = useState(""); + + const filteredCategories = search.trim() + ? categories.filter((cat) => { + const catMatch = cat.name.includes(search) || cat.slug.includes(search); + const childMatch = cat.children.some( + (c) => c.name.includes(search) || c.slug.includes(search) + ); + return catMatch || childMatch; }) - .catch(() => {}) - .finally(() => {}); + : categories; - fetch("/api/user/rankings?type=points&limit=10") - .then((r) => r.json()) - .then((data) => { - setTopByPoints(data.users || []); - setLoading(false); - }) - .catch(() => { - setLoading(false); - }); - }, []); + const totalSubCategories = categories.reduce((sum, c) => sum + c.children.length, 0); + const totalAll = categories.length + totalSubCategories; - const renderSkeleton = () => ( - Array.from({ length: 10 }).map((_, i) => ( -
-
-
-
-
- )) - ); + const isActive = (slug: string) => pathname === `/community/${slug}` || pathname.startsWith(`/community/${slug}`); - const renderUserRow = (user: UserRanking, i: number) => { - const initial = user.name?.charAt(0).toUpperCase() || user.email.charAt(0).toUpperCase() || "?"; - const levelInfo = getLevelInfo(user.points); - return ( - - {i + 1} - {user.avatarUrl ? ( - - ) : ( -
- {initial} -
- )} - {user.name || user.email?.split("@")[0]} - {levelInfo && ( - {levelInfo.label} - )} - - ); - }; + const parentItemClass = (slug: string) => + `flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-[13px] font-semibold transition-all duration-200 ${ + isActive(slug) + ? "bg-sky-50 text-sky-700 shadow-sm" + : "text-foreground/80 hover:bg-white hover:text-foreground hover:shadow-sm" + }`; + + const childItemClass = (slug: string) => + `flex w-full items-center gap-2 rounded-lg px-2.5 py-1.5 text-[12px] transition-all duration-200 pl-7 ${ + isActive(slug) + ? "bg-sky-50/60 text-sky-600" + : "text-muted-foreground hover:bg-white hover:text-foreground hover:shadow-sm" + }`; return ( -
+ ); } \ No newline at end of file diff --git a/src/app/community/page.tsx b/src/app/community/page.tsx index df456c2..a9d7384 100644 --- a/src/app/community/page.tsx +++ b/src/app/community/page.tsx @@ -2,20 +2,26 @@ import { prisma } from "@/lib/prisma"; import Link from "next/link"; import { HeroBanner } from "@/components/common/HeroBanner"; import { CommunitySidebar } from "./CommunitySidebar"; +import { CommunityRankings } from "./CommunityRankings"; export const dynamic = "force-dynamic"; export default async function CommunityPage() { - const [categories, topicsCount, userCount] = await Promise.all([ - prisma.forumCategory.findMany({ - where: { parentId: null }, - include: { - children: { - orderBy: [{ sortOrder: "asc" }], - }, + const industryParent = await prisma.forumCategory.findUnique({ + where: { slug: "industry" }, + }); + + const categories = await prisma.forumCategory.findMany({ + where: { parentId: industryParent?.id ?? undefined }, + include: { + children: { + orderBy: [{ sortOrder: "asc" }], }, - orderBy: [{ sortOrder: "asc" }, { createdAt: "desc" }], - }), + }, + orderBy: [{ sortOrder: "asc" }, { createdAt: "desc" }], + }); + + const [topicsCount, userCount] = await Promise.all([ prisma.forumTopic.count(), prisma.user.count(), ]); @@ -31,13 +37,17 @@ export default async function CommunityPage() { take: 5, }); + const totalSubCategories = categories.reduce((sum, c) => sum + c.children.length, 0); + return (
-
+
- {/* Left Sidebar: Rankings */} + {/* Left Sidebar: Two-level navigation */} {/* Middle Content */} @@ -47,18 +57,18 @@ export default async function CommunityPage() { highlight="会" colorScheme="forest" stats={[ - { label: "板块", value: categories.reduce((sum, c) => sum + c.children.length + 1, 0), unit: "个" }, + { label: "板块", value: categories.length + totalSubCategories, unit: "个" }, { label: "话题", value: topicsCount, unit: "帖" }, { label: "会员", value: userCount, unit: "人" }, ]} - slogan="AI爱好者交流社区,分享你的发现和思考" - subSlogan="AI工具 · 开源技能 · 技术深度 · 教程分享 · 社区互动" + slogan="AI驱动的行业智囊团,连接商业智慧" + subSlogan="电商零售 · AI科技 · 金融投资 · 跨境出海 · 实体经营" /> {/* Forum Categories */}
-

板块

+

全部板块

{categories.map((cat) => ( @@ -142,9 +152,9 @@ export default async function CommunityPage() {
- {/* Right Sidebar */} + {/* Right Sidebar: Guide + Rankings */}