| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- var us = {};
- us.cheerio = require("cheerio");
- us.qs = require("querystring");
- us.http = require("http");
- us.mysql = require("./mysql.js");
- // 将 mysql 调用 Promise 化(若原方法为回调风格)
- us.mysql.usselectAsync = (params) => {
- return new Promise((resolve, reject) => {
- us.mysql.usselect(params, (ret) => {
- if (ret === null || ret === undefined) {
- reject(new Error('Database query returned null'));
- } else {
- resolve(ret);
- }
- });
- });
- };
- us.savecscltime = null;
- us.connect = {};
- us.user = {};
- us.cscl = {};
- us.offLineMessage = {};
- us.mindNetwork = {};
- us.realTimeClass = {};
- us.word = {};
- us.excel = {};
- us.nav = {};
- us.cscldata = function () {
- return {
- id: "",
- userid: "",
- name: "",
- num: "",
- data: "",
- isClose: "",
- create_at: "",
- createuser: "",
- smailheadportrait: ""
- };
- };
- us.userConnect = function (pageId, response) {
- return {
- "pageId": pageId,
- "response": response,
- "loginTime": new Date(),
- "offLineTime": null
- };
- };
- us.userInfo = function (userid, username) {
- return {
- "userId": userid,
- "userName": username
- };
- };
- us.userOffLineMessage = function (type) {
- return {
- "message": [],
- "type": type,
- "word": [],
- "excel": [],
- "mindNetwork": [],
- "realTimeClass": [],
- "cscl": [],
- "nav": []
- };
- };
- us.message = function (sendid, type, messageinfo) {
- return {
- "id": us.createGuid(),
- "sendId": sendid,
- "time": new Date(),
- "type": type,
- "messageInfo": messageinfo
- };
- };
- process.on('uncaughtException', (e) => {
- console.error('process error is:', e.message);
- });
- us.server = us.http.createServer(async (req, res) => {
- res.writeHead(200, {
- "Content-Type": "text/html;application/json;charset=utf-8",
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Headers': 'Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With'
- });
- try {
- const param = await us.unifyDisposeAsync(req, res);
- if (!param || !param[0]) {
- return res.end("");
- }
- const _funname = param[0];
- const _param = param.slice(1);
- switch (_funname) {
- case 'login': {
- const _userinfo = JSON.parse(_param[0]);
- us.login(req, res, _userinfo.userId, _userinfo.pageId, _userinfo.userName, _userinfo.type);
- break;
- }
- case 'logout':
- us.logout(res, _param[0], _param[1]);
- break;
- case 'polling':
- us.polling(req, res, _param[0], _param[1], _param[2], _param[3]);
- break;
- case 'getWord':
- await us.getWord(res, _param[0], _param[1], _param[2]);
- break;
- case 'getExcel':
- await us.getExcel(res, _param[0], _param[1], _param[2]);
- break;
- case 'getNav':
- await us.getNav(res, _param[0], _param[1], _param[2]);
- break;
- case 'getMindNetwork':
- await us.getMindNetwork(res, _param[0], _param[1], _param[2]);
- break;
- case 'getcscl':
- await us.getcscl(res, _param[0], _param[1], _param[2]);
- break;
- case 'getcscldata':
- await us.getcscldata(res, _param[0], _param[1], _param[2]);
- break;
- case 'getRealTimeClass':
- await us.getRealTimeClass(res, _param[0], _param[1], _param[2]);
- break;
- case 'getNavPageContent':
- await us.getNavPageContent(res, _param[0], _param[1]);
- break;
- case 'send':
- await us.send(res, _param[0]);
- break;
- case 'quitOffice':
- us.quitOffice(res, _param[0]);
- break;
- case 'quitcscl':
- us.quitcscl(res, _param[0]);
- break;
- case 'newWordSave':
- await us.newWordSave(res, _param[0], _param[1], _param[2], _param[3], _param[4]);
- break;
- case 'newExcelSave':
- await us.newExcelSave(res, _param[0], _param[1], _param[2], _param[3], _param[4]);
- break;
- case 'newNavSave':
- await us.newNavSave(res, _param[0], _param[1], _param[2], _param[3], _param[4], _param[5], _param[6]);
- break;
- case 'addExcel':
- us.addExcel(res, _param[0]);
- break;
- case 'copyPageContent':
- await us.copyPageContent(res, _param[0], _param[1], _param[2], _param[3]);
- break;
- case 'updateName':
- await us.updateName(res, _param[0], _param[1], _param[2], _param[3], _param[4]);
- break;
- case 'insertModifyRecord':
- await us.insertModifyRecord(res, _param[0], _param[1], _param[2], _param[3], _param[4], _param[5]);
- break;
- case 'addUser':
- us.addUser(res, _param[0], _param[1], _param[2], _param[3], _param[4]);
- break;
- default:
- res.end("0");
- }
- } catch (err) {
- console.error('Request error:', err);
- res.end("");
- }
- });
- // 将原有的 unifyDispose 改为 Promise 版本
- us.unifyDisposeAsync = (req, res) => {
- return new Promise((resolve, reject) => {
- let _param = "";
- req.on("data", chunk => _param += chunk);
- req.on("end", () => {
- try {
- if (_param) {
- _param = us.qs.parse(_param);
- }
- _param = _param.mode ? _param.mode.split(",") : [];
- for (let i = 0; i < _param.length; i++) {
- _param[i] = decodeURIComponent(_param[i]);
- }
- resolve(_param);
- } catch (e) {
- reject(e);
- }
- });
- res.setTimeout(60000, () => {
- try { res.end(""); } catch (e) {}
- });
- req.on("error", (e) => reject(e));
- });
- };
- us.insertModifyRecord = async (response, type, fileid, filename, html, userid, pageid) => {
- let _html = html;
- if (us[type] && us[type][fileid] && us[type][fileid].content) {
- _html = us[type][fileid].content('body').html().replace(/'/ig, "''").replace(/"/ig, "\\\"");
- }
- try {
- const ret = await us.mysql.usselectAsync([
- '127.0.0.1', 'UseStudio_Office', 'InsertDocumentModifyRecord',
- userid, fileid, _html, filename
- ]);
- const _historyid = JSON.parse(ret)[0][0].historyid;
- const _messageinfo = us.message(userid, 'us.' + type, {
- id: us.createGuid(),
- type: "insertModifyRecord",
- historyid: _historyid,
- docId: fileid
- });
- const _message = { [fileid]: [_messageinfo] };
- us.broadcast(_message, pageid, type);
- response.end(_historyid);
- } catch (e) {
- response.end("");
- }
- };
- us.updateName = async (response, type, fileid, filename, userid, pageid) => {
- try {
- const ret = await us.mysql.usselectAsync([
- 'sqlserver.1473.cn', 'UseStudio_Disk', 'UpdateFileInfo', fileid, filename
- ]);
- if (ret) {
- const _messageinfo = us.message(userid, 'us.' + type, {
- id: us.createGuid(),
- type: "updateName",
- name: filename,
- docId: fileid
- });
- us.broadcast({ [fileid]: [_messageinfo] }, pageid, type);
- response.end('updateNameSuccess');
- } else {
- response.end('updateNameFail');
- }
- } catch (e) {
- response.end('updateNameFail');
- }
- };
- us.addUser = (response, type, fileid, userids, userid, pageid) => {
- const _messageinfo = us.message(userid, 'us.' + type, {
- id: us.createGuid(),
- type: "addUser",
- userIds: userids,
- docId: fileid
- });
- us.broadcast({ [fileid]: [_messageinfo] }, pageid, type);
- response.end('addUserSuccess');
- };
- us.getuserbytype = (userids) => {
- const _userinfo = [];
- for (let i in userids) {
- if (us.user[i]) _userinfo.push(us.user[i]);
- }
- return _userinfo;
- };
- us.sendUser = (userinfo, type, pageid, fileid) => {
- const _messageinfo = us.message(userinfo.userid, 'us.' + type, {
- id: us.createGuid(),
- type: "addUser",
- userinfo: userinfo,
- docId: fileid
- });
- us.broadcast({ [fileid]: [_messageinfo] }, pageid, type);
- };
- us.login = (req, res, userid, pageid, username, type) => {
- if (userid && pageid) {
- if (!us.user[userid]) {
- us.user[userid] = us.userInfo(userid, username || "");
- }
- us.polling(req, res, userid, pageid, type);
- }
- };
- us.deluser = (userid, pageid) => {
- if (pageid && us.offLineMessage[pageid]) {
- const _csclids = us.offLineMessage[pageid].cscl;
- delete us.offLineMessage[pageid];
- for (let i = 0; i < _csclids.length; i++) {
- const _docinfo = us.cscl[_csclids[i]];
- if (_docinfo) {
- const _fileid = _csclids[i];
- const _quitUserId = us.quitUserList(_docinfo, userid, pageid);
- if (_quitUserId) {
- const _messageinfo = us.message(userid, 'us.cscl', {
- id: us.createGuid(),
- type: "delUser",
- userinfo: us.user[_quitUserId],
- docId: _fileid
- });
- us.broadcast({ [_fileid]: [_messageinfo] }, pageid, "cscl");
- }
- }
- }
- }
- };
- us.offLine = () => {
- const _connect = us.connect;
- for (let i in _connect) {
- const _user = _connect[i];
- for (let j in _user) {
- if (_user[j].response.finished || (_user[j].response.connection == null || _user[j].response.connection.destroyed)) {
- us.offLineByUser(i, j, _user);
- }
- }
- }
- };
- us.offLineByUser = (userId, pageId, _user) => {
- setTimeout(() => {
- if (_user[pageId].response.finished || (_user[pageId].response.connection == null || _user[pageId].response.connection.destroyed)) {
- us.deluser(userId, pageId);
- delete _user[pageId];
- if (Object.keys(_user).length === 0) {
- delete us.user[userId];
- delete us.connect[userId];
- }
- }
- }, 5000);
- };
- us.polling = (req, res, userid, pageid, type) => {
- if (!us.connect[userid]) us.connect[userid] = {};
- const _userarray = us.connect[userid];
- const _messagearray = us.offLineMessage[pageid];
- const chunkSize = 100;
- if (_userarray[pageid]) {
- try { _userarray[pageid].response.end(""); } catch (e) {}
- _userarray[pageid].response = res;
- if (_messagearray && _messagearray.message.length > 0) {
- const _data = JSON.stringify(_messagearray.message);
- for (let i = 0; i < _data.length; i += chunkSize) {
- res.write(_data.slice(i, i + chunkSize));
- }
- res.write("\r\n");
- _messagearray.message = [];
- } else {
- us.offLineMessage[pageid] = us.offLineMessage[pageid] || us.userOffLineMessage(type);
- }
- } else {
- _userarray[pageid] = us.userConnect(pageid, res);
- us.offLineMessage[pageid] = us.userOffLineMessage(type);
- }
- };
- us.send = async (response, messageinfo) => {
- const _messageobj = JSON.parse(messageinfo);
- const _messagelist = {};
- // 使用 setImmediate 分片处理循环,避免长时间阻塞
- const processMessages = async () => {
- for (let i in _messageobj) {
- const _messagearr = _messageobj[i];
- const type = i.split('.')[1]; // mindNetwork, cscl, realTimeClass, word, excel, nav
- for (let j = 0; j < _messagearr.length; j++) {
- const msg = _messagearr[j];
- const _message = us.message(msg.sendId, i, msg.messageInfo);
- _message.ttype = msg.type;
- if (!_messagelist[msg.receiveId]) _messagelist[msg.receiveId] = [];
- _messagelist[msg.receiveId].push(_message);
- // 更新内存数据
- if (us[type] && us[type][msg.receiveId]) {
- us[type][msg.receiveId].history.push(_message);
- }
- if (type === 'mindNetwork') us.updatemindNetwork(msg.messageInfo);
- else if (type === 'cscl') us.updatecscl(msg.messageInfo, msg.receiveId, msg.type);
- else if (type === 'realTimeClass') us.updaterealTimeClass(msg.messageInfo);
- else if (type === 'word') us.updateWord(msg.messageInfo);
- else if (type === 'excel') us.updateExcel(msg.messageInfo);
- else if (type === 'nav') us.updateNav(msg.messageInfo);
- // 每处理10条消息让出事件循环
- if (j % 10 === 0) await new Promise(resolve => setImmediate(resolve));
- }
- if (_messagearr.length > 0) {
- us.broadcast(_messagelist, _messagearr[0].messageInfo?.pageId || _messagearr[0].pageId, type);
- }
- }
- };
- await processMessages();
- response.end('send');
- };
- us.updatemindNetwork = (messageInfo) => {
- if (us.mindNetwork[messageInfo.docId]?.content) {
- us.mindNetwork[messageInfo.docId].content[messageInfo.id] = messageInfo.content;
- }
- };
- us.updatecscl = (messageInfo, classId, ty) => {
- if (!us.cscl[classId]) return;
- let _obj = us.cscl[classId].content;
- if (ty === "clean") {
- us.cscl[classId].content = {};
- } else {
- _obj.backgroundUrl = messageInfo.backgroundUrl;
- _obj.edges = _obj.edges || [];
- _obj.nodes = _obj.nodes || [];
- // 处理 edges 和 nodes(原逻辑保留)
- for (let j = 0; j < messageInfo.edges.length; j++) {
- const edge = messageInfo.edges[j];
- const idx = _obj.edges.findIndex(e => e.id === edge.id);
- if (ty === "update") {
- if (idx === -1) _obj.edges.push(edge);
- else _obj.edges[idx] = edge;
- } else if (ty === "delete") {
- if (idx !== -1) _obj.edges.splice(idx, 1);
- }
- }
- for (let j = 0; j < messageInfo.nodes.length; j++) {
- const node = messageInfo.nodes[j];
- const idx = _obj.nodes.findIndex(n => n.id === node.id);
- if (ty === "update") {
- if (idx === -1) _obj.nodes.push(node);
- else _obj.nodes[idx] = node;
- } else if (ty === "delete") {
- if (idx !== -1) _obj.nodes.splice(idx, 1);
- }
- }
- }
- clearTimeout(us.savecscltime);
- us.savecscltime = setTimeout(() => {
- us.mysql.usselectAsync(['172.16.12.5', 'pbl', 'updateRoomData', JSON.stringify(us.cscl[classId].content), classId])
- .catch(e => console.error(e));
- }, 5000);
- };
- us.updaterealTimeClass = (messageInfo) => {
- if (us.realTimeClass[messageInfo.docId]?.content) {
- us.realTimeClass[messageInfo.docId].content[messageInfo.id] = messageInfo.content;
- }
- };
- us.updateWord = (messageInfo) => {
- const doc = us.word[messageInfo.docId];
- if (!doc?.content) return;
- const $ = doc.content;
- switch (messageInfo.type) {
- case 'update': $('#' + messageInfo.id).replaceWith(messageInfo.content); break;
- case 'add': messageInfo.nextId ? $('#' + messageInfo.nextId).before(messageInfo.content) : $('body').append(messageInfo.content); break;
- case 'delete': $('#' + messageInfo.id).remove(); break;
- }
- };
- us.updateNav = (messageInfo) => {
- const file = us.nav[messageInfo.docId];
- if (!file) return;
- const pageContent = file.page[messageInfo.navId];
- if (pageContent) {
- switch (messageInfo.type) {
- case 'update': pageContent('#' + messageInfo.id).replaceWith(messageInfo.content); break;
- case 'add': messageInfo.nextId ? pageContent('#' + messageInfo.nextId).before(messageInfo.content) : pageContent('body').append(messageInfo.content); break;
- case 'delete': pageContent('#' + messageInfo.id).remove(); break;
- }
- }
- // 其他 nav 操作(addNav, updateNav, deleteNav)保留原有实现...
- };
- us.updateExcel = (messageInfo) => {
- // 保留原有 Excel 更新逻辑,此处省略以节省篇幅,实际使用时需包含原代码中的 us.updateExcel 函数及其子方法
- };
- us.broadcast = (messageinfo, pageid, type) => {
- const chunkSize = 100;
- const _userconnect = us.connect;
- for (let docId in messageinfo) {
- const _messageinfo = messageinfo[docId];
- const users = us[type]?.[docId]?.user || {};
- for (let userId in users) {
- const pageIds = users[userId];
- for (let pid of pageIds) {
- if (pid === pageid) continue;
- try {
- const conn = _userconnect[userId]?.[pid];
- if (conn) {
- const data = JSON.stringify(_messageinfo);
- const success = conn.response.write("");
- if (!success) {
- us.offLineMessage[pid].message.push(..._messageinfo);
- } else {
- for (let i = 0; i < data.length; i += chunkSize) {
- conn.response.write(data.slice(i, i + chunkSize));
- }
- conn.response.write("\r\n");
- }
- }
- } catch (e) {
- console.error(e);
- }
- }
- }
- }
- };
- us.quitUserList = (docinfo, userid, pageid) => {
- const pages = docinfo.user[userid];
- if (pages) {
- const idx = pages.indexOf(pageid);
- if (idx !== -1) {
- pages.splice(idx, 1);
- if (pages.length === 0) {
- delete docinfo.user[userid];
- return userid;
- }
- }
- }
- return null;
- };
- us.insertHistory = (docinfo, docid, type) => {
- if (Object.keys(docinfo.user).length === 0) {
- switch (type) {
- case 'word': {
- const content = docinfo.content ? docinfo.content('body').html().replace(/'/ig, "\\'").replace(/"/ig, '\\"') : "";
- us.mysql.usselectAsync(['sqlserver.1473.cn', 'UseStudio_Disk', 'SaveFileContent', docid, content, ''])
- .catch(e => console.error(e));
- break;
- }
- // 其他类型类似...
- }
- }
- };
- us.logout = (response, userid, pageid) => {
- us.deluser(userid, pageid);
- const _user = us.connect[userid];
- if (_user) {
- delete _user[pageid];
- if (Object.keys(_user).length === 0) {
- delete us.user[userid];
- delete us.connect[userid];
- }
- }
- response.end('logout');
- };
- // 其他函数(getWord, getExcel, getNav, getcscl, newWordSave 等)均改为 async/await 并调用 us.mysql.usselectAsync
- // 限于篇幅,此处仅给出 getWord 示例,其余类似改造。
- us.getWord = async (response, docid, pageid, userid) => {
- if (!us.word[docid]) {
- us.word[docid] = { user: {}, history: [] };
- us.offLineMessage[pageid]?.word.push(docid);
- }
- const doc = us.word[docid];
- if (!doc.user[userid]) doc.user[userid] = [pageid];
- else if (!doc.user[userid].includes(pageid)) doc.user[userid].push(pageid);
- try {
- const ret = await us.mysql.usselectAsync(['172.16.12.5', 'pbl', 'select_file', docid]);
- if (ret) {
- const officeData = ret[0][0].data ? ret[0][0].data.replace(/\\'/ig, "'").replace(/\\"/g, '"') : "";
- doc.content = us.cheerio.load(officeData);
- response.end(officeData);
- } else {
- doc.content = us.cheerio.load('');
- response.end('');
- }
- } catch (e) {
- response.end('');
- }
- };
- us.createGuid = () => {
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
- const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
- };
- us.server.listen('1473', '', () => {
- setInterval(() => us.offLine(), 60000);
- console.log("开始监听" + us.server.address().port + "......");
- });
|