socket.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * socket入口脚本文件
  3. *
  4. * @author caiaolin
  5. * @date 2017-05-12
  6. * @version
  7. */
  8. const socket = require("socket.io");
  9. const config = require("./config/config.js");
  10. const moment = require('moment');
  11. const { PageTarget } = require('./public/common_constants');
  12. let socketPort = config[process.env.NODE_ENV].socketPort?config[process.env.NODE_ENV].socketPort:5500;
  13. console.log(socketPort)
  14. const socketIO = socket(socketPort);
  15. const userCache = {};
  16. function getEditingUsers(projectID) {
  17. const users = userCache[projectID];
  18. if (!users) {
  19. return [];
  20. }
  21. const rst = [];
  22. const existMap = {};
  23. for (const user of users) {
  24. if (existMap[user._id]) {
  25. continue;
  26. }
  27. existMap[user._id] = true;
  28. rst.push(user);
  29. }
  30. return rst;
  31. }
  32. // socket.io相关操作
  33. socketIO.on('connection', function(socket) {
  34. let roomInfo = {};
  35. let curUser;
  36. let curProjectID;
  37. console.log("new connection");
  38. // 加入房间
  39. socket.on('join', function(data) {
  40. const { roomData, payload } = data;
  41. if (payload && payload.user) {
  42. curUser = payload.user;
  43. }
  44. if (roomData) {
  45. if (roomData.projectID) {
  46. curProjectID = roomData.projectID;
  47. if (!userCache[roomData.projectID]) {
  48. userCache[roomData.projectID] = [];
  49. }
  50. // 由于用户可以重复打开项目,因此不做唯一性处理
  51. userCache[roomData.projectID].push(curUser);
  52. }
  53. for(let key in roomData){
  54. roomInfo[key] = roomData[key];
  55. socket.join(roomData[key], () => {
  56. if (key === 'projectID') {
  57. const editingUsers = getEditingUsers(curProjectID);
  58. if (editingUsers.length > 1) { // 只有一个用户数据,说明只有用户自己打开项目,不需要推送数据,减少触发。
  59. socket.broadcast.to(roomInfo.projectID).emit('handleAvatarList', {editingUsers});
  60. socket.emit('handleAvatarList', {editingUsers});
  61. }
  62. }
  63. });
  64. }
  65. }
  66. });
  67. // 数据更改通知
  68. socket.on('unitFileChangeNotify', function(data) {
  69. socket.broadcast.to(roomInfo['unitFile']).emit('unitFileChange', data);
  70. if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data);
  71. });
  72. socket.on('feeRateChangeNotify', function(data) {
  73. socket.broadcast.to(roomInfo['feeRate']).emit('feeRateChange', data);
  74. if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data);
  75. });
  76. socket.on('changeNewRoom', function(data) {
  77. if(data.projectID){//如果有项目ID,则通知同一个项目在其它地方被打开的页面
  78. socket.broadcast.to(data.oldRoom).emit('changeFileNotify', data);
  79. if(data.userID) socket.broadcast.to(data.userID).emit('fileDataChange', data);
  80. }
  81. socket.leave(data.oldRoom);
  82. socket.join(data.newRoom);
  83. roomInfo[data.name]=data.newRoom;
  84. });
  85. socket.on('removeProjectMark', function(data) {
  86. if(data.projectID && data.userID){
  87. socket.broadcast.to(data.userID).emit('refreshProjectIcon', data);
  88. }
  89. });
  90. socket.on('multiFileChangeNotify', function(data) {
  91. console.log(data);
  92. let projectID = data.projects[0].projectID;
  93. let userID = data.user_id;
  94. if(projectID && userID){//通知项目管理页面
  95. socket.broadcast.to(userID).emit('fileDataChange', {projectID:projectID});
  96. }
  97. for(let fileID of data.oldFileIDs){//通知已打开的项目页面
  98. let messageTitle = data.from == "feeRateFile"?"feeRateChange":"unitFileChange";
  99. socket.broadcast.to(fileID).emit(messageTitle, data);
  100. }
  101. });
  102. // 分享权限变更
  103. socket.on('sharePermissionChange', async function ({ permissionType, userID, compilationID, projectID, emitTenders, payload }) {
  104. const emitPayload = { projectID };
  105. if (payload) {
  106. if (payload.prop) {
  107. payload.prop.updateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
  108. }
  109. Object.assign(emitPayload, payload);
  110. }
  111. // 推送给项目管理页面
  112. socket.broadcast.to(`${userID}@${compilationID}`).emit('sharePermissionChange', { permissionType, target: PageTarget.PM, payload: emitPayload });
  113. // 推送给主页面
  114. for (const tender of emitTenders) {
  115. const emitPayload = {};
  116. if (typeof tender.allowCooperate !== 'undefined') {
  117. emitPayload.allowCooperate = tender.allowCooperate;
  118. }
  119. socket.broadcast.to(`${userID}@${tender.ID}`).emit('sharePermissionChange', { permissionType, target: PageTarget.MAIN, payload: emitPayload });
  120. }
  121. });
  122. // 项目管理树结构变化
  123. socket.on('pmTreeChange', function ({ userID, compilationID, expandState, selection }) {
  124. socket.broadcast.to(`${userID}@${compilationID}`).emit('pmTreeChange', { expandState, selection });
  125. });
  126. socket.on('disconnect', function () {
  127. // 由于用户可以重复打开项目,因此不做唯一性处理,只删除一个数据,不删除所有的同用户数据
  128. if (curProjectID && userCache[curProjectID]) {
  129. const index = userCache[curProjectID].findIndex(user => user._id === curUser._id);
  130. if (index >= 0) {
  131. userCache[curProjectID].splice(index, 1);
  132. if (!userCache[curProjectID].length) {
  133. delete userCache[curProjectID];
  134. }
  135. const editingUsers = getEditingUsers(curProjectID);
  136. socket.broadcast.to(roomInfo.projectID).emit('handleAvatarList', {editingUsers});
  137. socket.emit('handleAvatarList', {editingUsers});
  138. }
  139. }
  140. console.log("client disconnect =========="+JSON.stringify(roomInfo));
  141. });
  142. });