当前位置: 首页 > news >正文

JAVA国际版图文短视频交友系统源码支持H5 + APP

JAVA国际版图文短视频交友系统:全栈式社交解决方案(支持H5 + APP)

在全球化数字社交浪潮的推动下,JAVA国际版图文短视频交友系统正成为社交娱乐行业数字化转型的核心技术架构。根据艾瑞咨询数据显示,2023年全球短视频社交市场规模突破3000亿美元,用户日均使用时长达到98分钟。这套图文短视频交友系统源码通过全媒体内容形态和智能化社交匹配,有效解决了传统社交平台存在的互动形式单一、内容生产力不足、用户粘性低等结构性痛点。

从技术经济学角度分析,该系统采用SpringBoot+MyBatisPlus+MySQL的微服务分布式架构,实现了海量多媒体内容的高效存储和实时分发。基于Uniapp框架构建的跨平台客户端,使社交平台能够以统一的代码基座快速覆盖H5、APP等移动端入口,极大提升了用户获取效率和产品迭代速度。管理后台采用Vue+ElementUI技术栈,为运营管理者提供了全方位的用户行为分析和内容监管能力。

行业前景方面,随着5G技术的普及和元宇宙概念的兴起,社交娱乐行业正朝着沉浸化、个性化、全球化方向发展。麦肯锡研究报告指出,具备短视频和智能推荐功能的社交平台用户留存率提升45%,日均活跃用户(DAU)增长60%。这套JAVA国际版图文短视频交友系统不仅实现了社交互动模式的创新重构,更通过深度学习算法和实时计算引擎为用户提供了精准的内容推荐和社交匹配,将成为下一代社交产品差异化竞争的技术基石。

系统技术架构深度解析 分布式社交服务架构设计

本系统采用基于SpringBoot的微服务架构,结合MyBatisPlusMySQL构建高可用的社交服务集群。以下是核心业务架构代码示例:

