# ims **Repository Path**: e4glet/ims ## Basic Information - **Project Name**: ims - **Description**: 在线会议系统,支持音视频通话、屏幕共享、文字聊天。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-22 - **Last Updated**: 2026-08-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Internal Meeting System (IMS) 内部会议系统,支持音视频通话、屏幕共享、文字聊天。支持**电脑、平板、手机**多端访问(响应式布局)。 --- ## 快速启动(开发环境) ### 后端 ```bash cd backend npm install npm run dev ``` ### 前端 ```bash cd frontend npm install npm run dev ``` 访问 http://localhost:5173 --- ## Docker 部署(生产环境) ### 部署架构 | 容器 | 端口映射 | 说明 | |------|----------|------| | ims-server | 8089:3000 | Node.js 后端服务 | | ims | 8090:80 | Nginx 前端静态服务 | ### 后端部署 ```bash # 构建镜像(在 backend 目录下) docker build -t ims-server . # 导出镜像 docker save -o ims-server.tar imsserver:latest # 导入镜像 docker load -i ims-server.tar # 运行容器 docker run --privileged=true -dit \ -p 8089:3000 \ --restart=always \ --name ims-server \ ims-server ``` ### 前端部署 #### 1. 修改前端配置 **`frontend/vite.config.js`** ```javascript export default defineConfig({ base: '/ims/', // 部署子路径 // ... 其他配置 }) ``` **`frontend/src/router/index.js`** ```javascript const router = createRouter({ history: createWebHistory('/ims/'), // 与 base 保持一致 routes: [...] }) ``` **`frontend/.env.production`** ```env VITE_WS_URL=https://your-domain.com VITE_SOCKET_PATH=/ims_server/socket.io ``` > 注意: > - `VITE_WS_URL` 只包含域名,不包含子路径。 > - `VITE_SOCKET_PATH` 指定 Socket.IO 连接路径:**开发环境**为 `/socket.io`(直连后端),**生产环境**为 `/ims_server/socket.io`(经 Nginx 代理去除前缀后到达后端)。 **`frontend/.env`(开发环境)** ```env VITE_WS_URL=http://localhost:3000 VITE_SOCKET_PATH=/socket.io ``` #### 2. 构建前端 ```bash cd frontend npm install npm run build # 构建产物输出到 frontend/dist/ ``` #### 3. 部署到服务器 ```bash # 创建部署目录 mkdir -p /root/ims # 上传构建产物 scp -r dist/* root@your-server-ip:/root/ims/ # 运行前端容器(使用自定义 Nginx 镜像) docker run --privileged=true -dit \ -p 8090:80 \ -v /root/ims:/usr/share/nginx/html/ \ --restart=always \ --name ims \ myvue ``` --- ## Nginx 反向代理配置(主服务器) 在域名所在服务器的 Nginx 配置中添加: ```nginx server { listen 443 ssl http2; server_name your-domain.com; # SSL 证书配置 ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; # 前端静态文件 location /ims/ { proxy_pass http://your-server-ip:8090/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 后端 API(含 WebSocket 支持) location /ims_server/ { proxy_pass http://your-server-ip:8089/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 60s; proxy_connect_timeout 60s; } # HTTP 重定向到 HTTPS listen 80; return 301 https://$server_name$request_uri; } ``` --- ## 访问地址 部署完成后访问: | 服务 | 地址 | |------|------| | 前端页面 | `https://your-domain.com/ims` | | 后端健康检查 | `https://your-domain.com/ims_server/health` | | WebSocket 连接 | `wss://your-domain.com/ims_server/socket.io/` | --- ## 多端适配(电脑 / 平板 / 手机) 前端为响应式布局,按屏幕宽度自动切换: | 设备 | 断点 | 布局 | |------|------|------| | 手机(<768px) | `max-width: 767px` | 视频区占满屏幕;聊天为右侧滑入的全屏抽屉(底部控制栏点「聊天」按钮打开,右上角 × 关闭);控制栏按钮与间距自动压缩 | | 平板 / 桌面(≥768px) | `min-width: 768px` | 左右布局:左侧视频网格 + 右侧常驻聊天侧栏 | 实现要点: - `index.html` 已配置 viewport meta。 - 会议室高度使用 `100dvh`,适配移动端浏览器动态地址栏。 - 底部控制栏与聊天输入框适配 iOS 刘海屏安全区(`env(safe-area-inset-bottom)`)。 - 手机端视频网格 `auto-fit minmax(140px, 1fr)`:单人自动铺满宽度,多人自动分列。 涉及文件:`MeetingRoom.vue`、`VideoGrid.vue`、`ChatBox.vue`、`ControlsBar.vue`、`Home.vue`。 --- ## 子路径适配说明 应用部署在 `/ims/` 子路径下,需要修改以下配置: ### 1. `frontend/vite.config.js` ```javascript export default defineConfig({ base: '/ims/', // 部署子路径 // ... }) ``` ### 2. `frontend/src/router/index.js` ```javascript const router = createRouter({ history: createWebHistory('/ims/'), // 与 base 保持一致 // ... }) ``` ### 3. `frontend/.env.production` ```env VITE_WS_URL=https://your-domain.com VITE_SOCKET_PATH=/ims_server/socket.io ``` ### 4. `frontend/src/views/MeetingRoom.vue` ```javascript const joinRoom = async () => { try { // URL 只包含域名 const wsUrl = import.meta.env.VITE_WS_URL || window.location.origin // Socket.IO 路径由环境变量 VITE_SOCKET_PATH 控制(开发 /socket.io,生产 /ims_server/socket.io) connect(wsUrl, { path: import.meta.env.VITE_SOCKET_PATH || '/socket.io' }) // ... } catch (error) { console.error('Failed to join room:', error) } } ``` ### 5. `frontend/src/composables/useSocket.js` ```javascript const connect = (serverUrl, options = {}) => { const defaultOptions = { transports: ['websocket'], reconnectionAttempts: 3, autoConnect: true } const socketOptions = { ...defaultOptions, ...options } socket.value = io(serverUrl, socketOptions) // ... } ``` --- ## 验证部署 ### 1. 检查容器状态 ```bash docker ps | grep ims ``` ### 2. 测试后端健康检查 ```bash curl https://your-domain.com/ims_server/health ``` 预期返回: ```json {"status":"ok","timestamp":"2026-07-22T05:49:28.348Z"} ``` ### 3. 浏览器验证 1. 访问 `https://your-domain.com/ims` 2. 按 F12 打开开发者工具 3. 查看 Console 是否显示 `Socket connected` 4. 查看 Network → WS 是否连接成功(状态码 101) --- ## 常见问题排查 ### Q1: 页面空白或 404 - 检查 `vite.config.js` 中 `base` 是否设置为 `/ims/` - 检查 `router/index.js` 中 `createWebHistory('/ims/')` - 确认 `/root/ims/` 目录包含 `index.html` ### Q2: WebSocket 连接失败 - 检查 Nginx 是否配置了 WebSocket 代理(Upgrade 头) - 确认环境变量 `VITE_SOCKET_PATH`:生产为 `/ims_server/socket.io`,开发为 `/socket.io` - 检查后端容器是否正常运行 ### Q3: 静态资源 404 - 确认 `vite.config.js` 中 `base: '/ims/'` - 检查构建产物中的资源路径是否以 `/ims/` 开头 ### Q4: 跨域问题 - 检查后端 CORS 配置是否正确 - 确认 `frontendUrl` 环境变量已设置 --- ## 技术栈 | 层 | 技术 | |----|------| | 前端 | Vue 3 + Vite + Socket.IO Client + simple-peer | | 后端 | Node.js + Express + Socket.IO | | 部署 | Docker + Nginx | | 通信 | WebSocket (信令) + WebRTC P2P (媒体) | | 多端适配 | 响应式布局(CSS Media Query),电脑 / 平板 / 手机 | --- ## 作者 - e4glet