SpringBootVue在线视频会议系统含AI助手敏感词过滤即时通讯核心功能1多人在线会议视频语音投屏2集成DeepSeek大模型作为AI会议助手3智能敏感词过滤系统可自定义规则4即时通讯好友系统消息同步5完善的后台管理系统数据统计/词云分析项目亮点✓ 采用WebRTC实时通信技术流畅稳定✓ 独创用户自主发起会议模式权限灵活可控✓ 接入DeepSeek大模型实现智能对话✓ 敏感词过滤消息加密双重安全保障包含了基础的音视频通信还融入了当下流行的AI 大模型和内容安全机制。核心架构设计、数据库模型、关键功能模块的代码实现以及前后端交互逻辑。你可以基于此框架快速构建出演示版本。️ 1. 系统技术栈与架构设计后端: Spring Boot 3.x, MyBatis-Plus, WebSocket (信令服务), Netty (可选用于高并发消息)前端: Vue 3 TypeScript, Element Plus, Simple-Peer / WebRTC APIAI 集成: DeepSeek API (HTTP 调用)敏感词过滤: DFA 算法 (确定有穷自动机) 或 第三方 API数据库: MySQL 8.0, Redis (缓存会议状态/消息队列)目录结构建议project-root ├── backend (SpringBoot) │ ├── src/main/java/com/meeting │ │ ├── config (WebRTC, WebSocket, AI Config) │ │ ├── controller (Meeting, Chat, AI, User) │ │ ├── service (impl) │ │ ├── model (Entity, DTO) │ │ ├── util (SensitiveWordFilter, DeepSeekClient) │ │ └── websocket (MeetingSignalingHandler) │ └── resources (application.yml) ├── frontend (Vue3) │ ├── src │ │ ├── api (axios instances) │ │ ├── components (VideoGrid, ChatBox, AIAssistant) │ │ ├── views (MeetingRoom, Login, AdminDashboard) │ │ ├── store (pinia for state management) │ │ └── utils (webRTC-helper.js) 2. 数据库设计 (MySQL)你需要至少以下几张核心表来支撑业务-- 用户表CREATETABLEsys_user(idbigintNOTNULLAUTO_INCREMENT,usernamevarchar(50)NOTNULL,passwordvarchar(100)NOTNULL,avatarvarchar(255)DEFAULTNULL,emailvarchar(100)DEFAULTNULL,PRIMARYKEY(id));-- 会议表CREATETABLEmeeting_room(idbigintNOTNULLAUTO_INCREMENT,meeting_idvarchar(64)NOTNULLCOMMENT会议唯一ID,host_idbigintNOTNULLCOMMENT主持人ID,topicvarchar(200)DEFAULT项目收尾总结会议,start_timedatetimeDEFAULTNULL,statustinyintDEFAULT1COMMENT1-进行中 0-已结束,PRIMARYKEY(id),UNIQUEKEYuk_meeting_id(meeting_id));-- 敏感词库表CREATETABLEsensitive_word(idintNOTNULLAUTO_INCREMENT,wordvarchar(50)NOTNULL,categoryvarchar(20)DEFAULTdefault,PRIMARYKEY(id));-- 聊天记录表 (含 AI 对话)CREATETABLEchat_message(idbigintNOTNULLAUTO_INCREMENT,meeting_idvarchar(64)NOTNULL,sender_idbigintDEFAULT0COMMENT0 代表 AI 助手,contenttextNOTNULL,msg_typetinyintDEFAULT1COMMENT1-文本 2-AI 回复 3-系统通知,create_timedatetimeDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(id));⚙️ 3. 后端核心代码实现 (SpringBoot)A. 敏感词过滤工具类 (DFA 算法简化版)这是保障内容安全的核心。ComponentpublicclassSensitiveWordFilter{privatefinalMapString,ObjectsensitiveMapnewHashMap();privatestaticfinalStringSKIP_SYMBOL*;PostConstructpublicvoidinit(){// 从数据库加载敏感词并构建 DFA 树ListStringwordsloadWordsFromDB();for(Stringword:words){addWordToMap(word);}}privatevoidaddWordToMap(Stringword){MapString,ObjectcurrentMapsensitiveMap;for(charc:word.toCharArray()){ObjectsubMapcurrentMap.get(String.valueOf(c));if(subMapnull){MapString,ObjectnewMapnewHashMap();currentMap.put(String.valueOf(c),newMap);currentMapnewMap;}else{currentMap(MapString,Object)subMap;}}currentMap.put(isEnd,true);}publicStringfilter(Stringtext){if(textnull)returnnull;StringBuilderresultnewStringBuilder();inttempIndex0;MapString,ObjectnowMapsensitiveMap;for(inti0;itext.length();i){charctext.charAt(i);ObjectsubMapnowMap.get(String.valueOf(c));if(subMapnull){result.append(text.charAt(tempIndex));tempIndex;itempIndex-1;nowMapsensitiveMap;}else{nowMap(MapString,Object)subMap;if(true.equals(nowMap.get(isEnd))){// 发现敏感词替换为 *for(intjtempIndex;ji;j){result.append(SKIP_SYMBOL);}tempIndexi1;nowMapsensitiveMap;}}}// 处理剩余字符while(tempIndextext.length()){result.append(text.charAt(tempIndex));}returnresult.toString();}// 模拟从 DB 加载privateListStringloadWordsFromDB(){returnArrays.asList(广告,赌博,违规词);}}B. DeepSeek AI 助手服务集成大模型作为会议助手用于总结或回答问题。ServicepublicclassDeepSeekService{Value(${deepseek.api.key})privateStringapiKey;Value(${deepseek.api.url})privateStringapiUrl;privatefinalRestTemplaterestTemplatenewRestTemplate();publicStringgetAiResponse(Stringcontext,StringuserQuestion){// 构建 PromptStringprompt你是一个会议助手。当前会议背景context\n用户提问userQuestion;MapString,ObjectbodynewHashMap();body.put(model,deepseek-chat);body.put(messages,Arrays.asList(Map.of(role,user,content,prompt)));HttpHeadersheadersnewHttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.set(Authorization,Bearer apiKey);HttpEntityMapString,ObjectentitynewHttpEntity(body,headers);try{ResponseEntityMapresponserestTemplate.postForEntity(apiUrl,entity,Map.class);if(response.getStatusCode().is2xxSuccessful()){ListMapchoices(ListMap)((Map)response.getBody()).get(choices);return(String)((Map)choices.get(0)).get(message).get(content);}}catch(Exceptione){e.printStackTrace();returnAI 助手暂时繁忙请稍后再试。;}return无法连接到 AI 服务。;}}C. WebSocket 信令服务器 (核心通信)处理加入房间、SDP 交换、ICE Candidate 交换。ServerEndpoint(/ws/meeting/{meetingId}/{userId})ComponentpublicclassMeetingWebSocket{privatestaticfinalConcurrentHashMapString,ConcurrentHashMapString,SessionMEETING_ROOMSnewConcurrentHashMap();AutowiredprivateSensitiveWordFiltersensitiveWordFilter;AutowiredprivateDeepSeekServicedeepSeekService;OnOpenpublicvoidonOpen(Sessionsession,PathParam(meetingId)StringmeetingId,PathParam(userId)StringuserId){// 用户加入房间逻辑MEETING_ROOMS.computeIfAbsent(meetingId,k-newConcurrentHashMap()).put(userId,session);sendMessageToRoom(meetingId,userId,SYSTEM,userId 加入了会议);}OnMessagepublicvoidonMessage(Stringmessage,Sessionsession,PathParam(meetingId)StringmeetingId,PathParam(userId)StringuserId){JSONObjectjsonMsgJSON.parseObject(message);StringtypejsonMsg.getString(type);if(OFFER.equals(type)||ANSWER.equals(type)||ICE_CANDIDATE.equals(type)){// WebRTC 信令转发StringtargetIdjsonMsg.getString(targetId);sendToOne(targetId,meetingId,message);}elseif(CHAT.equals(type)){// 聊天消息处理StringcontentjsonMsg.getString(content);// 1. 敏感词过滤StringfilteredContentsensitiveWordFilter.filter(content);// 2. 广播消息JSONObjectrespnewJSONObject();resp.put(type,CHAT);resp.put(senderId,userId);resp.put(content,filteredContent);sendMessageToRoom(meetingId,userId,resp.toJSONString());// 3. 如果AI触发 DeepSeekif(content.contains(AI)){newThread(()-{StringaiReplydeepSeekService.getAiResponse(会议中...,content.replace(AI,));JSONObjectaiRespnewJSONObject();aiResp.put(type,CHAT);aiResp.put(senderId,AI_BOT);aiResp.put(content,aiReply);sendMessageToRoom(meetingId,AI_BOT,aiResp.toJSONString());}).start();}}}privatevoidsendMessageToRoom(StringmeetingId,StringexcludeUserId,Stringmessage){ConcurrentHashMapString,SessionusersMEETING_ROOMS.get(meetingId);if(users!null){for(Map.EntryString,Sessionentry:users.entrySet()){if(!entry.getKey().equals(excludeUserId)){try{entry.getValue().getBasicRemote().sendText(message);}catch(IOExceptione){}}}}}// ... 其他方法 (onClose, sendToOne 等)}️ 4. 前端核心代码实现 (Vue 3)A. 视频网格组件 (VideoGrid.vue)使用simple-peer简化 WebRTC 连接。template div classvideo-grid div v-forpeer in peers :keypeer.peerId classvideo-item video refvideoRefs :data-peer-idpeer.peerId autoplay playsinline/video div classuser-label{{ peer.userName }}/div /div !-- 本地视频 -- div classvideo-item local video reflocalVideo autoplay muted playsinline/video div classuser-label我 (Host)/div /div /div /template script setup import { ref, onMounted, watch } from vue; import Peer from simple-peer; const props defineProps([socket, stream, users]); const localVideo ref(null); const videoRefs ref([]); const peers ref([]); onMounted(() { if (localVideo.value props.stream) { localVideo.value.srcObject props.stream; } }); // 监听新用户加入发起 Offer watch(() props.users, (newUsers) { newUsers.forEach(user { if (user.id ! myUserId !peers.value.find(p p.peerId user.id)) { createPeer(user.id, true); } }); }, { deep: true }); // 接收信令 props.socket.onmessage (event) { const data JSON.parse(event.data); if (data.type OFFER) { createPeer(data.senderId, false, data.signal); } else if (data.type ANSWER || data.type ICE_CANDIDATE) { const peer peers.value.find(p p.peerId data.senderId); if (peer) peer.peer.signal(data.signal); } }; function createPeer(peerId, initiator, signal null) { const peer new Peer({ initiator, trickle: false, stream: props.stream, signal }); peer.on(signal, data { props.socket.send(JSON.stringify({ type: initiator ? OFFER : ANSWER, targetId: peerId, signal: data })); }); peer.on(stream, remoteStream { const videoEl videoRefs.value.find(v v.dataset.peerId peerId); if (videoEl) videoEl.srcObject remoteStream; }); peers.value.push({ peerId, peer }); } /script style scoped .video-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px; } video { width: 100%; border-radius: 8px; background: #000; } /styleB. 聊天与 AI 助手组件 (ChatBox.vue)template div classchat-box div classmessages div v-formsg in messages :keymsg.id :class[msg, msg.senderId myId ? self : other] strong{{ msg.senderName }}:/strong p v-htmlhighlightKeywords(msg.content)/p /div /div div classinput-area input v-modelnewMessage keyup.entersendMessage placeholder输入消息AI 提问... / button clicksendMessage发送/button /div /div /template script setup import { ref } from vue; import { useSocketStore } from /store/socket; const socketStore useSocketStore(); const messages ref([]); const newMessage ref(); const myId current-user-id; // 从 store 获取 const sendMessage () { if (!newMessage.value.trim()) return; // 发送 WebSocket 消息 socketStore.send({ type: CHAT, content: newMessage.value }); // 本地追加 (实际应由服务端广播回来) messages.value.push({ senderId: myId, senderName: 我, content: newMessage.value }); newMessage.value ; }; // 简单的高亮显示敏感词替换后的效果 const highlightKeywords (text) { return text.replace(/\*/g, span stylecolor:red; font-weight:bold*/span); }; // 监听 Socket 消息 socketStore.socket.onmessage (e) { const data JSON.parse(e.data); if (data.type CHAT) { messages.value.push({ senderId: data.senderId, senderName: data.senderId AI_BOT ? AI 助手 : 参会者, content: data.content }); } }; /script 5. 如何运行与调试环境准备:安装 JDK 17, Node.js 18, MySQL 8.申请 DeepSeek API Key (在 DeepSeek 官网 获取)。后端启动:导入 SQL 脚本创建数据库。修改application.yml配置数据库连接和 DeepSeek Key。运行MeetingApplication.java。前端启动:npm install修改.env中的后端 WebSocket 地址 (如ws://localhost:8080/ws/meeting/...)。npm run dev测试流程:打开两个浏览器窗口或无痕模式。用户 A 创建会议复制会议 ID。用户 B 输入会议 ID 加入。视频测试: 双方应能看到彼此画面。敏感词测试: 发送包含“广告”的消息观察是否变为**。AI 测试: 发送AI 请总结一下今天的会议主题观察右侧是否收到 AI 回复。