/** * socket入口脚本文件 * * @author caiaolin * @date 2017-05-12 * @version */ const socket = require('socket.io'); const moment = require('moment'); const { PageTarget } = require('./public/common_constants'); const socketIO = socket(3300); const userCache = {}; function getEditingUsers(projectID) { const users = userCache[projectID]; if (!users) { return []; } const rst = []; const existMap = {}; for (const user of users) { if (existMap[user._id]) { continue; } existMap[user._id] = true; rst.push(user); } return rst; } // socket.io相关操作 socketIO.on('connection', function(socket) { let roomInfo = {}; let curUser; let curProjectID; console.log("new connection"); // 加入房间 socket.on('join', function(data) { const { roomData, payload } = data; if (payload && payload.user) { curUser = payload.user; } if (roomData) { if (roomData.projectID) { curProjectID = roomData.projectID; if (!userCache[roomData.projectID]) { userCache[roomData.projectID] = []; } // 由于用户可以重复打开项目,因此不做唯一性处理 userCache[roomData.projectID].push(curUser); } for(let key in roomData){ roomInfo[key] = roomData[key]; socket.join(roomData[key], () => { if (key === 'projectID') { const editingUsers = getEditingUsers(curProjectID); if (editingUsers.length > 1) { // 只有一个用户数据,说明只有用户自己打开项目,不需要推送数据,减少触发。 socket.broadcast.to(roomInfo.projectID).emit('handleAvatarList', {editingUsers}); socket.emit('handleAvatarList', {editingUsers}); } } }); } } }); // 数据更改通知 socket.on('unitFileChangeNotify', function(data) { socket.broadcast.to(roomInfo['unitFile']).emit('unitFileChange', data); if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data); }); socket.on('feeRateChangeNotify', function(data) { socket.broadcast.to(roomInfo['feeRate']).emit('feeRateChange', data); if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data); }); socket.on('changeNewRoom', function(data) { if(data.projectID){//如果有项目ID,则通知同一个项目在其它地方被打开的页面 socket.broadcast.to(data.oldRoom).emit('changeFileNotify', data); if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data); } socket.leave(data.oldRoom); socket.join(data.newRoom); roomInfo[data.name]=data.newRoom; }); socket.on('removeProjectMark', function(data) { if(data.projectID && data.userID){ socket.broadcast.to(data.userID).emit('refreshProjectIcon', data); } }); socket.on('multiFileChangeNotify', function(data) { console.log(data); let projectID = data.projects[0].projectID; let userID = data.user_id; if(projectID && userID){//通知项目管理页面 socket.broadcast.to(userID).emit('fileDataChange', {projectID:projectID}); } for(let fileID of data.oldFileIDs){//通知已打开的项目页面 let messageTitle = data.from == "feeRateFile"?"feeRateChange":"unitFileChange"; socket.broadcast.to(fileID).emit(messageTitle, data); } }); // 分享权限变更 socket.on('sharePermissionChange', async function ({ permissionType, userID, compilationID, projectID, emitTenders, payload }) { const emitPayload = { projectID }; if (payload) { if (payload.prop) { payload.prop.updateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'); } Object.assign(emitPayload, payload); } // 推送给项目管理页面 socket.broadcast.to(`${userID}@${compilationID}`).emit('sharePermissionChange', { permissionType, target: PageTarget.PM, payload: emitPayload }); // 推送给主页面 for (const tender of emitTenders) { const emitPayload = {}; if (typeof tender.allowCooperate !== 'undefined') { emitPayload.allowCooperate = tender.allowCooperate; } socket.broadcast.to(`${userID}@${tender.ID}`).emit('sharePermissionChange', { permissionType, target: PageTarget.MAIN, payload: emitPayload }); } }); // 项目管理树结构变化 socket.on('pmTreeChange', function ({ userID, compilationID, expandState, selection }) { socket.broadcast.to(`${userID}@${compilationID}`).emit('pmTreeChange', { expandState, selection }); }); socket.on('disconnect', function () { // 由于用户可以重复打开项目,因此不做唯一性处理,只删除一个数据,不删除所有的同用户数据 if (curProjectID && userCache[curProjectID]) { const index = userCache[curProjectID].findIndex(user => user._id === curUser._id); if (index >= 0) { userCache[curProjectID].splice(index, 1); if (!userCache[curProjectID].length) { delete userCache[curProjectID]; } const editingUsers = getEditingUsers(curProjectID); socket.broadcast.to(roomInfo.projectID).emit('handleAvatarList', {editingUsers}); socket.emit('handleAvatarList', {editingUsers}); } } console.log("client disconnect =========="+JSON.stringify(roomInfo)); }); });