<title>仿真论坛原型</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* 自定义一些简单的动画或样式补充 */
.modal {
transition: opacity 0.3s ease;
}
.modal.hidden {
display: none;
}
body {
background-color: #f3f4f6; /* gray-100 */
}
</style>
<!-- 顶部导航栏 -->
<nav class="sticky top-0 z-50 bg-white border-b border-gray-200 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<!-- Logo -->
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center gap-2 cursor-pointer">
<div class="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-white font-bold">F</div>
<span class="font-bold text-xl text-blue-600">ForumPro</span>
</div>
</div>
<!-- 搜索框 -->
<div class="flex-1 flex items-center justify-center px-2 lg:ml-6 lg:justify-end">
<div class="max-w-lg w-full lg:max-w-xs">
<label for="search" class="sr-only">搜索</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<input id="search" class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-full leading-5 bg-gray-50 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 sm:text-sm transition duration-150 ease-in-out" placeholder="搜索帖子..." type="search">
</div>
</div>
</div>
<!-- 用户头像 -->
<div class="flex items-center ml-4">
<button class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-gray-300 transition duration-150 ease-in-out">
<img class="h-8 w-8 rounded-full object-cover" src="https://api.dicebear.com/7.x/avataaars/svg?seed=Felix" alt="User Avatar">
</button>
</div>
</div>
</div>
</nav>
<!-- 主体内容 -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="grid grid-cols-1 md:grid-cols-12 gap-6">
<!-- 左侧:板块列表 -->
<div class="hidden md:block md:col-span-3">
<div class="bg-white rounded-lg shadow p-4 sticky top-24">
<h2 class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-4">板块列表</h2>
<nav class="space-y-1">
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-gray-900 bg-gray-100 rounded-md group">
<span class="truncate">全部内容</span>
</a>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:bg-gray-50 hover:text-gray-900 group">
<span class="truncate">前端开发</span>
</a>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:bg-gray-50 hover:text-gray-900 group">
<span class="truncate">后端架构</span>
</a>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:bg-gray-50 hover:text-gray-900 group">
<span class="truncate">人工智能</span>
</a>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:bg-gray-50 hover:text-gray-900 group">
<span class="truncate">生活闲聊</span>
</a>
</nav>
</div>
</div>
<!-- 中间:帖子列表 -->
<div class="md:col-span-9 lg:col-span-6 space-y-4">
<!-- 发布帖子入口 -->
<div class="bg-white p-4 rounded-lg shadow flex items-center space-x-4">
<img class="h-10 w-10 rounded-full bg-gray-200" src="https://api.dicebear.com/7.x/avataaars/svg?seed=Felix" alt="">
<input type="text" id="create-post-trigger" class="flex-1 bg-gray-100 hover:bg-gray-200 rounded-full px-4 py-2 text-sm cursor-pointer border-none focus:outline-none transition" placeholder="分享你的想法..." readonly>
<button id="create-btn-icon" class="text-gray-400 hover:text-blue-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
</button>
</div>
<!-- 帖子容器 -->
<div id="posts-container" class="space-y-4">
<!-- JS动态生成内容 -->
</div>
</div>
<!-- 右侧:热门话题 -->
<div class="hidden lg:block lg:col-span-3">
<div class="bg-white rounded-lg shadow p-4 sticky top-24">
<div class="flex items-center justify-between mb-4">
<h2 class="text-sm font-bold text-gray-900">热门话题</h2>
<a href="#" class="text-xs text-blue-600 hover:underline">更多</a>
</div>
<ul class="space-y-4">
<li class="flex flex-col">
<span class="text-xs text-gray-500">前端 · 热门</span>
<a href="#" class="text-sm font-medium text-gray-900 hover:underline mt-1">Tailwind CSS 4.0 即将发布,有什么新特性?</a>
<span class="text-xs text-gray-400 mt-1">125 帖子</span>
</li>
<li class="flex flex-col border-t border-gray-100 pt-3">
<span class="text-xs text-gray-500">科技 · 趋势</span>
<a href="#" class="text-sm font-medium text-gray-900 hover:underline mt-1">AI 编程助手会取代初级程序员吗?</a>
<span class="text-xs text-gray-400 mt-1">3.4k 帖子</span>
</li>
<li class="flex flex-col border-t border-gray-100 pt-3">
<span class="text-xs text-gray-500">职场 · 讨论</span>
<a href="#" class="text-sm font-medium text-gray-900 hover:underline mt-1">2026年互联网行业薪资报告</a>
<span class="text-xs text-gray-400 mt-1">892 帖子</span>
</li>
</ul>
</div>
<!-- 版权/页脚信息 -->
<div class="mt-4 px-4">
<p class="text-xs text-gray-500 leading-5">
© 2026 ForumPro Inc. <br>
用户协议 · 隐私政策 · 帮助中心
</p>
</div>
</div>
</div>
</div>
<!-- 模态框 (Modal) -->
<div id="post-modal" class="fixed inset-0 z-50 hidden overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<!-- 背景遮罩 -->
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true" id="modal-backdrop"></div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start w-full">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">发布新帖子</h3>
<div class="mt-4 space-y-4">
<div>
<label for="post-title" class="block text-sm font-medium text-gray-700">标题</label>
<input type="text" id="post-title" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" placeholder="请输入标题">
</div>
<div>
<label for="post-content" class="block text-sm font-medium text-gray-700">内容</label>
<textarea id="post-content" rows="4" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" placeholder="分享你的观点..."></textarea>
</div>
<div>
<label for="post-author" class="block text-sm font-medium text-gray-700">作者昵称</label>
<input type="text" id="post-author" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm" value="匿名用户">
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="submit-post" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
发布
</button>
<button type="button" id="cancel-post" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
取消
</button>
</div>
</div>
</div>
</div>
<script>
// 初始数据
const initialPosts = [
{
id: 1,
title: "如何看待 WebAssembly 的未来发展?",
author: "技术宅小王",
content: "WebAssembly (Wasm) 正在改变我们在浏览器中运行高性能应用的方式。大家觉得它会取代 JavaScript 吗?还是会共存?最近在看 Rust 编译到 Wasm 的项目,感觉潜力巨大。",
likes: 342,
comments: 56,
time: "2小时前",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Jack"
},
{
id: 2,
title: "分享一组自己拍的赛博朋克风格夜景",
author: "摄影师Li",
content: "昨天晚上去重庆洪崖洞拍的,后期调色用了 Lightroom。这种霓虹灯的感觉真的太棒了,仿佛置身于未来世界。大家给点意见?",
likes: 1205,
comments: 89,
time: "5小时前",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Annie"
},
{
id: 3,
title: "Tailwind CSS 真的比手写 CSS 香吗?",
author: "FrontendNewbie",
content: "最近刚开始学 Tailwind,感觉 HTML 变得好乱啊,全是类名。但是不用来回切文件写 CSS 确实挺爽的。老哥们怎么看?",
likes: 89,
comments: 124,
time: "1天前",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Bob"
},
{
id: 4,
title: "推荐几本适合程序员读的非技术书",
author: "BookWorm",
content: "整天看代码头都大了,想看点人文社科或者科幻小说放松一下。最近看了《三体》和《黑客与画家》,求推荐类似的!",
likes: 567,
comments: 45,
time: "1天前",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Cathy"
},
{
id: 5,
title: "年度最佳独立游戏提名出炉",
author: "GameMaster",
content: "TGA 刚刚公布了名单,《Hades 2》赫然在列!感觉今年的独立游戏质量都好高啊,大家玩过哪几个?",
likes: 231,
comments: 12,
time: "2天前",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Dave"
}
];
// 状态管理
let posts = [...initialPosts];
// DOM 元素
const postsContainer = document.getElementById('posts-container');
const modal = document.getElementById('post-modal');
const createTrigger = document.getElementById('create-post-trigger');
const createIconBtn = document.getElementById('create-btn-icon');
const submitBtn = document.getElementById('submit-post');
const cancelBtn = document.getElementById('cancel-post');
const modalBackdrop = document.getElementById('modal-backdrop');
const inputTitle = document.getElementById('post-title');
const inputContent = document.getElementById('post-content');
const inputAuthor = document.getElementById('post-author');
// 渲染函数
function renderPosts() {
postsContainer.innerHTML = '';
posts.forEach(post => {
const postElement = document.createElement('div');
postElement.className = 'bg-white p-4 rounded-lg shadow hover:shadow-md transition duration-200 cursor-pointer border border-transparent hover:border-gray-200';
postElement.innerHTML = `
<div class="flex items-start space-x-3">
<!-- 侧边点赞栏 (仿 Reddit) -->
<div class="flex flex-col items-center space-y-1 bg-gray-50 p-2 rounded w-10 flex-shrink-0">
<button class="text-gray-400 hover:text-orange-500 hover:bg-gray-200 rounded p-1 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path></svg>
</button>
<span class="text-sm font-bold text-gray-700">${formatLikes(post.likes)}</span>
<button class="text-gray-400 hover:text-blue-500 hover:bg-gray-200 rounded p-1 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
</button>
</div>
<!-- 帖子主体 -->
<div class="flex-1 min-w-0">
<div class="flex items-center text-xs text-gray-500 mb-1 space-x-2">
<img src="${post.avatar}" class="w-5 h-5 rounded-full" alt="avatar">
<span class="font-medium text-gray-700 hover:underline">u/${post.author}</span>
<span>•</span>
<span>${post.time}</span>
</div>
<h3 class="text-lg font-semibold text-gray-900 mb-1 leading-snug">${post.title}</h3>
<p class="text-gray-600 text-sm line-clamp-3 mb-3">${post.content}</p>
<!-- 底部操作栏 -->
<div class="flex items-center space-x-4">
<button class="flex items-center space-x-1 text-gray-500 hover:bg-gray-100 px-2 py-1 rounded text-xs font-medium transition">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path></svg>
<span>${post.comments} 评论</span>
</button>
<button class="flex items-center space-x-1 text-gray-500 hover:bg-gray-100 px-2 py-1 rounded text-xs font-medium transition">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"></path></svg>
<span>分享</span>
</button>
<button class="flex items-center space-x-1 text-gray-500 hover:bg-gray-100 px-2 py-1 rounded text-xs font-medium transition">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"></path></svg>
<span>收藏</span>
</button>
</div>
</div>
</div>
`;
postsContainer.appendChild(postElement);
});
}
function formatLikes(num) {
if (num >= 1000) {
return (num / 1000).toFixed(1) + 'k';
}
return num;
}
// 模态框控制
function openModal() {
modal.classList.remove('hidden');
// 简单动画效果
setTimeout(() => {
const panel = modal.querySelector('.transform');
panel.classList.remove('opacity-0', 'translate-y-4', 'sm:translate-y-0', 'sm:scale-95');
panel.classList.add('opacity-100', 'translate-y-0', 'sm:scale-100');
}, 10);
}
function closeModal() {
const panel = modal.querySelector('.transform');
// 简单的关闭动画(这里直接隐藏,实际开发可以用 CSS transition end 事件)
modal.classList.add('hidden');
// 清空输入
inputTitle.value = '';
inputContent.value = '';
inputAuthor.value = '匿名用户';
}
// 添加新帖子
function addNewPost() {
const title = inputTitle.value.trim();
const content = inputContent.value.trim();
const author = inputAuthor.value.trim() || "匿名用户";
if (!title || !content) {
alert("请填写标题和内容");
return;
}
const newPost = {
id: posts.length + 1,
title: title,
author: author,
content: content,
likes: 0,
comments: 0,
time: "刚刚",
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${Math.random()}`
};
// 添加到数组开头
posts.unshift(newPost);
// 重新渲染
renderPosts();
// 关闭模态框
closeModal();
}
// 事件监听
createTrigger.addEventListener('click', openModal);