社交平台是Web开发中最具挑战性的项目类型之一,它涉及用户关系、内容发布、实时通讯、消息推送等多个核心模块,是学习现代Web技术的综合实践项目。
东巴文(db-w.cn) 认为:社交平台不仅是技术平台,更是连接人与人的桥梁。好的社交平台应该让分享变得简单,让交流变得自然。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>项目规划 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.goal-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
margin: 15px 0;
border-radius: 10px;
}
.goal-card h3 {
margin-bottom: 10px;
}
.info-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.info-table th,
.info-table td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
.info-table th {
background: #667eea;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>项目规划</h1>
<h2>项目目标</h2>
<div class="goal-card">
<h3>🎯 核心目标</h3>
<ul>
<li>实现用户注册和登录</li>
<li>支持内容发布和分享</li>
<li>实现用户关注和粉丝</li>
<li>支持点赞、评论、转发</li>
</ul>
</div>
<div class="goal-card">
<h3>🎯 次要目标</h3>
<ul>
<li>实现实时消息通讯</li>
<li>支持图片和视频上传</li>
<li>添加消息推送功能</li>
<li>实现内容推荐算法</li>
</ul>
</div>
<h2>技术选型</h2>
<table class="info-table">
<thead>
<tr>
<th>技术层</th>
<th>技术选择</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>前端</td>
<td>HTML5 + CSS3 + JavaScript</td>
<td>原生技术,性能优化</td>
</tr>
<tr>
<td>后端</td>
<td>Node.js + Express / Socket.io</td>
<td>支持实时通讯</td>
</tr>
<tr>
<td>数据库</td>
<td>MongoDB + Redis</td>
<td>文档数据库 + 缓存</td>
</tr>
<tr>
<td>消息队列</td>
<td>RabbitMQ / Kafka</td>
<td>异步消息处理</td>
</tr>
<tr>
<td>搜索</td>
<td>Elasticsearch</td>
<td>全文搜索</td>
</tr>
<tr>
<td>部署</td>
<td>云服务器 + CDN</td>
<td>高可用架构</td>
</tr>
</tbody>
</table>
<h2>项目范围</h2>
<ul>
<li><strong>用户角色:</strong> 普通用户、认证用户、管理员</li>
<li><strong>核心功能:</strong> 内容发布、社交互动、消息通讯</li>
<li><strong>开发周期:</strong> 10-16周</li>
<li><strong>团队规模:</strong> 4-6人</li>
</ul>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>社交平台要特别关注性能和扩展性。实时通讯、消息推送、内容推荐等功能对系统性能要求高,要做好架构设计。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>需求分析 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.feature-list {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.feature-list h3 {
color: #667eea;
margin-bottom: 10px;
}
.feature-item {
background: white;
padding: 15px;
margin: 10px 0;
border-left: 4px solid #667eea;
}
.info-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.info-table th,
.info-table td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
.info-table th {
background: #667eea;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>需求分析</h1>
<h2>功能需求</h2>
<div class="feature-list">
<h3>👤 用户管理</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>用户注册和登录</li>
<li>个人资料设置</li>
<li>头像和背景图上传</li>
<li>账号安全设置</li>
<li>隐私设置</li>
<li>用户认证</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>📝 内容发布</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>发布文字内容</li>
<li>上传图片和视频</li>
<li>添加话题标签</li>
<li>@提及用户</li>
<li>内容编辑和删除</li>
<li>内容审核</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>💬 社交互动</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>关注和取消关注</li>
<li>点赞和取消点赞</li>
<li>评论和回复</li>
<li>转发和引用</li>
<li>收藏内容</li>
<li>分享到其他平台</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>📨 消息系统</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>私信聊天</li>
<li>群组聊天</li>
<li>消息通知</li>
<li>系统通知</li>
<li>消息已读状态</li>
<li>消息撤回</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>🔍 内容发现</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>内容搜索</li>
<li>用户搜索</li>
<li>话题搜索</li>
<li>热门话题</li>
<li>推荐内容</li>
<li>附近的人</li>
</ul>
</div>
</div>
<h2>非功能需求</h2>
<table class="info-table">
<thead>
<tr>
<th>需求类型</th>
<th>具体要求</th>
<th>优先级</th>
</tr>
</thead>
<tbody>
<tr>
<td>性能</td>
<td>支持高并发,实时消息延迟 < 100ms</td>
<td>高</td>
</tr>
<tr>
<td>可扩展性</td>
<td>支持横向扩展,微服务架构</td>
<td>高</td>
</tr>
<tr>
<td>可用性</td>
<td>99.9%可用性,数据备份</td>
<td>高</td>
</tr>
<tr>
<td>安全</td>
<td>内容审核,隐私保护,防攻击</td>
<td>高</td>
</tr>
<tr>
<td>用户体验</td>
<td>响应式设计,流畅交互</td>
<td>高</td>
</tr>
</tbody>
</table>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>社交平台要特别注意内容审核和隐私保护。建立完善的内容审核机制,保护用户隐私数据,营造健康的社区环境。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据库设计 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.db-schema {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.db-schema h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>数据库设计</h1>
<h2>数据模型</h2>
<div class="db-schema">
<h3>用户表(Users)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"username": String, // 用户名
"email": String, // 邮箱
"phone": String, // 手机号
"password": String, // 加密密码
"nickname": String, // 昵称
"avatar": String, // 头像
"bio": String, // 个人简介
"gender": String, // 性别
"birthday": Date, // 生日
"location": String, // 位置
"website": String, // 个人网站
"verified": Boolean, // 是否认证
"verify_type": String, // 认证类型
"followers_count": Number, // 粉丝数
"following_count": Number, // 关注数
"posts_count": Number, // 发布数
"likes_count": Number, // 获赞数
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>帖子表(Posts)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"user_id": ObjectId, // 发布者ID
"content": String, // 内容
"images": [String], // 图片列表
"video": { // 视频
"url": String,
"thumbnail": String,
"duration": Number
},
"tags": [String], // 话题标签
"mentions": [ObjectId], // @提及的用户
"location": { // 位置
"name": String,
"coordinates": [Number] // [经度, 纬度]
},
"visibility": String, // 可见性(public, friends, private)
"likes_count": Number, // 点赞数
"comments_count": Number, // 评论数
"shares_count": Number, // 转发数
"is_pinned": Boolean, // 是否置顶
"is_hot": Boolean, // 是否热门
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>评论表(Comments)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"post_id": ObjectId, // 帖子ID
"user_id": ObjectId, // 评论者ID
"content": String, // 评论内容
"reply_to": ObjectId, // 回复的评论ID
"mentions": [ObjectId], // @提及的用户
"likes_count": Number, // 点赞数
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>关注关系表(Follows)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"follower_id": ObjectId, // 关注者ID
"following_id": ObjectId, // 被关注者ID
"created_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>消息表(Messages)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"conversation_id": ObjectId, // 会话ID
"sender_id": ObjectId, // 发送者ID
"receiver_id": ObjectId, // 接收者ID
"content": String, // 消息内容
"type": String, // 消息类型(text, image, video)
"media_url": String, // 媒体URL
"read": Boolean, // 是否已读
"read_at": Date, // 阅读时间
"created_at": Date
}
</pre>
</div>
</div>
<h2>索引设计</h2>
<ul>
<li><strong>用户表:</strong> username(唯一), email(唯一), phone(唯一)</li>
<li><strong>帖子表:</strong> user_id, created_at, tags, location(地理索引)</li>
<li><strong>评论表:</strong> post_id, user_id, created_at</li>
<li><strong>关注关系表:</strong> follower_id + following_id(复合唯一索引)</li>
<li><strong>消息表:</strong> conversation_id, created_at</li>
</ul>
<h2>缓存策略</h2>
<ul>
<li><strong>用户信息:</strong> Redis缓存,过期时间1小时</li>
<li><strong>热门帖子:</strong> Redis缓存,过期时间10分钟</li>
<li><strong>关注关系:</strong> Redis Set存储</li>
<li><strong>消息未读数:</strong> Redis计数器</li>
</ul>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>社交平台数据量大,要合理使用缓存和索引。Redis缓存热点数据,MongoDB索引优化查询性能,确保系统响应速度。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户系统 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.user-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.user-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>用户系统</h1>
<h2>注册登录</h2>
<div class="user-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 注册表单 -->
<form id="register-form" class="auth-form">
<h2>注册账号</h2>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" name="username" required
minlength="3" maxlength="20"
pattern="[a-zA-Z0-9_]+">
<span class="hint">3-20个字符,只能包含字母、数字、下划线</span>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" required
minlength="8" maxlength="32">
<div class="password-strength">
<div class="strength-bar"></div>
<span class="strength-text">密码强度</span>
</div>
</div>
<div class="form-group">
<label for="confirm-password">确认密码</label>
<input type="password" id="confirm-password" name="confirm_password" required>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="agree" required>
<span>我已阅读并同意<a href="/terms">用户协议</a>和<a href="/privacy">隐私政策</a></span>
</label>
</div>
<button type="submit" class="submit-btn">注册</button>
<p class="auth-link">
已有账号? <a href="/login">立即登录</a>
</p>
</form>
<!-- 登录表单 -->
<form id="login-form" class="auth-form">
<h2>登录</h2>
<div class="form-group">
<label for="login-account">账号</label>
<input type="text" id="login-account" name="account" required
placeholder="用户名/邮箱/手机号">
</div>
<div class="form-group">
<label for="login-password">密码</label>
<input type="password" id="login-password" name="password" required>
</div>
<div class="form-options">
<label class="checkbox-label">
<input type="checkbox" name="remember">
<span>记住我</span>
</label>
<a href="/forgot-password" class="forgot-link">忘记密码?</a>
</div>
<button type="submit" class="submit-btn">登录</button>
<p class="auth-link">
还没有账号? <a href="/register">立即注册</a>
</p>
</form>
</pre>
</div>
</div>
<h2>个人主页</h2>
<div class="user-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 个人主页 -->
<div class="user-profile">
<!-- 封面图 -->
<div class="profile-cover">
<img src="cover.jpg" alt="封面图">
<button class="edit-cover-btn">更换封面</button>
</div>
<!-- 用户信息 -->
<div class="profile-info">
<div class="avatar-section">
<img src="avatar.jpg" alt="头像" class="avatar">
<button class="edit-avatar-btn">更换头像</button>
</div>
<div class="user-details">
<h1 class="username">
用户名
<span class="verified-badge">✓</span>
</h1>
<p class="user-bio">个人简介...</p>
<div class="user-meta">
<span class="location">📍 北京</span>
<span class="website">🔗 example.com</span>
<span class="join-date">📅 2024年1月加入</span>
</div>
<div class="user-stats">
<div class="stat-item">
<strong>100</strong>
<span>关注</span>
</div>
<div class="stat-item">
<strong>1000</strong>
<span>粉丝</span>
</div>
<div class="stat-item">
<strong>500</strong>
<span>发布</span>
</div>
</div>
</div>
<div class="profile-actions">
<button class="edit-profile-btn">编辑资料</button>
<button class="follow-btn">关注</button>
<button class="message-btn">私信</button>
</div>
</div>
<!-- 内容标签 -->
<div class="profile-tabs">
<button class="tab-btn active" data-tab="posts">帖子</button>
<button class="tab-btn" data-tab="media">媒体</button>
<button class="tab-btn" data-tab="likes">喜欢</button>
</div>
<!-- 内容列表 -->
<div class="profile-content">
<!-- 帖子列表 -->
</div>
</div>
</pre>
</div>
</div>
<h2>关注系统</h2>
<div class="user-demo">
<h3>JavaScript实现</h3>
<div class="code-block">
<pre>
// 关注管理
class FollowManager {
constructor() {
this.init();
}
init() {
this.bindEvents();
}
// 关注用户
async followUser(userId) {
try {
const response = await fetch(`/api/users/${userId}/follow`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.updateFollowButton(userId, true);
this.updateFollowCount(userId, 1);
this.showNotification('关注成功');
} else {
this.showNotification(result.message, 'error');
}
} catch (error) {
console.error('关注失败:', error);
}
}
// 取消关注
async unfollowUser(userId) {
if (!confirm('确定要取消关注吗?')) return;
try {
const response = await fetch(`/api/users/${userId}/follow`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.updateFollowButton(userId, false);
this.updateFollowCount(userId, -1);
this.showNotification('已取消关注');
}
} catch (error) {
console.error('取消关注失败:', error);
}
}
// 更新关注按钮
updateFollowButton(userId, isFollowing) {
const btn = document.querySelector(`[data-user-id="${userId}"].follow-btn`);
if (btn) {
if (isFollowing) {
btn.textContent = '已关注';
btn.classList.add('following');
} else {
btn.textContent = '关注';
btn.classList.remove('following');
}
}
}
// 更新关注数
updateFollowCount(userId, delta) {
const countEl = document.querySelector(`[data-user-id="${userId}"].followers-count`);
if (countEl) {
const currentCount = parseInt(countEl.textContent);
countEl.textContent = currentCount + delta;
}
}
// 绑定事件
bindEvents() {
document.addEventListener('click', (e) => {
if (e.target.classList.contains('follow-btn')) {
const userId = e.target.dataset.userId;
if (e.target.classList.contains('following')) {
this.unfollowUser(userId);
} else {
this.followUser(userId);
}
}
});
}
}
// 初始化
new FollowManager();
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>用户系统是社交平台的基础。做好用户注册、登录、个人主页等功能,为后续社交互动打下良好基础。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>内容发布 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.post-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.post-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>内容发布</h1>
<h2>发布器</h2>
<div class="post-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 内容发布器 -->
<div class="post-composer">
<div class="composer-header">
<img src="avatar.jpg" alt="头像" class="avatar">
<div class="composer-input">
<textarea id="post-content"
placeholder="分享你的想法..."
maxlength="5000"></textarea>
<div class="char-count">
<span id="char-count">0</span>/5000
</div>
</div>
</div>
<!-- 已上传的媒体 -->
<div id="media-preview" class="media-preview">
<!-- 图片预览 -->
</div>
<!-- 工具栏 -->
<div class="composer-toolbar">
<div class="toolbar-left">
<button class="tool-btn" id="upload-image-btn" title="上传图片">
🖼️ 图片
</button>
<button class="tool-btn" id="upload-video-btn" title="上传视频">
🎬 视频
</button>
<button class="tool-btn" id="add-emoji-btn" title="添加表情">
😊 表情
</button>
<button class="tool-btn" id="add-topic-btn" title="添加话题">
# 话题
</button>
<button class="tool-btn" id="add-location-btn" title="添加位置">
📍 位置
</button>
</div>
<div class="toolbar-right">
<select id="visibility-select">
<option value="public">公开</option>
<option value="friends">好友可见</option>
<option value="private">仅自己可见</option>
</select>
<button class="submit-btn" id="submit-post-btn">发布</button>
</div>
</div>
<!-- 隐藏的文件输入 -->
<input type="file" id="image-input" accept="image/*" multiple hidden>
<input type="file" id="video-input" accept="video/*" hidden>
</div>
</pre>
</div>
</div>
<h2>内容展示</h2>
<div class="post-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 帖子卡片 -->
<div class="post-card">
<!-- 帖子头部 -->
<div class="post-header">
<img src="avatar.jpg" alt="头像" class="avatar">
<div class="post-author">
<a href="/user/123" class="username">用户名</a>
<span class="verified-badge">✓</span>
<p class="post-meta">
<span class="post-time">2小时前</span>
<span class="post-location">📍 北京</span>
</p>
</div>
<button class="more-btn">⋯</button>
</div>
<!-- 帖子内容 -->
<div class="post-content">
<p>这是帖子内容...</p>
<!-- 话题标签 -->
<a href="/topic/前端开发" class="topic-tag">#前端开发</a>
<!-- @提及 -->
<a href="/user/456" class="mention">@张三</a>
</div>
<!-- 媒体内容 -->
<div class="post-media">
<!-- 单图 -->
<img src="image.jpg" alt="图片" class="single-image">
<!-- 多图网格 -->
<div class="image-grid grid-2">
<img src="image1.jpg" alt="图片">
<img src="image2.jpg" alt="图片">
</div>
<!-- 视频 -->
<video controls poster="thumbnail.jpg">
<source src="video.mp4" type="video/mp4">
</video>
</div>
<!-- 帖子操作 -->
<div class="post-actions">
<button class="action-btn like-btn" data-post-id="123">
<span class="icon">👍</span>
<span class="count">100</span>
</button>
<button class="action-btn comment-btn" data-post-id="123">
<span class="icon">💬</span>
<span class="count">50</span>
</button>
<button class="action-btn share-btn" data-post-id="123">
<span class="icon">🔄</span>
<span class="count">20</span>
</button>
<button class="action-btn bookmark-btn" data-post-id="123">
<span class="icon">🔖</span>
</button>
</div>
<!-- 评论区 -->
<div class="post-comments">
<div class="comment-item">
<img src="avatar.jpg" alt="头像">
<div class="comment-content">
<a href="/user/456" class="username">李四</a>
<p>评论内容...</p>
<div class="comment-meta">
<span class="time">1小时前</span>
<button class="reply-btn">回复</button>
<button class="like-btn">赞</button>
</div>
</div>
</div>
<!-- 评论输入 -->
<div class="comment-input">
<input type="text" placeholder="发表评论...">
<button class="submit-btn">发送</button>
</div>
</div>
</div>
</pre>
</div>
</div>
<h2>内容交互</h2>
<div class="post-demo">
<h3>JavaScript实现</h3>
<div class="code-block">
<pre>
// 内容交互管理
class PostInteraction {
constructor() {
this.init();
}
init() {
this.bindEvents();
}
// 点赞
async toggleLike(postId) {
try {
const response = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.updateLikeButton(postId, result.data.liked, result.data.likes_count);
}
} catch (error) {
console.error('点赞失败:', error);
}
}
// 评论
async submitComment(postId, content) {
try {
const response = await fetch(`/api/posts/${postId}/comments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`
},
body: JSON.stringify({ content })
});
const result = await response.json();
if (result.success) {
this.addCommentToDOM(postId, result.data.comment);
}
} catch (error) {
console.error('评论失败:', error);
}
}
// 转发
async sharePost(postId) {
try {
const response = await fetch(`/api/posts/${postId}/share`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.showNotification('转发成功');
}
} catch (error) {
console.error('转发失败:', error);
}
}
// 更新点赞按钮
updateLikeButton(postId, liked, count) {
const btn = document.querySelector(`[data-post-id="${postId}"].like-btn`);
if (btn) {
const icon = btn.querySelector('.icon');
const countEl = btn.querySelector('.count');
if (liked) {
icon.textContent = '❤️';
btn.classList.add('liked');
} else {
icon.textContent = '👍';
btn.classList.remove('liked');
}
countEl.textContent = count;
}
}
// 添加评论到DOM
addCommentToDOM(postId, comment) {
const commentsContainer = document.querySelector(`[data-post-id="${postId}"] .post-comments`);
if (commentsContainer) {
const commentHTML = `
<div class="comment-item">
<img src="${comment.user.avatar}" alt="头像">
<div class="comment-content">
<a href="/user/${comment.user._id}" class="username">${comment.user.username}</a>
<p>${comment.content}</p>
<div class="comment-meta">
<span class="time">刚刚</span>
</div>
</div>
</div>
`;
commentsContainer.insertAdjacentHTML('afterbegin', commentHTML);
}
}
// 绑定事件
bindEvents() {
document.addEventListener('click', (e) => {
const postId = e.target.closest('[data-post-id]')?.dataset.postId;
if (e.target.closest('.like-btn')) {
this.toggleLike(postId);
} else if (e.target.closest('.share-btn')) {
this.sharePost(postId);
}
});
}
}
// 初始化
new PostInteraction();
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>内容发布是社交平台的核心。提供便捷的发布器,支持多种内容形式,让用户轻松分享生活点滴。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实时通讯 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.chat-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.chat-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>实时通讯</h1>
<h2>WebSocket连接</h2>
<div class="chat-demo">
<h3>客户端实现</h3>
<div class="code-block">
<pre>
// WebSocket管理
class WebSocketManager {
constructor() {
this.ws = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectDelay = 1000;
this.messageQueue = [];
this.listeners = {};
}
// 连接WebSocket
connect() {
const token = getToken();
const wsUrl = `wss://example.com/ws?token=${token}`;
this.ws = new WebSocket(wsUrl);
this.ws.onopen = () => {
console.log('WebSocket连接成功');
this.reconnectAttempts = 0;
this.flushMessageQueue();
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
this.ws.onerror = (error) => {
console.error('WebSocket错误:', error);
};
this.ws.onclose = () => {
console.log('WebSocket连接关闭');
this.reconnect();
};
}
// 重连
reconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
setTimeout(() => {
this.connect();
}, this.reconnectDelay * this.reconnectAttempts);
}
}
// 发送消息
send(message) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
} else {
this.messageQueue.push(message);
}
}
// 发送队列中的消息
flushMessageQueue() {
while (this.messageQueue.length > 0) {
const message = this.messageQueue.shift();
this.send(message);
}
}
// 处理消息
handleMessage(message) {
const { type, data } = message;
if (this.listeners[type]) {
this.listeners[type].forEach(callback => callback(data));
}
}
// 监听消息
on(type, callback) {
if (!this.listeners[type]) {
this.listeners[type] = [];
}
this.listeners[type].push(callback);
}
// 取消监听
off(type, callback) {
if (this.listeners[type]) {
this.listeners[type] = this.listeners[type].filter(cb => cb !== callback);
}
}
// 关闭连接
close() {
if (this.ws) {
this.ws.close();
}
}
}
// 初始化
const wsManager = new WebSocketManager();
wsManager.connect();
</pre>
</div>
</div>
<h2>聊天界面</h2>
<div class="chat-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 聊天窗口 -->
<div class="chat-window">
<!-- 聊天头部 -->
<div class="chat-header">
<img src="avatar.jpg" alt="头像">
<div class="chat-info">
<h3>用户名</h3>
<span class="online-status">在线</span>
</div>
<button class="close-btn">✕</button>
</div>
<!-- 消息列表 -->
<div class="message-list" id="message-list">
<!-- 时间分隔 -->
<div class="time-divider">
<span>今天 14:30</span>
</div>
<!-- 对方消息 -->
<div class="message-item received">
<img src="avatar.jpg" alt="头像">
<div class="message-content">
<p>你好!</p>
<span class="message-time">14:30</span>
</div>
</div>
<!-- 自己的消息 -->
<div class="message-item sent">
<div class="message-content">
<p>你好!</p>
<span class="message-time">14:31</span>
<span class="message-status">已读</span>
</div>
</div>
</div>
<!-- 输入区域 -->
<div class="chat-input">
<button class="emoji-btn">😊</button>
<button class="image-btn">🖼️</button>
<input type="text" id="message-input" placeholder="输入消息...">
<button class="send-btn" id="send-btn">发送</button>
</div>
</div>
</pre>
</div>
</div>
<h2>消息处理</h2>
<div class="chat-demo">
<h3>JavaScript实现</h3>
<div class="code-block">
<pre>
// 聊天管理
class ChatManager {
constructor(conversationId) {
this.conversationId = conversationId;
this.init();
}
init() {
this.bindEvents();
this.setupWebSocket();
}
// 设置WebSocket监听
setupWebSocket() {
wsManager.on('new_message', (message) => {
if (message.conversation_id === this.conversationId) {
this.addMessageToDOM(message);
this.markAsRead(message._id);
}
});
wsManager.on('message_read', (data) => {
this.updateMessageStatus(data.message_id, '已读');
});
}
// 发送消息
sendMessage(content) {
const message = {
type: 'send_message',
data: {
conversation_id: this.conversationId,
content: content,
type: 'text'
}
};
wsManager.send(message);
// 添加到DOM
this.addMessageToDOM({
_id: Date.now(),
content: content,
sender_id: 'me',
created_at: new Date()
});
}
// 添加消息到DOM
addMessageToDOM(message) {
const messageList = document.getElementById('message-list');
const isSent = message.sender_id === 'me';
const messageHTML = `
<div class="message-item ${isSent ? 'sent' : 'received'}">
${!isSent ? `<img src="${message.sender.avatar}" alt="头像">` : ''}
<div class="message-content">
<p>${message.content}</p>
<span class="message-time">${this.formatTime(message.created_at)}</span>
${isSent ? '<span class="message-status">已发送</span>' : ''}
</div>
</div>
`;
messageList.insertAdjacentHTML('beforeend', messageHTML);
this.scrollToBottom();
}
// 标记已读
markAsRead(messageId) {
wsManager.send({
type: 'mark_read',
data: {
message_id: messageId
}
});
}
// 更新消息状态
updateMessageStatus(messageId, status) {
const messageEl = document.querySelector(`[data-message-id="${messageId}"] .message-status`);
if (messageEl) {
messageEl.textContent = status;
}
}
// 滚动到底部
scrollToBottom() {
const messageList = document.getElementById('message-list');
messageList.scrollTop = messageList.scrollHeight;
}
// 格式化时间
formatTime(date) {
return new Date(date).toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
}
// 绑定事件
bindEvents() {
const input = document.getElementById('message-input');
const sendBtn = document.getElementById('send-btn');
sendBtn.addEventListener('click', () => {
const content = input.value.trim();
if (content) {
this.sendMessage(content);
input.value = '';
}
});
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendBtn.click();
}
});
}
}
</pre>
</div>
</div>
<h2>消息通知</h2>
<div class="chat-demo">
<h3>通知推送</h3>
<div class="code-block">
<pre>
// 通知管理
class NotificationManager {
constructor() {
this.init();
}
init() {
this.requestPermission();
this.setupWebSocket();
}
// 请求通知权限
async requestPermission() {
if ('Notification' in window) {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
console.log('通知权限已授权');
}
}
}
// 设置WebSocket监听
setupWebSocket() {
wsManager.on('new_message', (message) => {
this.showNotification('新消息', {
body: message.content,
icon: message.sender.avatar,
tag: message.conversation_id
});
});
wsManager.on('new_comment', (comment) => {
this.showNotification('新评论', {
body: comment.content,
icon: comment.user.avatar
});
});
wsManager.on('new_like', (like) => {
this.showNotification('新点赞', {
body: `${like.user.username} 赞了你的帖子`
});
});
}
// 显示通知
showNotification(title, options = {}) {
if (Notification.permission === 'granted') {
const notification = new Notification(title, {
icon: options.icon || '/favicon.ico',
body: options.body,
tag: options.tag,
requireInteraction: false
});
notification.onclick = () => {
window.focus();
notification.close();
if (options.url) {
window.location.href = options.url;
}
};
// 自动关闭
setTimeout(() => {
notification.close();
}, 5000);
}
}
}
// 初始化
new NotificationManager();
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>实时通讯是社交平台的重要功能。使用WebSocket实现实时消息推送,提供流畅的聊天体验,增强用户粘性。
</div>
</div>
</body>
</html>
东巴文(db-w.cn) 提醒:社交平台是最复杂的Web应用之一。从简单开始,逐步完善功能,特别关注性能和实时性。记住,好的社交平台应该让连接变得简单,让交流变得自然。