// 短视频内容实体类
@Entity
@Table(name = "short_video")
public class ShortVideo {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "user_id", nullable = false)private Long userId; // 发布用户ID@Column(name = "video_url", nullable = false)private String videoUrl; // 视频文件地址@Column(name = "cover_url")private String coverUrl; // 封面图地址@Column(name = "video_description")private String videoDescription; // 视频描述@Column(name = "video_duration")private Integer videoDuration; // 视频时长(秒)@Column(name = "video_size")private Long videoSize; // 视频文件大小@Column(name = "video_resolution")private String videoResolution; // 视频分辨率@Column(name = "content_type")private Integer contentType; // 内容类型:1-短视频 2-图文@Column(name = "like_count")private Integer likeCount = 0; // 点赞数@Column(name = "comment_count")private Integer commentCount = 0; // 评论数@Column(name = "share_count")private Integer shareCount = 0; // 分享数@Column(name = "view_count")private Integer viewCount = 0; // 播放次数@Column(name = "topic_tags")private String topicTags; // 话题标签@Column(name = "location")private String location; // 发布位置@Column(name = "visibility")private Integer visibility = 1; // 可见性:1-公开 2-私密@Column(name = "audit_status")private Integer auditStatus = 1; // 审核状态@Column(name = "create_time")private LocalDateTime createTime;
}// 用户社交关系实体
@Entity
@Table(name = "user_relationship")
public class UserRelationship {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "from_user_id")private Long fromUserId; // 关注者ID@Column(name = "to_user_id")private Long toUserId; // 被关注者ID@Column(name = "relationship_type")private Integer relationshipType; // 关系类型:1-关注 2-好友@Column(name = "relationship_status")private Integer relationshipStatus; // 关系状态@Column(name = "create_time")private LocalDateTime createTime;
}// 智能推荐服务
@Service
public class ContentRecommendationService {@Autowiredprivate ShortVideoMapper shortVideoMapper;@Autowiredprivate UserBehaviorMapper userBehaviorMapper;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 基于用户兴趣的智能内容推荐*/public List<ShortVideo> recommendVideos(Long userId, Integer page, Integer size) {// 1. 获取用户兴趣标签Set<String> userInterests = getUserInterests(userId);// 2. 获取用户行为数据List<UserBehavior> userBehaviors = getUserRecentBehaviors(userId);// 3. 多策略内容召回List<ShortVideo> candidates = new ArrayList<>();// 基于兴趣标签召回candidates.addAll(recallByInterests(userInterests, page, size));// 基于协同过滤召回candidates.addAll(recallByCollaborativeFiltering(userId, page, size));// 基于热度召回candidates.addAll(recallByHotness(page, size));// 4. 多维度排序return candidates.stream().distinct().map(video -> {RecommendationScore score = calculateVideoScore(video, userId, userInterests, userBehaviors);return new VideoRecommendation(video, score);}).sorted(Comparator.comparing(VideoRecommendation::getScore).reversed()).limit(size).map(VideoRecommendation::getVideo).collect(Collectors.toList());}/*** 计算视频推荐分数*/private RecommendationScore calculateVideoScore(ShortVideo video, Long userId, Set<String> userInterests, List<UserBehavior> userBehaviors) {RecommendationScore score = new RecommendationScore();// 内容匹配度(35%权重)score.setContentMatchScore(calculateContentMatchScore(video, userInterests));// 用户相似度(25%权重)score.setUserSimilarityScore(calculateUserSimilarityScore(video.getUserId(), userId));// 实时热度(20%权重)score.setHotnessScore(calculateHotnessScore(video));// 新鲜度(15%权重)score.setFreshnessScore(calculateFreshnessScore(video.getCreateTime()));// 多样性(5%权重)score.setDiversityScore(calculateDiversityScore(video, userBehaviors));return score;}/*** 基于兴趣标签的内容匹配*/private double calculateContentMatchScore(ShortVideo video, Set<String> userInterests) {if (userInterests.isEmpty()) return 50.0;Set<String> videoTags = parseTags(video.getTopicTags());long matchedCount = userInterests.stream().filter(videoTags::contains).count();return (double) matchedCount / userInterests.size() * 100;}/*** 计算用户相似度*/private double calculateUserSimilarityScore(Long videoUserId, Long currentUserId) {// 基于用户行为计算相似度List<Long> commonFollows = findCommonFollows(videoUserId, currentUserId);List<Long> commonLikes = findCommonLikes(videoUserId, currentUserId);double followSimilarity = calculateJaccardSimilarity(getFollowSet(videoUserId), getFollowSet(currentUserId));double likeSimilarity = calculateJaccardSimilarity(getLikeSet(videoUserId), getLikeSet(currentUserId));return followSimilarity * 0.6 + likeSimilarity * 0.4;}
}// 推荐评分模型
@Data
class RecommendationScore {private double contentMatchScore;    // 内容匹配度private double userSimilarityScore;  // 用户相似度private double hotnessScore;         // 实时热度private double freshnessScore;       // 新鲜度private double diversityScore;       // 多样性public double getScore() {return contentMatchScore * 0.35 + userSimilarityScore * 0.25 + hotnessScore * 0.2 + freshnessScore * 0.15 + diversityScore * 0.05;}
}
实时消息通信系统
// WebSocket消息处理器
@Component
@ServerEndpoint("/chat/websocket/{userId}")
public class ChatWebSocketHandler {private static final Map<Long, Session> userSessions = new ConcurrentHashMap<>();@OnOpenpublic void onOpen(Session session, @PathParam("userId") Long userId) {userSessions.put(userId, session);sendOnlineStatus(userId, true);}@OnClosepublic void onClose(@PathParam("userId") Long userId) {userSessions.remove(userId);sendOnlineStatus(userId, false);}@OnMessagepublic void onMessage(String message, Session session) {ChatMessage chatMessage = JSON.parseObject(message, ChatMessage.class);processChatMessage(chatMessage);}/*** 发送私聊消息*/public void sendPrivateMessage(ChatMessage message) {Session receiverSession = userSessions.get(message.getReceiverId());if (receiverSession != null && receiverSession.isOpen()) {try {receiverSession.getBasicRemote().sendText(JSON.toJSONString(message));// 更新消息状态为已送达updateMessageStatus(message.getId(), 2);} catch (IOException e) {// 处理发送失败}} else {// 用户离线,推送手机通知pushMobileNotification(message);}}/*** 发送系统通知*/public void sendSystemNotification(SystemNotification notification) {Session userSession = userSessions.get(notification.getUserId());if (userSession != null && userSession.isOpen()) {try {userSession.getBasicRemote().sendText(JSON.toJSONString(notification));} catch (IOException e) {// 处理发送失败}}}
}// 聊天消息服务
@Service
@Transactional
public class ChatService {@Autowiredprivate ChatMessageMapper chatMessageMapper;@Autowiredprivate ChatWebSocketHandler webSocketHandler;/*** 发送聊天消息*/public ChatMessage sendMessage(MessageSendDTO sendDTO) {// 1. 创建消息记录ChatMessage message = new ChatMessage();BeanUtils.copyProperties(sendDTO, message);message.setMessageStatus(1); // 已发送message.setSendTime(LocalDateTime.now());chatMessageMapper.insert(message);// 2. 实时推送webSocketHandler.sendPrivateMessage(message);// 3. 更新会话时间updateConversation(sendDTO.getSenderId(), sendDTO.getReceiverId());return message;}/*** 获取聊天记录*/public List<ChatMessage> getChatHistory(Long user1, Long user2, Integer page, Integer size) {LambdaQueryWrapper<ChatMessage> query = new LambdaQueryWrapper<>();query.and(wrapper -> wrapper.eq(ChatMessage::getSenderId, user1).eq(ChatMessage::getReceiverId, user2).or().eq(ChatMessage::getSenderId, user2).eq(ChatMessage::getReceiverId, user1)).orderByDesc(ChatMessage::getSendTime).last("LIMIT " + (page * size) + "," + size);return chatMessageMapper.selectList(query);}
}
用户端Uniapp实现

用户端采用Uniapp开发,支持H5和APP。以下是核心社交功能页面实现:

<template><view class="social-app-container"><!-- 顶部导航 --><view class="header-nav"><view class="nav-item" :class="{active: currentTab === 0}" @tap="switchTab(0)"><text class="nav-text">推荐</text></view><view class="nav-item" :class="{active: currentTab === 1}" @tap="switchTab(1)"><text class="nav-text">关注</text></view><view class="nav-item" :class="{active: currentTab === 2}" @tap="switchTab(2)"><text class="nav-text">消息</text><view class="message-badge" v-if="unreadCount > 0">{{ unreadCount }}</view></view><view class="nav-item" :class="{active: currentTab === 3}" @tap="switchTab(3)"><text class="nav-text">我的</text></view></view><!-- 推荐内容流 --><view class="content-feed" v-if="currentTab === 0"><view v-for="item in videoList" :key="item.id" class="video-card"><!-- 视频播放器 --><view class="video-player-section"><video :src="item.videoUrl" :poster="item.coverUrl" class="video-player" autoplay loop@play="onVideoPlay(item)" @pause="onVideoPause(item)"></video><!-- 互动操作栏 --><view class="interaction-bar"><view class="interaction-item" @tap="likeVideo(item)"><image :src="item.isLiked ? '/static/like-active.png' : '/static/like.png'" class="interaction-icon"></image><text class="interaction-count">{{ item.likeCount }}</text></view><view class="interaction-item" @tap="showCommentPanel(item)"><image src="/static/comment.png" class="interaction-icon"></image><text class="interaction-count">{{ item.commentCount }}</text></view><view class="interaction-item" @tap="shareVideo(item)"><image src="/static/share.png" class="interaction-icon"></image><text class="interaction-count">{{ item.shareCount }}</text></view><view class="interaction-item" @tap="followUser(item.userId)"><image :src="item.isFollowing ? '/static/following.png' : '/static/follow.png'" class="interaction-icon"></image></view></view></view><!-- 视频信息 --><view class="video-info-section"><view class="user-info"><image :src="item.userAvatar" class="user-avatar" @tap="viewUserProfile(item.userId)"></image><view class="user-details"><text class="username">@{{ item.username }}</text><text class="video-desc">{{ item.videoDescription }}</text><view class="video-tags"><text v-for="tag in item.topicTags" :key="tag" class="tag-item" @tap="searchByTag(tag)">#{{ tag }}</text></view></view></view><view class="video-meta"><text class="location" v-if="item.location"><image src="/static/location.png" class="meta-icon"></image>{{ item.location }}</text><text class="create-time">{{ formatTime(item.createTime) }}</text></view></view></view><!-- 加载更多 --><view class="load-more" v-if="hasMore" @tap="loadMoreVideos"><text class="load-more-text">加载更多内容</text></view></view><!-- 消息页面 --><view class="message-page" v-if="currentTab === 2"><view class="conversation-list"><view v-for="conversation in conversations" :key="conversation.id" class="conversation-item" @tap="openChat(conversation)"><image :src="conversation.avatar" class="conversation-avatar"></image><view class="conversation-info"><view class="conversation-header"><text class="conversation-name">{{ conversation.username }}</text><text class="last-time">{{ formatTime(conversation.lastMessageTime) }}</text></view><text class="last-message">{{ conversation.lastMessage }}</text></view><view class="unread-badge" v-if="conversation.unreadCount > 0">{{ conversation.unreadCount }}</view></view></view></view><!-- 发布按钮 --><view class="publish-fab" @tap="showPublishModal"><image src="/static/publish.png" class="publish-icon"></image></view><!-- 发布内容模态框 --><uni-popup ref="publishPopup" type="bottom"><view class="publish-modal"><view class="modal-header"><text class="modal-title">发布内容</text><text class="close-btn" @tap="closePublishModal">×</text></view><view class="publish-content"><!-- 内容类型选择 --><view class="content-type-selector"><view class="type-item" :class="{active: publishData.contentType === 1}" @tap="publishData.contentType = 1"><image src="/static/video.png" class="type-icon"></image><text>短视频</text></view><view class="type-item" :class="{active: publishData.contentType === 2}" @tap="publishData.contentType = 2"><image src="/static/image.png" class="type-icon"></image><text>图文</text></view></view><!-- 媒体上传 --><view class="media-upload-section"><view v-if="publishData.contentType === 1" class="video-upload"><video v-if="publishData.videoUrl" :src="publishData.videoUrl" class="preview-video" controls></video><view v-else class="upload-placeholder" @tap="chooseVideo"><image src="/static/upload-video.png" class="upload-icon"></image><text class="upload-text">选择视频</text></view></view><view v-else class="image-upload"><view class="image-grid"><view v-for="(image, index) in publishData.images" :key="index" class="image-item"><image :src="image" class="uploaded-image" mode="aspectFill"></image><text class="remove-image" @tap="removeImage(index)">×</text></view><view v-if="publishData.images.length < 9" class="add-image" @tap="chooseImage"><image src="/static/add-image.png" class="add-icon"></image></view></view></view></view><!-- 内容描述 --><view class="content-description"><textarea class="description-input" v-model="publishData.description" placeholder="添加描述..." maxlength="500"></textarea><text class="word-count">{{ publishData.description.length }}/500</text></view><!-- 话题标签 --><view class="topic-tags"><text class="section-title">添加话题</text><view class="tag-input-section"><input class="tag-input" v-model="newTag" placeholder="输入话题标签" @confirm="addTag" /><button class="add-tag-btn" @tap="addTag">添加</button></view><view class="tag-list"><text v-for="tag in publishData.tags" :key="tag" class="tag-item">#{{ tag }} <text class="remove-tag" @tap="removeTag(tag)">×</text></text></view></view><!-- 发布设置 --><view class="publish-settings"><view class="setting-item"><text class="setting-label">可见性</text><picker @change="onVisibilityChange" :value="publishData.visibility" :range="visibilityOptions"><view class="picker">{{ visibilityOptions[publishData.visibility] }}</view></picker></view><view class="setting-item"><text class="setting-label">定位</text><switch :checked="publishData.enableLocation" @change="onLocationToggle" /><text class="location-text" v-if="publishData.enableLocation">{{ currentLocation }}</text></view></view></view><button class="publish-btn" @tap="publishContent" :disabled="!canPublish">发布</button></view></uni-popup><!-- 评论面板 --><uni-popup ref="commentPopup" type="bottom"><view class="comment-panel"><view class="panel-header"><text class="panel-title">评论</text><text class="close-panel" @tap="closeCommentPanel">关闭</text></view><scroll-view class="comment-list" scroll-y><view v-for="comment in currentComments" :key="comment.id" class="comment-item"><image :src="comment.userAvatar" class="comment-avatar"></image><view class="comment-content"><text class="comment-username">{{ comment.username }}</text><text class="comment-text">{{ comment.content }}</text><view class="comment-meta"><text class="comment-time">{{ formatTime(comment.createTime) }}</text><view class="comment-actions"><text class="comment-action" @tap="likeComment(comment)">点赞({{ comment.likeCount }})</text><text class="comment-action" @tap="replyComment(comment)">回复</text></view></view></view></view></scroll-view><view class="comment-input-section"><input class="comment-input" v-model="newComment" placeholder="写下你的评论..." /><button class="send-comment-btn" @tap="sendComment">发送</button></view></view></uni-popup></view>
</template><script>
export default {data() {return {currentTab: 0,videoList: [],conversations: [],unreadCount: 0,hasMore: true,pageNum: 1,pageSize: 10,// 发布相关数据publishData: {contentType: 1,videoUrl: '',images: [],description: '',tags: [],visibility: 0,enableLocation: false},newTag: '',visibilityOptions: ['公开', '私密', '好友可见'],// 评论相关数据currentVideo: null,currentComments: [],newComment: '',currentLocation: ''}},computed: {canPublish() {if (this.publishData.contentType === 1) {return this.publishData.videoUrl && this.publishData.description.trim();} else {return this.publishData.images.length > 0 && this.publishData.description.trim();}}},onLoad() {this.loadVideoFeed()this.loadConversations()this.getCurrentLocation()},onPullDownRefresh() {this.refreshVideoFeed()},onReachBottom() {this.loadMoreVideos()},methods: {// 加载视频推荐流async loadVideoFeed() {try {const params = {pageNum: this.pageNum,pageSize: this.pageSize}const res = await this.$http.get('/api/video/feed', { params })if (res.code === 200) {if (this.pageNum === 1) {this.videoList = res.data.list} else {this.videoList = [...this.videoList, ...res.data.list]}this.hasMore = res.data.hasMore}} catch (error) {uni.showToast({title: '加载失败',icon: 'none'})}},// 点赞视频async likeVideo(video) {try {const res = await this.$http.post('/api/video/like', {videoId: video.id,action: !video.isLiked})if (res.code === 200) {video.isLiked = !video.isLikedvideo.likeCount += video.isLiked ? 1 : -1}} catch (error) {uni.showToast({title: '操作失败',icon: 'none'})}},// 关注用户async followUser(userId) {try {const user = this.videoList.find(v => v.userId === userId)const res = await this.$http.post('/api/user/follow', {toUserId: userId,action: !user.isFollowing})if (res.code === 200) {user.isFollowing = !user.isFollowinguni.showToast({title: user.isFollowing ? '关注成功' : '已取消关注',icon: 'success'})}} catch (error) {uni.showToast({title: '操作失败',icon: 'none'})}},// 发布内容async publishContent() {try {const formData = new FormData()formData.append('contentType', this.publishData.contentType)formData.append('description', this.publishData.description)formData.append('tags', JSON.stringify(this.publishData.tags))formData.append('visibility', this.publishData.visibility)if (this.publishData.contentType === 1) {formData.append('video', this.publishData.videoUrl)} else {this.publishData.images.forEach((image, index) => {formData.append('images', image)})}if (this.publishData.enableLocation) {formData.append('location', this.currentLocation)}const res = await this.$http.post('/api/content/publish', formData, {header: {'Content-Type': 'multipart/form-data'}})if (res.code === 200) {uni.showToast({title: '发布成功',icon: 'success'})this.closePublishModal()this.refreshVideoFeed()}} catch (error) {uni.showToast({title: '发布失败',icon: 'none'})}},// 选择视频async chooseVideo() {try {const res = await uni.chooseVideo({sourceType: ['album', 'camera'],maxDuration: 60,camera: 'back'})this.publishData.videoUrl = res.tempFilePath} catch (error) {uni.showToast({title: '选择视频失败',icon: 'none'})}},// 选择图片async chooseImage() {try {const res = await uni.chooseImage({count: 9 - this.publishData.images.length,sizeType: ['compressed'],sourceType: ['album', 'camera']})this.publishData.images = [...this.publishData.images, ...res.tempFilePaths]} catch (error) {uni.showToast({title: '选择图片失败',icon: 'none'})}},// 显示评论面板async showCommentPanel(video) {this.currentVideo = videotry {const res = await this.$http.get(`/api/comment/list/${video.id}`)if (res.code === 200) {this.currentComments = res.datathis.$refs.commentPopup.open()}} catch (error) {uni.showToast({title: '加载评论失败',icon: 'none'})}},// 发送评论async sendComment() {if (!this.newComment.trim()) returntry {const res = await this.$http.post('/api/comment/add', {videoId: this.currentVideo.id,content: this.newComment})if (res.code === 200) {this.currentComments.unshift(res.data)this.currentVideo.commentCount++this.newComment = ''}} catch (error) {uni.showToast({title: '评论失败',icon: 'none'})}},// 切换标签页switchTab(index) {this.currentTab = index},// 显示发布模态框showPublishModal() {this.$refs.publishPopup.open()},// 关闭发布模态框closePublishModal() {this.$refs.publishPopup.close()this.resetPublishData()},// 重置发布数据resetPublishData() {this.publishData = {contentType: 1,videoUrl: '',images: [],description: '',tags: [],visibility: 0,enableLocation: false}},// 添加标签addTag() {if (this.newTag.trim() && !this.publishData.tags.includes(this.newTag.trim())) {this.publishData.tags.push(this.newTag.trim())this.newTag = ''}},// 移除标签removeTag(tag) {this.publishData.tags = this.publishData.tags.filter(t => t !== tag)},// 移除图片removeImage(index) {this.publishData.images.splice(index, 1)},// 刷新视频流async refreshVideoFeed() {this.pageNum = 1await this.loadVideoFeed()uni.stopPullDownRefresh()},// 加载更多视频async loadMoreVideos() {if (!this.hasMore) returnthis.pageNum++await this.loadVideoFeed()}}
}
</script><style scoped>
.social-app-container {background: #000;min-height: 100vh;color: white;
}.header-nav {display: flex;background: rgba(0, 0, 0, 0.9);position: fixed;top: 0;left: 0;right: 0;z-index: 1000;padding: 20rpx 0;
}.nav-item {flex: 1;text-align: center;position: relative;padding: 20rpx 0;
}.nav-item.active {color: #ff2d55;
}.message-badge {position: absolute;top: 10rpx;right: 40rpx;background: #ff2d55;color: white;border-radius: 50%;width: 36rpx;height: 36rpx;font-size: 20rpx;display: flex;align-items: center;justify-content: center;
}.content-feed {margin-top: 80rpx;
}.video-card {position: relative;margin-bottom: 20rpx;
}.video-player {width: 100%;height: 100vh;
}.interaction-bar {position: absolute;right: 30rpx;bottom: 150rpx;display: flex;flex-direction: column;align-items: center;
}.interaction-item {display: flex;flex-direction: column;align-items: center;margin-bottom: 40rpx;
}.interaction-icon {width: 60rpx;height: 60rpx;margin-bottom: 10rpx;
}.interaction-count {font-size: 24rpx;color: white;
}.video-info-section {position: absolute;bottom: 0;left: 0;right: 0;background: linear-gradient(transparent, rgba(0,0,0,0.8));padding: 40rpx 30rpx;
}.user-info {display: flex;align-items: flex-start;margin-bottom: 20rpx;
}.user-avatar {width: 80rpx;height: 80rpx;border-radius: 50%;margin-right: 20rpx;
}.publish-fab {position: fixed;right: 40rpx;bottom: 120rpx;width: 120rpx;height: 120rpx;background: linear-gradient(45deg, #ff2d55, #ff6b9c);border-radius: 50%;display: flex;align-items: center;justify-content: center;box-shadow: 0 8rpx 40rpx rgba(255, 45, 85, 0.3);
}.publish-modal {background: white;border-top-left-radius: 30rpx;border-top-right-radius: 30rpx;max-height: 80vh;overflow-y: auto;
}.modal-header {display: flex;justify-content: space-between;align-items: center;padding: 40rpx;border-bottom: 1rpx solid #eee;
}.publish-content {padding: 40rpx;
}.content-type-selector {display: flex;margin-bottom: 40rpx;
}.type-item {flex: 1;display: flex;flex-direction: column;align-items: center;padding: 30rpx;border: 2rpx solid #eee;border-radius: 16rpx;margin: 0 10rpx;
}.type-item.active {border-color: #ff2d55;background: #fff0f5;
}.media-upload-section {margin-bottom: 40rpx;
}.upload-placeholder {border: 2rpx dashed #ccc;border-radius: 16rpx;padding: 100rpx;text-align: center;
}.image-grid {display: grid;grid-template-columns: repeat(3, 1fr);gap: 20rpx;
}.publish-btn {background: #ff2d55;color: white;border-radius: 50rpx;padding: 25rpx;margin: 40rpx;
}.publish-btn:disabled {background: #ccc;
}
</style>
管理后台Vue+ElementUI实现

管理后台采用Vue+ElementUI构建,提供完善的运营管理功能:

<template><div class="social-admin-container"><!-- 数据概览 --><el-row :gutter="20" class="stats-row"><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.totalUsers }}</div><div class="stats-label">总用户数</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.totalVideos }}</div><div class="stats-label">视频总数</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.dailyActiveUsers }}</div><div class="stats-label">日活用户</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.avgWatchTime }}</div><div class="stats-label">平均观看时长(分钟)</div></div></el-card></el-col></el-row><!-- 内容管理 --><el-card class="table-card"><template #header><div class="card-header"><span>内容管理</span><el-button type="primary" @click="exportContent">导出数据</el-button></div></template><!-- 筛选条件 --><el-form :model="queryParams" inline><el-form-item label="内容类型"><el-select v-model="queryParams.contentType" placeholder="请选择类型"><el-option label="全部" value=""></el-option><el-option label="短视频" value="1"></el-option><el-option label="图文" value="2"></el-option></el-select></el-form-item><el-form-item label="审核状态"><el-select v-model="queryParams.auditStatus" placeholder="请选择状态"><el-option label="全部" value=""></el-option><el-option label="待审核" value="1"></el-option><el-option label="审核通过" value="2"></el-option><el-option label="审核拒绝" value="3"></el-option></el-select></el-form-item><el-form-item label="发布时间"><el-date-pickerv-model="queryParams.dateRange"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"></el-date-picker></el-form-item><el-form-item><el-button type="primary" @click="handleSearch">搜索</el-button><el-button @click="handleReset">重置</el-button></el-form-item></el-form><!-- 内容表格 --><el-table :data="contentList" v-loading="loading"><el-table-column prop="id" label="ID" width="80" /><el-table-column label="内容预览" width="120"><template #default="scope"><video v-if="scope.row.contentType === 1" :src="scope.row.videoUrl" class="content-preview" controls></video><image v-else :src="scope.row.coverUrl" class="content-preview"></image></template></el-table-column><el-table-column prop="username" label="发布用户" width="120" /><el-table-column prop="videoDescription" label="内容描述" width="200" show-overflow-tooltip /><el-table-column prop="contentType" label="内容类型" width="100"><template #default="scope">{{ scope.row.contentType === 1 ? '短视频' : '图文' }}</template></el-table-column><el-table-column prop="likeCount" label="点赞数" width="100" /><el-table-column prop="commentCount" label="评论数" width="100" /><el-table-column prop="viewCount" label="播放量" width="100" /><el-table-column prop="auditStatus" label="审核状态" width="120"><template #default="scope"><el-tag :type="getAuditStatusTagType(scope.row.auditStatus)">{{ getAuditStatusText(scope.row.auditStatus) }}</el-tag></template></el-table-column><el-table-column prop="createTime" label="发布时间" width="180" /><el-table-column label="操作" width="200" fixed="right"><template #default="scope"><el-button size="small" @click="viewContentDetail(scope.row)">详情</el-button><el-button v-if="scope.row.auditStatus === 1" size="small" type="success"@click="approveContent(scope.row)">通过</el-button><el-button v-if="scope.row.auditStatus === 1" size="small" type="danger"@click="rejectContent(scope.row)">拒绝</el-button></template></el-table-column></el-table><!-- 分页 --><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pagination.current":page-sizes="[10, 20, 50]":page-size="pagination.size"layout="total, sizes, prev, pager, next, jumper":total="pagination.total"></el-pagination></el-card><!-- 用户管理 --><el-card class="user-management-card"><template #header><span>用户管理</span></template><el-table :data="userList" v-loading="userLoading"><el-table-column prop="id" label="ID" width="80" /><el-table-column prop="username" label="用户名" width="120" /><el-table-column prop="phone" label="手机号" width="130" /><el-table-column prop="followerCount" label="粉丝数" width="100" /><el-table-column prop="followingCount" label="关注数" width="100" /><el-table-column prop="videoCount" label="作品数" width="100" /><el-table-column prop="likeCount" label="获赞数" width="100" /><el-table-column prop="userStatus" label="用户状态" width="100"><template #default="scope"><el-tag :type="scope.row.userStatus === 1 ? 'success' : 'danger'">{{ scope.row.userStatus === 1 ? '正常' : '封禁' }}</el-tag></template></el-table-column><el-table-column prop="createTime" label="注册时间" width="180" /><el-table-column label="操作" width="150"><template #default="scope"><el-button size="small" @click="viewUserDetail(scope.row)">详情</el-button><el-button size="small" :type="scope.row.userStatus === 1 ? 'warning' : 'success'"@click="toggleUserStatus(scope.row)">{{ scope.row.userStatus === 1 ? '封禁' : '解封' }}</el-button></template></el-table-column></el-table></el-card></div>
</template><script>
import { getContents, getDashboardStats, approveContent, rejectContent, getUsers, toggleUserStatus } from '@/api/social'export default {name: 'SocialAdmin',data() {return {stats: {totalUsers: 0,totalVideos: 0,dailyActiveUsers: 0,avgWatchTime: 0},contentList: [],userList: [],loading: false,userLoading: false,queryParams: {contentType: '',auditStatus: '',dateRange: []},pagination: {current: 1,size: 10,total: 0}}},mounted() {this.loadDashboardData()this.loadContentList()this.loadUserList()},methods: {async loadDashboardData() {try {const res = await getDashboardStats()if (res.code === 200) {this.stats = res.data}} catch (error) {this.$message.error('加载数据失败')}},async loadContentList() {this.loading = truetry {const params = {...this.queryParams,page: this.pagination.current,size: this.pagination.size}const res = await getContents(params)if (res.code === 200) {this.contentList = res.data.recordsthis.pagination.total = res.data.total}} catch (error) {this.$message.error('加载内容列表失败')} finally {this.loading = false}},async loadUserList() {this.userLoading = truetry {const res = await getUsers()if (res.code === 200) {this.userList = res.data}} catch (error) {this.$message.error('加载用户列表失败')} finally {this.userLoading = false}},getAuditStatusTagType(status) {const map = {1: 'warning',  // 待审核2: 'success',  // 审核通过3: 'danger'    // 审核拒绝}return map[status] || 'info'},getAuditStatusText(status) {const map = {1: '待审核',2: '审核通过',3: '审核拒绝'}return map[status] || '未知'},// 审核通过内容async approveContent(content) {try {const res = await approveContent(content.id)if (res.code === 200) {this.$message.success('审核通过')this.loadContentList()}} catch (error) {this.$message.error('操作失败')}},// 审核拒绝内容async rejectContent(content) {try {const res = await rejectContent(content.id)if (res.code === 200) {this.$message.success('已拒绝')this.loadContentList()}} catch (error) {this.$message.error('操作失败')}},// 切换用户状态async toggleUserStatus(user) {try {const res = await toggleUserStatus(user.id, user.userStatus === 1 ? 0 : 1)if (res.code === 200) {this.$message.success('操作成功')this.loadUserList()}} catch (error) {this.$message.error('操作失败')}},handleSearch() {this.pagination.current = 1this.loadContentList()},handleReset() {this.queryParams = {contentType: '',auditStatus: '',dateRange: []}this.handleSearch()},handleSizeChange(size) {this.pagination.size = sizethis.loadContentList()},handleCurrentChange(current) {this.pagination.current = currentthis.loadContentList()},viewContentDetail(content) {this.$router.push(`/content/detail/${content.id}`)},viewUserDetail(user) {this.$router.push(`/user/detail/${user.id}`)}}
}
</script><style scoped>
.social-admin-container {padding: 20px;background: #f5f7fa;
}.stats-card {text-align: center;
}.stats-number {font-size: 32px;font-weight: bold;color: #1890ff;margin-bottom: 8px;
}.stats-label {color: #666;font-size: 14px;
}.table-card {margin-top: 20px;
}.card-header {display: flex;justify-content: space-between;align-items: center;
}.user-management-card {margin-top: 20px;
}.content-preview {width: 100px;height: 80px;border-radius: 8px;object-fit: cover;
}
</style>
数据库设计核心表结构
-- 用户信息表
CREATE TABLE `user_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '用户名',`phone` varchar(20) DEFAULT NULL COMMENT '手机号',`email` varchar(100) DEFAULT NULL COMMENT '邮箱',`password` varchar(255) NOT NULL COMMENT '密码',`avatar` varchar(500) DEFAULT NULL COMMENT '头像',`bio` varchar(200) DEFAULT NULL COMMENT '个人简介',`gender` tinyint(1) DEFAULT NULL COMMENT '性别',`birthday` date DEFAULT NULL COMMENT '生日',`location` varchar(100) DEFAULT NULL COMMENT '位置',`follower_count` int(11) DEFAULT '0' COMMENT '粉丝数',`following_count` int(11) DEFAULT '0' COMMENT '关注数',`video_count` int(11) DEFAULT '0' COMMENT '作品数',`like_count` int(11) DEFAULT '0' COMMENT '获赞数',`user_status` tinyint(1) DEFAULT '1' COMMENT '用户状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `uk_username` (`username`),UNIQUE KEY `uk_phone` (`phone`),KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';-- 短视频内容表
CREATE TABLE `short_video` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) NOT NULL COMMENT '发布用户ID',`video_url` varchar(500) NOT NULL COMMENT '视频文件地址',`cover_url` varchar(500) DEFAULT NULL COMMENT '封面图地址',`video_description` varchar(1000) DEFAULT NULL COMMENT '视频描述',`video_duration` int(11) NOT NULL COMMENT '视频时长',`video_size` bigint(20) NOT NULL COMMENT '视频文件大小',`video_resolution` varchar(20) DEFAULT NULL COMMENT '视频分辨率',`content_type` tinyint(1) NOT NULL COMMENT '内容类型',`like_count` int(11) DEFAULT '0' COMMENT '点赞数',`comment_count` int(11) DEFAULT '0' COMMENT '评论数',`share_count` int(11) DEFAULT '0' COMMENT '分享数',`view_count` int(11) DEFAULT '0' COMMENT '播放次数',`topic_tags` json DEFAULT NULL COMMENT '话题标签',`location` varchar(100) DEFAULT NULL COMMENT '发布位置',`visibility` tinyint(1) DEFAULT '1' COMMENT '可见性',`audit_status` tinyint(1) DEFAULT '1' COMMENT '审核状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`),KEY `idx_audit_status` (`audit_status`),KEY `idx_create_time` (`create_time`),KEY `idx_like_count` (`like_count`),FULLTEXT KEY `ft_description` (`video_description`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短视频内容表';-- 用户关系表
CREATE TABLE `user_relationship` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`from_user_id` bigint(20) NOT NULL COMMENT '关注者ID',`to_user_id` bigint(20) NOT NULL COMMENT '被关注者ID',`relationship_type` tinyint(1) NOT NULL COMMENT '关系类型',`relationship_status` tinyint(1) DEFAULT '1' COMMENT '关系状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `uk_follow` (`from_user_id`, `to_user_id`),KEY `idx_from_user` (`from_user_id`),KEY `idx_to_user` (`to_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户关系表';-- 聊天消息表
CREATE TABLE `chat_message` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`sender_id` bigint(20) NOT NULL COMMENT '发送者ID',`receiver_id` bigint(20) NOT NULL COMMENT '接收者ID',`message_type` tinyint(1) NOT NULL COMMENT '消息类型',`content` text NOT NULL COMMENT '消息内容',`image_url` varchar(500) DEFAULT NULL COMMENT '图片地址',`video_url` varchar(500) DEFAULT NULL COMMENT '视频地址',`message_status` tinyint(1) DEFAULT '1' COMMENT '消息状态',`send_time` datetime DEFAULT CURRENT_TIMESTAMP,`read_time` datetime DEFAULT NULL COMMENT '阅读时间',PRIMARY KEY (`id`),KEY `idx_sender` (`sender_id`),KEY `idx_receiver` (`receiver_id`),KEY `idx_send_time` (`send_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天消息表';

这套基于JAVA国际版图文短视频交友系统的完整解决方案,通过现代化的微服务架构和实时多媒体处理技术,为全球社交娱乐行业提供了全方位的数字化转型升级路径。系统采用SpringBoot+MyBatisPlus+MySQL构建高可用分布式服务集群,使用Uniapp框架实现H5、APP多端统一的用户界面,配合Vue+ElementUI的管理后台,形成了完整的技术生态闭环。

从技术实现角度看,该系统创新性地引入了智能推荐算法、实时消息通信、多媒体内容处理等先进技术理念,确保了社交平台在高并发场景下的性能稳定和用户体验流畅。对于社交平台运营商而言,这套系统不仅实现了社交功能的全面覆盖,更重要的是通过数据分析和机器学习为用户提供了个性化的内容推荐和精准的社交匹配。

随着5G技术的普及和全球数字化社交需求的持续增长,图文短视频社交正在成为新一代的主流社交方式。这套JAVA国际版图文短视频交友系统源码以其先进的技术架构、完善的功能设计和良好的国际化支持,将成为社交创业者和企业在全球市场竞争中赢得用户青睐的重要技术支撑。未来,随着人工智能、虚拟现实等新技术的深度融合,该系统还将持续演进,为全球社交娱乐行业创新发展提供更强大的技术动力。

JAVA国际版图文短视频交友系统:全栈式社交解决方案(支持H5 + APP)

在全球化数字社交浪潮的推动下,JAVA国际版图文短视频交友系统正成为社交娱乐行业数字化转型的核心技术架构。根据艾瑞咨询数据显示,2023年全球短视频社交市场规模突破3000亿美元,用户日均使用时长达到98分钟。这套图文短视频交友系统源码通过全媒体内容形态和智能化社交匹配,有效解决了传统社交平台存在的互动形式单一、内容生产力不足、用户粘性低等结构性痛点。

从技术经济学角度分析,该系统采用SpringBoot+MyBatisPlus+MySQL的微服务分布式架构,实现了海量多媒体内容的高效存储和实时分发。基于Uniapp框架构建的跨平台客户端,使社交平台能够以统一的代码基座快速覆盖H5、APP等移动端入口,极大提升了用户获取效率和产品迭代速度。管理后台采用Vue+ElementUI技术栈,为运营管理者提供了全方位的用户行为分析和内容监管能力。

行业前景方面,随着5G技术的普及和元宇宙概念的兴起,社交娱乐行业正朝着沉浸化、个性化、全球化方向发展。麦肯锡研究报告指出,具备短视频和智能推荐功能的社交平台用户留存率提升45%,日均活跃用户(DAU)增长60%。这套JAVA国际版图文短视频交友系统不仅实现了社交互动模式的创新重构,更通过深度学习算法和实时计算引擎为用户提供了精准的内容推荐和社交匹配,将成为下一代社交产品差异化竞争的技术基石。

系统技术架构深度解析 分布式社交服务架构设计

本系统采用基于SpringBoot的微服务架构,结合MyBatisPlusMySQL构建高可用的社交服务集群。以下是核心业务架构代码示例:

// 短视频内容实体类
@Entity
@Table(name = "short_video")
public class ShortVideo {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "user_id", nullable = false)private Long userId; // 发布用户ID@Column(name = "video_url", nullable = false)private String videoUrl; // 视频文件地址@Column(name = "cover_url")private String coverUrl; // 封面图地址@Column(name = "video_description")private String videoDescription; // 视频描述@Column(name = "video_duration")private Integer videoDuration; // 视频时长(秒)@Column(name = "video_size")private Long videoSize; // 视频文件大小@Column(name = "video_resolution")private String videoResolution; // 视频分辨率@Column(name = "content_type")private Integer contentType; // 内容类型:1-短视频 2-图文@Column(name = "like_count")private Integer likeCount = 0; // 点赞数@Column(name = "comment_count")private Integer commentCount = 0; // 评论数@Column(name = "share_count")private Integer shareCount = 0; // 分享数@Column(name = "view_count")private Integer viewCount = 0; // 播放次数@Column(name = "topic_tags")private String topicTags; // 话题标签@Column(name = "location")private String location; // 发布位置@Column(name = "visibility")private Integer visibility = 1; // 可见性:1-公开 2-私密@Column(name = "audit_status")private Integer auditStatus = 1; // 审核状态@Column(name = "create_time")private LocalDateTime createTime;
}// 用户社交关系实体
@Entity
@Table(name = "user_relationship")
public class UserRelationship {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "from_user_id")private Long fromUserId; // 关注者ID@Column(name = "to_user_id")private Long toUserId; // 被关注者ID@Column(name = "relationship_type")private Integer relationshipType; // 关系类型:1-关注 2-好友@Column(name = "relationship_status")private Integer relationshipStatus; // 关系状态@Column(name = "create_time")private LocalDateTime createTime;
}// 智能推荐服务
@Service
public class ContentRecommendationService {@Autowiredprivate ShortVideoMapper shortVideoMapper;@Autowiredprivate UserBehaviorMapper userBehaviorMapper;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 基于用户兴趣的智能内容推荐*/public List<ShortVideo> recommendVideos(Long userId, Integer page, Integer size) {// 1. 获取用户兴趣标签Set<String> userInterests = getUserInterests(userId);// 2. 获取用户行为数据List<UserBehavior> userBehaviors = getUserRecentBehaviors(userId);// 3. 多策略内容召回List<ShortVideo> candidates = new ArrayList<>();// 基于兴趣标签召回candidates.addAll(recallByInterests(userInterests, page, size));// 基于协同过滤召回candidates.addAll(recallByCollaborativeFiltering(userId, page, size));// 基于热度召回candidates.addAll(recallByHotness(page, size));// 4. 多维度排序return candidates.stream().distinct().map(video -> {RecommendationScore score = calculateVideoScore(video, userId, userInterests, userBehaviors);return new VideoRecommendation(video, score);}).sorted(Comparator.comparing(VideoRecommendation::getScore).reversed()).limit(size).map(VideoRecommendation::getVideo).collect(Collectors.toList());}/*** 计算视频推荐分数*/private RecommendationScore calculateVideoScore(ShortVideo video, Long userId, Set<String> userInterests, List<UserBehavior> userBehaviors) {RecommendationScore score = new RecommendationScore();// 内容匹配度(35%权重)score.setContentMatchScore(calculateContentMatchScore(video, userInterests));// 用户相似度(25%权重)score.setUserSimilarityScore(calculateUserSimilarityScore(video.getUserId(), userId));// 实时热度(20%权重)score.setHotnessScore(calculateHotnessScore(video));// 新鲜度(15%权重)score.setFreshnessScore(calculateFreshnessScore(video.getCreateTime()));// 多样性(5%权重)score.setDiversityScore(calculateDiversityScore(video, userBehaviors));return score;}/*** 基于兴趣标签的内容匹配*/private double calculateContentMatchScore(ShortVideo video, Set<String> userInterests) {if (userInterests.isEmpty()) return 50.0;Set<String> videoTags = parseTags(video.getTopicTags());long matchedCount = userInterests.stream().filter(videoTags::contains).count();return (double) matchedCount / userInterests.size() * 100;}/*** 计算用户相似度*/private double calculateUserSimilarityScore(Long videoUserId, Long currentUserId) {// 基于用户行为计算相似度List<Long> commonFollows = findCommonFollows(videoUserId, currentUserId);List<Long> commonLikes = findCommonLikes(videoUserId, currentUserId);double followSimilarity = calculateJaccardSimilarity(getFollowSet(videoUserId), getFollowSet(currentUserId));double likeSimilarity = calculateJaccardSimilarity(getLikeSet(videoUserId), getLikeSet(currentUserId));return followSimilarity * 0.6 + likeSimilarity * 0.4;}
}// 推荐评分模型
@Data
class RecommendationScore {private double contentMatchScore;    // 内容匹配度private double userSimilarityScore;  // 用户相似度private double hotnessScore;         // 实时热度private double freshnessScore;       // 新鲜度private double diversityScore;       // 多样性public double getScore() {return contentMatchScore * 0.35 + userSimilarityScore * 0.25 + hotnessScore * 0.2 + freshnessScore * 0.15 + diversityScore * 0.05;}
}
实时消息通信系统
// WebSocket消息处理器
@Component
@ServerEndpoint("/chat/websocket/{userId}")
public class ChatWebSocketHandler {private static final Map<Long, Session> userSessions = new ConcurrentHashMap<>();@OnOpenpublic void onOpen(Session session, @PathParam("userId") Long userId) {userSessions.put(userId, session);sendOnlineStatus(userId, true);}@OnClosepublic void onClose(@PathParam("userId") Long userId) {userSessions.remove(userId);sendOnlineStatus(userId, false);}@OnMessagepublic void onMessage(String message, Session session) {ChatMessage chatMessage = JSON.parseObject(message, ChatMessage.class);processChatMessage(chatMessage);}/*** 发送私聊消息*/public void sendPrivateMessage(ChatMessage message) {Session receiverSession = userSessions.get(message.getReceiverId());if (receiverSession != null && receiverSession.isOpen()) {try {receiverSession.getBasicRemote().sendText(JSON.toJSONString(message));// 更新消息状态为已送达updateMessageStatus(message.getId(), 2);} catch (IOException e) {// 处理发送失败}} else {// 用户离线,推送手机通知pushMobileNotification(message);}}/*** 发送系统通知*/public void sendSystemNotification(SystemNotification notification) {Session userSession = userSessions.get(notification.getUserId());if (userSession != null && userSession.isOpen()) {try {userSession.getBasicRemote().sendText(JSON.toJSONString(notification));} catch (IOException e) {// 处理发送失败}}}
}// 聊天消息服务
@Service
@Transactional
public class ChatService {@Autowiredprivate ChatMessageMapper chatMessageMapper;@Autowiredprivate ChatWebSocketHandler webSocketHandler;/*** 发送聊天消息*/public ChatMessage sendMessage(MessageSendDTO sendDTO) {// 1. 创建消息记录ChatMessage message = new ChatMessage();BeanUtils.copyProperties(sendDTO, message);message.setMessageStatus(1); // 已发送message.setSendTime(LocalDateTime.now());chatMessageMapper.insert(message);// 2. 实时推送webSocketHandler.sendPrivateMessage(message);// 3. 更新会话时间updateConversation(sendDTO.getSenderId(), sendDTO.getReceiverId());return message;}/*** 获取聊天记录*/public List<ChatMessage> getChatHistory(Long user1, Long user2, Integer page, Integer size) {LambdaQueryWrapper<ChatMessage> query = new LambdaQueryWrapper<>();query.and(wrapper -> wrapper.eq(ChatMessage::getSenderId, user1).eq(ChatMessage::getReceiverId, user2).or().eq(ChatMessage::getSenderId, user2).eq(ChatMessage::getReceiverId, user1)).orderByDesc(ChatMessage::getSendTime).last("LIMIT " + (page * size) + "," + size);return chatMessageMapper.selectList(query);}
}
用户端Uniapp实现

用户端采用Uniapp开发,支持H5和APP。以下是核心社交功能页面实现:

<template><view class="social-app-container"><!-- 顶部导航 --><view class="header-nav"><view class="nav-item" :class="{active: currentTab === 0}" @tap="switchTab(0)"><text class="nav-text">推荐</text></view><view class="nav-item" :class="{active: currentTab === 1}" @tap="switchTab(1)"><text class="nav-text">关注</text></view><view class="nav-item" :class="{active: currentTab === 2}" @tap="switchTab(2)"><text class="nav-text">消息</text><view class="message-badge" v-if="unreadCount > 0">{{ unreadCount }}</view></view><view class="nav-item" :class="{active: currentTab === 3}" @tap="switchTab(3)"><text class="nav-text">我的</text></view></view><!-- 推荐内容流 --><view class="content-feed" v-if="currentTab === 0"><view v-for="item in videoList" :key="item.id" class="video-card"><!-- 视频播放器 --><view class="video-player-section"><video :src="item.videoUrl" :poster="item.coverUrl" class="video-player" autoplay loop@play="onVideoPlay(item)" @pause="onVideoPause(item)"></video><!-- 互动操作栏 --><view class="interaction-bar"><view class="interaction-item" @tap="likeVideo(item)"><image :src="item.isLiked ? '/static/like-active.png' : '/static/like.png'" class="interaction-icon"></image><text class="interaction-count">{{ item.likeCount }}</text></view><view class="interaction-item" @tap="showCommentPanel(item)"><image src="/static/comment.png" class="interaction-icon"></image><text class="interaction-count">{{ item.commentCount }}</text></view><view class="interaction-item" @tap="shareVideo(item)"><image src="/static/share.png" class="interaction-icon"></image><text class="interaction-count">{{ item.shareCount }}</text></view><view class="interaction-item" @tap="followUser(item.userId)"><image :src="item.isFollowing ? '/static/following.png' : '/static/follow.png'" class="interaction-icon"></image></view></view></view><!-- 视频信息 --><view class="video-info-section"><view class="user-info"><image :src="item.userAvatar" class="user-avatar" @tap="viewUserProfile(item.userId)"></image><view class="user-details"><text class="username">@{{ item.username }}</text><text class="video-desc">{{ item.videoDescription }}</text><view class="video-tags"><text v-for="tag in item.topicTags" :key="tag" class="tag-item" @tap="searchByTag(tag)">#{{ tag }}</text></view></view></view><view class="video-meta"><text class="location" v-if="item.location"><image src="/static/location.png" class="meta-icon"></image>{{ item.location }}</text><text class="create-time">{{ formatTime(item.createTime) }}</text></view></view></view><!-- 加载更多 --><view class="load-more" v-if="hasMore" @tap="loadMoreVideos"><text class="load-more-text">加载更多内容</text></view></view><!-- 消息页面 --><view class="message-page" v-if="currentTab === 2"><view class="conversation-list"><view v-for="conversation in conversations" :key="conversation.id" class="conversation-item" @tap="openChat(conversation)"><image :src="conversation.avatar" class="conversation-avatar"></image><view class="conversation-info"><view class="conversation-header"><text class="conversation-name">{{ conversation.username }}</text><text class="last-time">{{ formatTime(conversation.lastMessageTime) }}</text></view><text class="last-message">{{ conversation.lastMessage }}</text></view><view class="unread-badge" v-if="conversation.unreadCount > 0">{{ conversation.unreadCount }}</view></view></view></view><!-- 发布按钮 --><view class="publish-fab" @tap="showPublishModal"><image src="/static/publish.png" class="publish-icon"></image></view><!-- 发布内容模态框 --><uni-popup ref="publishPopup" type="bottom"><view class="publish-modal"><view class="modal-header"><text class="modal-title">发布内容</text><text class="close-btn" @tap="closePublishModal">×</text></view><view class="publish-content"><!-- 内容类型选择 --><view class="content-type-selector"><view class="type-item" :class="{active: publishData.contentType === 1}" @tap="publishData.contentType = 1"><image src="/static/video.png" class="type-icon"></image><text>短视频</text></view><view class="type-item" :class="{active: publishData.contentType === 2}" @tap="publishData.contentType = 2"><image src="/static/image.png" class="type-icon"></image><text>图文</text></view></view><!-- 媒体上传 --><view class="media-upload-section"><view v-if="publishData.contentType === 1" class="video-upload"><video v-if="publishData.videoUrl" :src="publishData.videoUrl" class="preview-video" controls></video><view v-else class="upload-placeholder" @tap="chooseVideo"><image src="/static/upload-video.png" class="upload-icon"></image><text class="upload-text">选择视频</text></view></view><view v-else class="image-upload"><view class="image-grid"><view v-for="(image, index) in publishData.images" :key="index" class="image-item"><image :src="image" class="uploaded-image" mode="aspectFill"></image><text class="remove-image" @tap="removeImage(index)">×</text></view><view v-if="publishData.images.length < 9" class="add-image" @tap="chooseImage"><image src="/static/add-image.png" class="add-icon"></image></view></view></view></view><!-- 内容描述 --><view class="content-description"><textarea class="description-input" v-model="publishData.description" placeholder="添加描述..." maxlength="500"></textarea><text class="word-count">{{ publishData.description.length }}/500</text></view><!-- 话题标签 --><view class="topic-tags"><text class="section-title">添加话题</text><view class="tag-input-section"><input class="tag-input" v-model="newTag" placeholder="输入话题标签" @confirm="addTag" /><button class="add-tag-btn" @tap="addTag">添加</button></view><view class="tag-list"><text v-for="tag in publishData.tags" :key="tag" class="tag-item">#{{ tag }} <text class="remove-tag" @tap="removeTag(tag)">×</text></text></view></view><!-- 发布设置 --><view class="publish-settings"><view class="setting-item"><text class="setting-label">可见性</text><picker @change="onVisibilityChange" :value="publishData.visibility" :range="visibilityOptions"><view class="picker">{{ visibilityOptions[publishData.visibility] }}</view></picker></view><view class="setting-item"><text class="setting-label">定位</text><switch :checked="publishData.enableLocation" @change="onLocationToggle" /><text class="location-text" v-if="publishData.enableLocation">{{ currentLocation }}</text></view></view></view><button class="publish-btn" @tap="publishContent" :disabled="!canPublish">发布</button></view></uni-popup><!-- 评论面板 --><uni-popup ref="commentPopup" type="bottom"><view class="comment-panel"><view class="panel-header"><text class="panel-title">评论</text><text class="close-panel" @tap="closeCommentPanel">关闭</text></view><scroll-view class="comment-list" scroll-y><view v-for="comment in currentComments" :key="comment.id" class="comment-item"><image :src="comment.userAvatar" class="comment-avatar"></image><view class="comment-content"><text class="comment-username">{{ comment.username }}</text><text class="comment-text">{{ comment.content }}</text><view class="comment-meta"><text class="comment-time">{{ formatTime(comment.createTime) }}</text><view class="comment-actions"><text class="comment-action" @tap="likeComment(comment)">点赞({{ comment.likeCount }})</text><text class="comment-action" @tap="replyComment(comment)">回复</text></view></view></view></view></scroll-view><view class="comment-input-section"><input class="comment-input" v-model="newComment" placeholder="写下你的评论..." /><button class="send-comment-btn" @tap="sendComment">发送</button></view></view></uni-popup></view>
</template><script>
export default {data() {return {currentTab: 0,videoList: [],conversations: [],unreadCount: 0,hasMore: true,pageNum: 1,pageSize: 10,// 发布相关数据publishData: {contentType: 1,videoUrl: '',images: [],description: '',tags: [],visibility: 0,enableLocation: false},newTag: '',visibilityOptions: ['公开', '私密', '好友可见'],// 评论相关数据currentVideo: null,currentComments: [],newComment: '',currentLocation: ''}},computed: {canPublish() {if (this.publishData.contentType === 1) {return this.publishData.videoUrl && this.publishData.description.trim();} else {return this.publishData.images.length > 0 && this.publishData.description.trim();}}},onLoad() {this.loadVideoFeed()this.loadConversations()this.getCurrentLocation()},onPullDownRefresh() {this.refreshVideoFeed()},onReachBottom() {this.loadMoreVideos()},methods: {// 加载视频推荐流async loadVideoFeed() {try {const params = {pageNum: this.pageNum,pageSize: this.pageSize}const res = await this.$http.get('/api/video/feed', { params })if (res.code === 200) {if (this.pageNum === 1) {this.videoList = res.data.list} else {this.videoList = [...this.videoList, ...res.data.list]}this.hasMore = res.data.hasMore}} catch (error) {uni.showToast({title: '加载失败',icon: 'none'})}},// 点赞视频async likeVideo(video) {try {const res = await this.$http.post('/api/video/like', {videoId: video.id,action: !video.isLiked})if (res.code === 200) {video.isLiked = !video.isLikedvideo.likeCount += video.isLiked ? 1 : -1}} catch (error) {uni.showToast({title: '操作失败',icon: 'none'})}},// 关注用户async followUser(userId) {try {const user = this.videoList.find(v => v.userId === userId)const res = await this.$http.post('/api/user/follow', {toUserId: userId,action: !user.isFollowing})if (res.code === 200) {user.isFollowing = !user.isFollowinguni.showToast({title: user.isFollowing ? '关注成功' : '已取消关注',icon: 'success'})}} catch (error) {uni.showToast({title: '操作失败',icon: 'none'})}},// 发布内容async publishContent() {try {const formData = new FormData()formData.append('contentType', this.publishData.contentType)formData.append('description', this.publishData.description)formData.append('tags', JSON.stringify(this.publishData.tags))formData.append('visibility', this.publishData.visibility)if (this.publishData.contentType === 1) {formData.append('video', this.publishData.videoUrl)} else {this.publishData.images.forEach((image, index) => {formData.append('images', image)})}if (this.publishData.enableLocation) {formData.append('location', this.currentLocation)}const res = await this.$http.post('/api/content/publish', formData, {header: {'Content-Type': 'multipart/form-data'}})if (res.code === 200) {uni.showToast({title: '发布成功',icon: 'success'})this.closePublishModal()this.refreshVideoFeed()}} catch (error) {uni.showToast({title: '发布失败',icon: 'none'})}},// 选择视频async chooseVideo() {try {const res = await uni.chooseVideo({sourceType: ['album', 'camera'],maxDuration: 60,camera: 'back'})this.publishData.videoUrl = res.tempFilePath} catch (error) {uni.showToast({title: '选择视频失败',icon: 'none'})}},// 选择图片async chooseImage() {try {const res = await uni.chooseImage({count: 9 - this.publishData.images.length,sizeType: ['compressed'],sourceType: ['album', 'camera']})this.publishData.images = [...this.publishData.images, ...res.tempFilePaths]} catch (error) {uni.showToast({title: '选择图片失败',icon: 'none'})}},// 显示评论面板async showCommentPanel(video) {this.currentVideo = videotry {const res = await this.$http.get(`/api/comment/list/${video.id}`)if (res.code === 200) {this.currentComments = res.datathis.$refs.commentPopup.open()}} catch (error) {uni.showToast({title: '加载评论失败',icon: 'none'})}},// 发送评论async sendComment() {if (!this.newComment.trim()) returntry {const res = await this.$http.post('/api/comment/add', {videoId: this.currentVideo.id,content: this.newComment})if (res.code === 200) {this.currentComments.unshift(res.data)this.currentVideo.commentCount++this.newComment = ''}} catch (error) {uni.showToast({title: '评论失败',icon: 'none'})}},// 切换标签页switchTab(index) {this.currentTab = index},// 显示发布模态框showPublishModal() {this.$refs.publishPopup.open()},// 关闭发布模态框closePublishModal() {this.$refs.publishPopup.close()this.resetPublishData()},// 重置发布数据resetPublishData() {this.publishData = {contentType: 1,videoUrl: '',images: [],description: '',tags: [],visibility: 0,enableLocation: false}},// 添加标签addTag() {if (this.newTag.trim() && !this.publishData.tags.includes(this.newTag.trim())) {this.publishData.tags.push(this.newTag.trim())this.newTag = ''}},// 移除标签removeTag(tag) {this.publishData.tags = this.publishData.tags.filter(t => t !== tag)},// 移除图片removeImage(index) {this.publishData.images.splice(index, 1)},// 刷新视频流async refreshVideoFeed() {this.pageNum = 1await this.loadVideoFeed()uni.stopPullDownRefresh()},// 加载更多视频async loadMoreVideos() {if (!this.hasMore) returnthis.pageNum++await this.loadVideoFeed()}}
}
</script><style scoped>
.social-app-container {background: #000;min-height: 100vh;color: white;
}.header-nav {display: flex;background: rgba(0, 0, 0, 0.9);position: fixed;top: 0;left: 0;right: 0;z-index: 1000;padding: 20rpx 0;
}.nav-item {flex: 1;text-align: center;position: relative;padding: 20rpx 0;
}.nav-item.active {color: #ff2d55;
}.message-badge {position: absolute;top: 10rpx;right: 40rpx;background: #ff2d55;color: white;border-radius: 50%;width: 36rpx;height: 36rpx;font-size: 20rpx;display: flex;align-items: center;justify-content: center;
}.content-feed {margin-top: 80rpx;
}.video-card {position: relative;margin-bottom: 20rpx;
}.video-player {width: 100%;height: 100vh;
}.interaction-bar {position: absolute;right: 30rpx;bottom: 150rpx;display: flex;flex-direction: column;align-items: center;
}.interaction-item {display: flex;flex-direction: column;align-items: center;margin-bottom: 40rpx;
}.interaction-icon {width: 60rpx;height: 60rpx;margin-bottom: 10rpx;
}.interaction-count {font-size: 24rpx;color: white;
}.video-info-section {position: absolute;bottom: 0;left: 0;right: 0;background: linear-gradient(transparent, rgba(0,0,0,0.8));padding: 40rpx 30rpx;
}.user-info {display: flex;align-items: flex-start;margin-bottom: 20rpx;
}.user-avatar {width: 80rpx;height: 80rpx;border-radius: 50%;margin-right: 20rpx;
}.publish-fab {position: fixed;right: 40rpx;bottom: 120rpx;width: 120rpx;height: 120rpx;background: linear-gradient(45deg, #ff2d55, #ff6b9c);border-radius: 50%;display: flex;align-items: center;justify-content: center;box-shadow: 0 8rpx 40rpx rgba(255, 45, 85, 0.3);
}.publish-modal {background: white;border-top-left-radius: 30rpx;border-top-right-radius: 30rpx;max-height: 80vh;overflow-y: auto;
}.modal-header {display: flex;justify-content: space-between;align-items: center;padding: 40rpx;border-bottom: 1rpx solid #eee;
}.publish-content {padding: 40rpx;
}.content-type-selector {display: flex;margin-bottom: 40rpx;
}.type-item {flex: 1;display: flex;flex-direction: column;align-items: center;padding: 30rpx;border: 2rpx solid #eee;border-radius: 16rpx;margin: 0 10rpx;
}.type-item.active {border-color: #ff2d55;background: #fff0f5;
}.media-upload-section {margin-bottom: 40rpx;
}.upload-placeholder {border: 2rpx dashed #ccc;border-radius: 16rpx;padding: 100rpx;text-align: center;
}.image-grid {display: grid;grid-template-columns: repeat(3, 1fr);gap: 20rpx;
}.publish-btn {background: #ff2d55;color: white;border-radius: 50rpx;padding: 25rpx;margin: 40rpx;
}.publish-btn:disabled {background: #ccc;
}
</style>
管理后台Vue+ElementUI实现

管理后台采用Vue+ElementUI构建,提供完善的运营管理功能:

<template><div class="social-admin-container"><!-- 数据概览 --><el-row :gutter="20" class="stats-row"><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.totalUsers }}</div><div class="stats-label">总用户数</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.totalVideos }}</div><div class="stats-label">视频总数</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.dailyActiveUsers }}</div><div class="stats-label">日活用户</div></div></el-card></el-col><el-col :span="6"><el-card class="stats-card"><div class="stats-content"><div class="stats-number">{{ stats.avgWatchTime }}</div><div class="stats-label">平均观看时长(分钟)</div></div></el-card></el-col></el-row><!-- 内容管理 --><el-card class="table-card"><template #header><div class="card-header"><span>内容管理</span><el-button type="primary" @click="exportContent">导出数据</el-button></div></template><!-- 筛选条件 --><el-form :model="queryParams" inline><el-form-item label="内容类型"><el-select v-model="queryParams.contentType" placeholder="请选择类型"><el-option label="全部" value=""></el-option><el-option label="短视频" value="1"></el-option><el-option label="图文" value="2"></el-option></el-select></el-form-item><el-form-item label="审核状态"><el-select v-model="queryParams.auditStatus" placeholder="请选择状态"><el-option label="全部" value=""></el-option><el-option label="待审核" value="1"></el-option><el-option label="审核通过" value="2"></el-option><el-option label="审核拒绝" value="3"></el-option></el-select></el-form-item><el-form-item label="发布时间"><el-date-pickerv-model="queryParams.dateRange"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"></el-date-picker></el-form-item><el-form-item><el-button type="primary" @click="handleSearch">搜索</el-button><el-button @click="handleReset">重置</el-button></el-form-item></el-form><!-- 内容表格 --><el-table :data="contentList" v-loading="loading"><el-table-column prop="id" label="ID" width="80" /><el-table-column label="内容预览" width="120"><template #default="scope"><video v-if="scope.row.contentType === 1" :src="scope.row.videoUrl" class="content-preview" controls></video><image v-else :src="scope.row.coverUrl" class="content-preview"></image></template></el-table-column><el-table-column prop="username" label="发布用户" width="120" /><el-table-column prop="videoDescription" label="内容描述" width="200" show-overflow-tooltip /><el-table-column prop="contentType" label="内容类型" width="100"><template #default="scope">{{ scope.row.contentType === 1 ? '短视频' : '图文' }}</template></el-table-column><el-table-column prop="likeCount" label="点赞数" width="100" /><el-table-column prop="commentCount" label="评论数" width="100" /><el-table-column prop="viewCount" label="播放量" width="100" /><el-table-column prop="auditStatus" label="审核状态" width="120"><template #default="scope"><el-tag :type="getAuditStatusTagType(scope.row.auditStatus)">{{ getAuditStatusText(scope.row.auditStatus) }}</el-tag></template></el-table-column><el-table-column prop="createTime" label="发布时间" width="180" /><el-table-column label="操作" width="200" fixed="right"><template #default="scope"><el-button size="small" @click="viewContentDetail(scope.row)">详情</el-button><el-button v-if="scope.row.auditStatus === 1" size="small" type="success"@click="approveContent(scope.row)">通过</el-button><el-button v-if="scope.row.auditStatus === 1" size="small" type="danger"@click="rejectContent(scope.row)">拒绝</el-button></template></el-table-column></el-table><!-- 分页 --><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pagination.current":page-sizes="[10, 20, 50]":page-size="pagination.size"layout="total, sizes, prev, pager, next, jumper":total="pagination.total"></el-pagination></el-card><!-- 用户管理 --><el-card class="user-management-card"><template #header><span>用户管理</span></template><el-table :data="userList" v-loading="userLoading"><el-table-column prop="id" label="ID" width="80" /><el-table-column prop="username" label="用户名" width="120" /><el-table-column prop="phone" label="手机号" width="130" /><el-table-column prop="followerCount" label="粉丝数" width="100" /><el-table-column prop="followingCount" label="关注数" width="100" /><el-table-column prop="videoCount" label="作品数" width="100" /><el-table-column prop="likeCount" label="获赞数" width="100" /><el-table-column prop="userStatus" label="用户状态" width="100"><template #default="scope"><el-tag :type="scope.row.userStatus === 1 ? 'success' : 'danger'">{{ scope.row.userStatus === 1 ? '正常' : '封禁' }}</el-tag></template></el-table-column><el-table-column prop="createTime" label="注册时间" width="180" /><el-table-column label="操作" width="150"><template #default="scope"><el-button size="small" @click="viewUserDetail(scope.row)">详情</el-button><el-button size="small" :type="scope.row.userStatus === 1 ? 'warning' : 'success'"@click="toggleUserStatus(scope.row)">{{ scope.row.userStatus === 1 ? '封禁' : '解封' }}</el-button></template></el-table-column></el-table></el-card></div>
</template><script>
import { getContents, getDashboardStats, approveContent, rejectContent, getUsers, toggleUserStatus } from '@/api/social'export default {name: 'SocialAdmin',data() {return {stats: {totalUsers: 0,totalVideos: 0,dailyActiveUsers: 0,avgWatchTime: 0},contentList: [],userList: [],loading: false,userLoading: false,queryParams: {contentType: '',auditStatus: '',dateRange: []},pagination: {current: 1,size: 10,total: 0}}},mounted() {this.loadDashboardData()this.loadContentList()this.loadUserList()},methods: {async loadDashboardData() {try {const res = await getDashboardStats()if (res.code === 200) {this.stats = res.data}} catch (error) {this.$message.error('加载数据失败')}},async loadContentList() {this.loading = truetry {const params = {...this.queryParams,page: this.pagination.current,size: this.pagination.size}const res = await getContents(params)if (res.code === 200) {this.contentList = res.data.recordsthis.pagination.total = res.data.total}} catch (error) {this.$message.error('加载内容列表失败')} finally {this.loading = false}},async loadUserList() {this.userLoading = truetry {const res = await getUsers()if (res.code === 200) {this.userList = res.data}} catch (error) {this.$message.error('加载用户列表失败')} finally {this.userLoading = false}},getAuditStatusTagType(status) {const map = {1: 'warning',  // 待审核2: 'success',  // 审核通过3: 'danger'    // 审核拒绝}return map[status] || 'info'},getAuditStatusText(status) {const map = {1: '待审核',2: '审核通过',3: '审核拒绝'}return map[status] || '未知'},// 审核通过内容async approveContent(content) {try {const res = await approveContent(content.id)if (res.code === 200) {this.$message.success('审核通过')this.loadContentList()}} catch (error) {this.$message.error('操作失败')}},// 审核拒绝内容async rejectContent(content) {try {const res = await rejectContent(content.id)if (res.code === 200) {this.$message.success('已拒绝')this.loadContentList()}} catch (error) {this.$message.error('操作失败')}},// 切换用户状态async toggleUserStatus(user) {try {const res = await toggleUserStatus(user.id, user.userStatus === 1 ? 0 : 1)if (res.code === 200) {this.$message.success('操作成功')this.loadUserList()}} catch (error) {this.$message.error('操作失败')}},handleSearch() {this.pagination.current = 1this.loadContentList()},handleReset() {this.queryParams = {contentType: '',auditStatus: '',dateRange: []}this.handleSearch()},handleSizeChange(size) {this.pagination.size = sizethis.loadContentList()},handleCurrentChange(current) {this.pagination.current = currentthis.loadContentList()},viewContentDetail(content) {this.$router.push(`/content/detail/${content.id}`)},viewUserDetail(user) {this.$router.push(`/user/detail/${user.id}`)}}
}
</script><style scoped>
.social-admin-container {padding: 20px;background: #f5f7fa;
}.stats-card {text-align: center;
}.stats-number {font-size: 32px;font-weight: bold;color: #1890ff;margin-bottom: 8px;
}.stats-label {color: #666;font-size: 14px;
}.table-card {margin-top: 20px;
}.card-header {display: flex;justify-content: space-between;align-items: center;
}.user-management-card {margin-top: 20px;
}.content-preview {width: 100px;height: 80px;border-radius: 8px;object-fit: cover;
}
</style>
数据库设计核心表结构
-- 用户信息表
CREATE TABLE `user_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '用户名',`phone` varchar(20) DEFAULT NULL COMMENT '手机号',`email` varchar(100) DEFAULT NULL COMMENT '邮箱',`password` varchar(255) NOT NULL COMMENT '密码',`avatar` varchar(500) DEFAULT NULL COMMENT '头像',`bio` varchar(200) DEFAULT NULL COMMENT '个人简介',`gender` tinyint(1) DEFAULT NULL COMMENT '性别',`birthday` date DEFAULT NULL COMMENT '生日',`location` varchar(100) DEFAULT NULL COMMENT '位置',`follower_count` int(11) DEFAULT '0' COMMENT '粉丝数',`following_count` int(11) DEFAULT '0' COMMENT '关注数',`video_count` int(11) DEFAULT '0' COMMENT '作品数',`like_count` int(11) DEFAULT '0' COMMENT '获赞数',`user_status` tinyint(1) DEFAULT '1' COMMENT '用户状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `uk_username` (`username`),UNIQUE KEY `uk_phone` (`phone`),KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';-- 短视频内容表
CREATE TABLE `short_video` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) NOT NULL COMMENT '发布用户ID',`video_url` varchar(500) NOT NULL COMMENT '视频文件地址',`cover_url` varchar(500) DEFAULT NULL COMMENT '封面图地址',`video_description` varchar(1000) DEFAULT NULL COMMENT '视频描述',`video_duration` int(11) NOT NULL COMMENT '视频时长',`video_size` bigint(20) NOT NULL COMMENT '视频文件大小',`video_resolution` varchar(20) DEFAULT NULL COMMENT '视频分辨率',`content_type` tinyint(1) NOT NULL COMMENT '内容类型',`like_count` int(11) DEFAULT '0' COMMENT '点赞数',`comment_count` int(11) DEFAULT '0' COMMENT '评论数',`share_count` int(11) DEFAULT '0' COMMENT '分享数',`view_count` int(11) DEFAULT '0' COMMENT '播放次数',`topic_tags` json DEFAULT NULL COMMENT '话题标签',`location` varchar(100) DEFAULT NULL COMMENT '发布位置',`visibility` tinyint(1) DEFAULT '1' COMMENT '可见性',`audit_status` tinyint(1) DEFAULT '1' COMMENT '审核状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`),KEY `idx_audit_status` (`audit_status`),KEY `idx_create_time` (`create_time`),KEY `idx_like_count` (`like_count`),FULLTEXT KEY `ft_description` (`video_description`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短视频内容表';-- 用户关系表
CREATE TABLE `user_relationship` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`from_user_id` bigint(20) NOT NULL COMMENT '关注者ID',`to_user_id` bigint(20) NOT NULL COMMENT '被关注者ID',`relationship_type` tinyint(1) NOT NULL COMMENT '关系类型',`relationship_status` tinyint(1) DEFAULT '1' COMMENT '关系状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `uk_follow` (`from_user_id`, `to_user_id`),KEY `idx_from_user` (`from_user_id`),KEY `idx_to_user` (`to_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户关系表';-- 聊天消息表
CREATE TABLE `chat_message` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`sender_id` bigint(20) NOT NULL COMMENT '发送者ID',`receiver_id` bigint(20) NOT NULL COMMENT '接收者ID',`message_type` tinyint(1) NOT NULL COMMENT '消息类型',`content` text NOT NULL COMMENT '消息内容',`image_url` varchar(500) DEFAULT NULL COMMENT '图片地址',`video_url` varchar(500) DEFAULT NULL COMMENT '视频地址',`message_status` tinyint(1) DEFAULT '1' COMMENT '消息状态',`send_time` datetime DEFAULT CURRENT_TIMESTAMP,`read_time` datetime DEFAULT NULL COMMENT '阅读时间',PRIMARY KEY (`id`),KEY `idx_sender` (`sender_id`),KEY `idx_receiver` (`receiver_id`),KEY `idx_send_time` (`send_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天消息表';

这套基于JAVA国际版图文短视频交友系统的完整解决方案,通过现代化的微服务架构和实时多媒体处理技术,为全球社交娱乐行业提供了全方位的数字化转型升级路径。系统采用SpringBoot+MyBatisPlus+MySQL构建高可用分布式服务集群,使用Uniapp框架实现H5、APP多端统一的用户界面,配合Vue+ElementUI的管理后台,形成了完整的技术生态闭环。

从技术实现角度看,该系统创新性地引入了智能推荐算法、实时消息通信、多媒体内容处理等先进技术理念,确保了社交平台在高并发场景下的性能稳定和用户体验流畅。对于社交平台运营商而言,这套系统不仅实现了社交功能的全面覆盖,更重要的是通过数据分析和机器学习为用户提供了个性化的内容推荐和精准的社交匹配。

随着5G技术的普及和全球数字化社交需求的持续增长,图文短视频社交正在成为新一代的主流社交方式。这套JAVA国际版图文短视频交友系统源码以其先进的技术架构、完善的功能设计和良好的国际化支持,将成为社交创业者和企业在全球市场竞争中赢得用户青睐的重要技术支撑。未来,随着人工智能、虚拟现实等新技术的深度融合,该系统还将持续演进,为全球社交娱乐行业创新发展提供更强大的技术动力。

http://www.dtcms.com/a/499816.html

相关文章:

  • 【图像处理】图片的前向映射与后向映射
  • K8S(十三)—— Helm3从入门到实战:简化Kubernetes应用部署与管理
  • 如何录制视频,用 OBS
  • 网站地址做图标大型公司网站建设
  • 图片下载网站哪个好自己建设博客网站
  • 宝安哪有网站建设网站制作公司优势
  • 数据结构之——线性表的应用
  • Streamlit 交互与人python工智能网站开发基础
  • 湖北省建设厅官方网站文件福建省龙岩市新罗区建设局网站
  • 【点云】pointnet网络梳理
  • 我编译好的opencv库与ros2 humble库里面的opencv库的解决方案
  • 免费seo网站自动推广wordpress电子商务站
  • 不同程序建的网站风格网站名称 备案
  • 鸿蒙 emitter 和 eventHub 的区别
  • Java中Elasticsearch完全指南:从零基础到实战应用
  • 网站开发承包合同网站地图怎么弄
  • 【算法】day7 滑动窗口+二分查找
  • Kylin Linux Advanced Server V10 (Sword)上离线安装Ansible
  • 大学生做的广告短视频网站山东省建设教育集团网站首页
  • LeetCode 面试经典 150_栈_最小栈(54_155_C++_中等)(辅助栈)
  • 西安网站建设服务商十强文明网站建设
  • 互动网站如何做做网站和做程序一样吗
  • mockpuls可以做网站吗湖南招聘信息网官网
  • 【Qt】信号与槽(Signal and Slot)- 简易计算器
  • 2.5 网口
  • 肤契:全域协议版 IV 樱花町的晨光
  • dede 建设网站做个普通的网站多少钱
  • Nivo图表库全面指南:配置与用法详解
  • 典型营销型网站有哪些惠阳住房和城乡建设局网站
  • 算法题——贪心算法