commit 21bcbf78f86a4752a8427618323a7fdce7956da2 Author: qubiaobiao <3294694717@qq.com> Date: Fri Mar 27 17:57:44 2026 +0800 卫星通信服务平台 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..4ebc8ae --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +coverage diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..f304bdd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,4 @@ +{ + "extends": "eslint-config-egg", + "root": true +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..652759b --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +logs/ +npm-debug.log +yarn-error.log +node_modules/ +*-lock.json +*-lock.yaml +yarn.lock +coverage/ +.idea/ +run/ +.DS_Store +*.sw* +*.un~ +typings/ +.nyc_output/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6490747 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# tqxz-sn-message-platform + + + +## QuickStart + + + +see [egg docs][egg] for more detail. + +### Development + +```bash +npm i +npm run dev +open http://localhost:7001/ +``` + +### Deploy + +```bash +npm start +npm stop +``` + +### npm scripts + +- Use `npm run lint` to check code style. +- Use `npm test` to run unit test. + +[egg]: https://eggjs.org diff --git a/app/controller/home.js b/app/controller/home.js new file mode 100644 index 0000000..1ff827a --- /dev/null +++ b/app/controller/home.js @@ -0,0 +1,464 @@ +const { Controller } = require('egg'); + +const GBK = require("gbk.js"); + +const decode = (data) => { + let arr = []; + data.match(/..?/g).forEach((element) => { + arr.push(parseInt(element, 16)); + }); + return GBK.decode(arr); +} + +const CryptoJS = require("crypto-js"); + +const KEY = CryptoJS.enc.Utf8.parse('BDQH'); + +const decryptRequest = (body) => { + return CryptoJS.AES.decrypt(body, KEY, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }).toString(CryptoJS.enc.Utf8); +} + +const checkUid = async (ctx) => { + const uid = ctx.request.body.uid; + const token = ctx.request.header.authorization; + const redis = ctx.app.redis; + let rdmcode; + if (!uid) { + const [buser, cuser, tuser] = await Promise.all([ + redis.get('db0').get(token), + redis.get('db1').get(token), + redis.get('db5').get(token), + ]); + rdmcode = buser || cuser || tuser; + } else { + let decryptUid = decryptRequest(uid).split('?')[0]; + const redisType = { + "B": "db0", + "C": "db1", + "T": "db5", + }; + const lastCode = decryptUid[decryptUid.length - 1]; + rdmcode = await redis.get(redisType[lastCode]).get(token); + } + if (!rdmcode) { + return false; + } + return rdmcode; +}; + +const fileName = "home"; + +const setResponse = (ctx, code, msg, model, data = {}) => { + const modelType = { + "none": { code, msg }, + "deconstruction": { code, msg, ...data }, + "polymerization": { code, msg, data } + } + ctx.body = modelType[model]; +} + +class HomeController extends Controller { + // 获取SN号 + async getSN() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const result = await ctx.service.home.getSN(uid); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + const data = { snNumber: result.dataValues.sn_number }; + setResponse(ctx, 200, '获取SN号成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '获取SN号失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "getSN"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 搜索SN号 + async searchSN() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const { snNumber } = ctx.request.body; + const result = await ctx.service.home.searchSN(snNumber); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + if (result.dataValues.cuser == null) { + setResponse(ctx, 201, '此SN号未绑定', "deconstruction", result); + } else if (result.dataValues.cuser == uid) { + setResponse(ctx, 202, '此SN号已与当前账号绑定', "none"); + } else { + setResponse(ctx, 203, '此SN号已绑定', "none"); + } + } else { + setResponse(ctx, 404, '此SN号未注册', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "searchSN"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 搜索可绑定的SN号 + async searchBindSN() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const result = await ctx.service.home.searchBindSN(uid); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + const data = { + result + } + setResponse(ctx, 200, '获取可绑定的SN号成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '获取可绑定的SN号失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "searchBindSN"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 搜索可绑定的单位用户 + async searchBindUser() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const result = await ctx.service.home.searchBindUser(uid); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + const data = { + result + } + setResponse(ctx, 200, '获取可绑定的单位用户成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '获取可绑定的单位用户失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "searchBindUser"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 绑定SN号 + async bindSN() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const body = ctx.request.body; + const result = await ctx.service.home.bindSN(uid, body); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + setResponse(ctx, 200, '绑卡成功', "none"); + } else { + setResponse(ctx, 404, '绑卡失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "bindSN"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 解绑SN号 + async unBindingSN() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const body = ctx.request.body; + const result = await ctx.service.home.unBindingSN(uid, body); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + setResponse(ctx, 200, '解绑成功', "none"); + } else { + setResponse(ctx, 404, '解绑失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "unBindingSN"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 获取绑定记录 + async getRecord() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const body = ctx.request.body; + const result = await ctx.service.home.getRecord(uid, body); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + let recordMsg = []; + result.rows.forEach(element => { + recordMsg.push(element.dataValues); + }); + const data = { + recordMsg: recordMsg, + count: result.count + }; + setResponse(ctx, 200, '绑定记录查询成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '绑定记录查询失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "getRecord"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 存储消息记录 + async shortMsg() { + const ctx = this.ctx; + try { + const body = ctx.request.body; + console.log(body) + const { sn_number, original_msg, msg_data, created_at } = body; + const form = { + sn_number: sn_number, + original_msg: original_msg, + msg_data: msg_data, + created_at: created_at + }; + const result = await ctx.service.home.shortMsg(form); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + setResponse(ctx, 200, '消息记录存储成功', "none"); + } else { + setResponse(ctx, 404, '消息记录存储失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "shortMsg"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 获取历史消息 + async getHistoryMsg() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const body = ctx.request.body; + const result = await ctx.service.home.getHistoryMsg(uid, body); + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + let historyMsg = []; + result.rows.forEach(element => { + historyMsg.push(element.dataValues); + }); + const data = { + historyMsg: historyMsg, + count: result.count + }; + setResponse(ctx, 200, '历史消息查找成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '历史消息查找失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "getHistoryMsg"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 删除历史消息 + async delHistoryMsg() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + const body = ctx.request.body; + const model = decryptRequest(body.model); + const password = decryptRequest(body.password); + const requestMsg = body.userMsg; + const resetList = await ctx.service.home.delHistoryMsg(uid, model, password, requestMsg); + if(resetList == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (resetList) { + setResponse(ctx, 200, '删除历史消息成功', "none"); + } else { + setResponse(ctx, 404, '删除历史消息失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "delHistoryMsg"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + /** + * 将sequelize查询结果转换为普通对象数组 + * @param {Array} rows - sequelize查询结果行 + * @returns {Array} 转换后的普通对象数组 + */ + transformBsideUsers(rows) { + let bsideUsers = []; + rows.forEach(element => { + bsideUsers.push(element.dataValues); + }); + return bsideUsers; + } + + // 获取单位用户 + async bsideUserManager() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + let result; + if(uid[uid.length - 1] == 'B') { + const body = ctx.request.body; + result = await ctx.service.home.bsideUserManager(uid, body); + } + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + const bsideUsers = this.transformBsideUsers(result.rows); + const data = { + bsideUsers: bsideUsers, + count: result.count + }; + setResponse(ctx, 200, '获取单位用户成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '获取单位用户失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "bsideUserManager"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } + + // 获取可管理的SN号 + async bsideSNManager() { + const ctx = this.ctx; + try { + let rdmcode = await checkUid(ctx); + if (!rdmcode) { + setResponse(ctx, 401, 'token过期或错误', "none"); + return; + } + const uid = JSON.parse(rdmcode).uid; + let result; + if(uid[uid.length - 1] == 'B') { + const body = ctx.request.body; + result = await ctx.service.home.bsideSNManager(uid, body); + } + if(result == "error") { + setResponse(ctx, 500, '服务器错误', "none"); + return; + } + if (result) { + let snArr = []; + result.forEach(element => { + snArr.push(element.dataValues); + }); + const data = { + count: result.length, + bsideSN: snArr, + }; + setResponse(ctx, 200, '获取可管理的SN号成功', "deconstruction", data); + } else { + setResponse(ctx, 404, '获取可管理的SN号失败', "none"); + } + } catch (error) { + const blockName = fileName + "--" + "bsideSNManager"; + ctx.app.middleware.utils.log('../../../controllerLog', blockName + ">>>>" + error); + setResponse(ctx, 500, '服务器错误', "none"); + } + } +} + +module.exports = HomeController; diff --git a/app/core/base_service.js b/app/core/base_service.js new file mode 100644 index 0000000..8a79e50 --- /dev/null +++ b/app/core/base_service.js @@ -0,0 +1,50 @@ +const { Service } = require('egg'); + +const sha256 = require("crypto-js/sha256"); + +const CryptoJS = require("crypto-js"); + +const KEY = CryptoJS.enc.Utf8.parse('BDQH'); + +class BaseService extends Service { + shaForm = (body, salt) => { + return sha256(sha256(body).toString() + salt).toString(); + } + + encryptRequest = (body) => { + return CryptoJS.AES.encrypt(body, KEY, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }).toString(); + } + + decryptRequest = (body) => { + return CryptoJS.AES.decrypt(body, KEY, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }).toString(CryptoJS.enc.Utf8); + } + + opOptions = (attributes, searchOptions, substring, key, between, sortOptions) => { + let where = {}, order = []; + attributes.forEach(element => { + if (searchOptions[element]) { + if (substring.includes(element)) { + where[element] = { [Op.substring]: searchOptions[element] }; + } else if (key.includes(element)) { + where[element] = searchOptions[element]; + } else if (between.includes(element)) { + where[element] = { [Op.between]: [searchOptions[element][0], searchOptions[element][1]] }; + } + } + if (!sortOptions[element]) { + order.push([element, 'DESC']); + } else if (sortOptions[element]) { + order.push([element, 'ASC']); + } + }); + return { where, order } + } +} + +module.exports = BaseService; \ No newline at end of file diff --git a/app/middleware/shunt/socketEmitter.js b/app/middleware/shunt/socketEmitter.js new file mode 100644 index 0000000..815eca4 --- /dev/null +++ b/app/middleware/shunt/socketEmitter.js @@ -0,0 +1,8 @@ +// socket事件监听器 +const EventEmitter = require('events'); + +const socketEmitter = new EventEmitter(); + +module.exports = () => { + return socketEmitter; +}; \ No newline at end of file diff --git a/app/middleware/socket/socketServer.js b/app/middleware/socket/socketServer.js new file mode 100644 index 0000000..f45d33f --- /dev/null +++ b/app/middleware/socket/socketServer.js @@ -0,0 +1,68 @@ +const net = require('net'); + +module.exports = (app) => { + const { middleware } = app; + const shunt = middleware.shunt; + + net.createServer(function (socket) { + socket.on('lookup', function (data) { + console.log(data); + console.log('lookup') + }); + socket.on('connection', function (data) { + console.log(data); + console.log('socket客户端已连接'); + }); + socket.on('data', async function (data) { + let value = data.toString('hex'); + console.log(value); + let response = "000000068100"; + socket.write(Buffer.from(response, 'hex')); + // 00000043010000000000000000000000000000000000000000 18 31353037365f32303236303330333135313835315f323832 00 0f 0102030405060708090a0b0c0d0e0f + let sn_value = value.slice(52, 100), + snBuffer = Buffer.from(sn_value, 'hex'), + snNumber = snBuffer.toString('ascii').split("_")[0], + msg_value = value.slice(104, value.length), + msgBuffer = Buffer.from(msg_value, 'hex'), + msgData = msgBuffer.toString('ascii'); + console.log(msgData) + // socket接收消息后触发事件监听器,将消息发送给websocket客户端并存储在数据库中 + shunt.socketEmitter().emit(snNumber, { msg_data: msgData, created_at: new Date() }); + await app.curl('http://127.0.0.1:' + app.server.address().port + '/shortMsg', { + dataType: 'json', + contentType: 'application/x-www-form-urlencoded', + method: 'POST', + timeout: 3000, + data: { + sn_number: snNumber, + original_msg: value, + msg_data: msgData, + created_at: new Date() + }, + }); + }); + socket.on('end', function (data) { + console.log(data); + console.log('end'); + }); + socket.on('timeout', function (data) { + console.log(data); + console.log('空闲超时'); + }); + socket.on('drain', function (data) { + console.log(data); + console.log('写缓存为空'); + }); + socket.on('error', function (data) { + console.log(data); + console.log('发生错误'); + }); + socket.on('close', function (data) { + console.log(data); + console.log('socket客户端已断开连接'); + }); + socket.pipe(socket); + }).listen(8100, function () { + console.log('socket服务器已启动,监听端口:8100'); + }); +} \ No newline at end of file diff --git a/app/middleware/utils/log.js b/app/middleware/utils/log.js new file mode 100644 index 0000000..6d7323a --- /dev/null +++ b/app/middleware/utils/log.js @@ -0,0 +1,72 @@ +// 错误日志 +const fs = require('fs'); +const os = require('os'); +const path = require('path'); + +const dirCheck = (dirPath) => { + // 检查文件夹是否存在 + fs.access(dirPath, fs.constants.F_OK, (err) => { + if (err) { + // 文件夹不存在 + console.log('文件夹不存在,正在创建...'); + fs.mkdir(dirPath, { recursive: true }, (err) => { + if (err) throw err; + console.log('文件夹已创建'); + }); + } else { + // 文件夹存在 + console.log('文件夹已存在'); + } + }); +} + +module.exports = (filePath, msg) => { + // 获取时间 + let now = new Date(), + times = { + year: now.getFullYear(), + month: now.getMonth() + 1, + day: now.getDate(), + hour: now.getHours(), + minute: now.getMinutes(), + second: now.getSeconds() + }; + // 获取操作系统类型 + const type = os.type(); + console.log(`操作系统类型: ${type}`); + filePath = path.join(__dirname, filePath); + dirCheck(filePath); + const yearPath = filePath + '/' + times.year; + dirCheck(yearPath); + const monthPath = yearPath + '/' + times.month; + dirCheck(monthPath); + const dayPath = monthPath + '/' + times.day + '.txt'; + const logTime = '[' + times.year + '-' + times.month + '-' + times.day + '>>>' + times.hour + ':' + times.minute + ':' + times.second + ']' + '>>>'; + let crlf; + // 判断操作系统类型,设置换行符 + if (type === 'Windows_NT') { + crlf = '\n'; + } else { + crlf = '\r\n'; + } + // 读取文件内容 + fs.readFile(dayPath, 'utf8', (err, data) => { + if (err) { + if (err.code === 'ENOENT') { + // 文件不存在,直接写入新内容(这里实际上还是使用了覆盖的方式) + fs.writeFile(dayPath, logTime + msg + crlf, (err) => { + if (err) throw err; + console.log('文件已创建并写入新内容'); + }); + } else { + throw err; + } + } else { + // 文件存在,追加新内容 + fs.appendFile(dayPath, logTime + msg + crlf, (err) => { + if (err) throw err; + console.log('新内容已追加到文件'); + }); + } + }); +}; \ No newline at end of file diff --git a/app/middleware/webSocket/webSocketServer.js b/app/middleware/webSocket/webSocketServer.js new file mode 100644 index 0000000..a07e4a9 --- /dev/null +++ b/app/middleware/webSocket/webSocketServer.js @@ -0,0 +1,47 @@ +// webSocket服务端 +const http = require('http'); +const { Server } = require('socket.io'); + +module.exports = (app) => { + // 创建HTTP服务器并监听8110端口 + const server = http.createServer(function (req, res) { + if (req.url === '/') { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.end('Hello World!'); + } + }).listen(app.config.webSocketServer.port); + + let io = new Server(server, { + cors: { + origin: app.config.webSocketServer.allowedOrigins, // 生产环境应指定具体域名 + methods: ["GET", "POST"] + }, + // path: app.config.webSocketServer.path, + transports: ['websocket', 'polling'], + connectionStateRecovery: {} + }); + + console.log(`websocket: ${ app.config.webSocketServer.ip }服务器已启动,监听端口:${ app.config.webSocketServer.port }`); + + const socketEmitter = app.middleware.shunt.socketEmitter(); + const utils = app.middleware.utils; + + io.on('connection', (socket) => { + socket.on('message', (snNumber) => { + if(socketEmitter.listeners(snNumber).length !== 0) { + socketEmitter.removeAllListeners(snNumber); + }; + socketEmitter.on(snNumber, (msg) => { + socket.emit(snNumber, msg); + }); + }); + }); + + io.on('error', (err) => { + utils.log('../../webSocketLog', err); + io = new Server(app.config.webSocketServer.port, { + cors: true, + connectionStateRecovery: {} + }); + }); +}; \ No newline at end of file diff --git a/app/model/BSNMsg.js b/app/model/BSNMsg.js new file mode 100644 index 0000000..f8da667 --- /dev/null +++ b/app/model/BSNMsg.js @@ -0,0 +1,21 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, TEXT, DATE } = app.Sequelize; + + const BSNMsg = app.model.define('bsn-msg', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + original_msg: TEXT, + msg_data: TEXT, + created_at: DATE + }, { + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false + }); + + return BSNMsg; +}; \ No newline at end of file diff --git a/app/model/BSide.js b/app/model/BSide.js new file mode 100644 index 0000000..726431c --- /dev/null +++ b/app/model/BSide.js @@ -0,0 +1,30 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, DATE } = app.Sequelize; + + const BSide = app.model.define('b-side', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + uid: CHAR(15), + salt: CHAR(24), + status: INTEGER(3), + role: INTEGER(3), + account_name: STRING(20), + password: CHAR(64), + organization: CHAR(16), + user_name: STRING(20), + phone: CHAR(11), + msg: STRING(300), + created_at: DATE, + updated_at: DATE, + login_at: DATE, + login_status: INTEGER(3) + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: true, + }); + + return BSide; +}; \ No newline at end of file diff --git a/app/model/BindBSNrecord.js b/app/model/BindBSNrecord.js new file mode 100644 index 0000000..06c4497 --- /dev/null +++ b/app/model/BindBSNrecord.js @@ -0,0 +1,20 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, DATE } = app.Sequelize; + + const BindBSNrecord = app.model.define('bind-bsnrecord', { + id: { type: INTEGER(11), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + type: INTEGER(1), + created_at: DATE, + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false, + }); + + return BindBSNrecord; +}; \ No newline at end of file diff --git a/app/model/BuserSNAdmin.js b/app/model/BuserSNAdmin.js new file mode 100644 index 0000000..12c9528 --- /dev/null +++ b/app/model/BuserSNAdmin.js @@ -0,0 +1,19 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, TEXT } = app.Sequelize; + + const BuserSNAdmin = app.model.define('buser-snadmin', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + length: INTEGER(3), + sn_set: TEXT, + },{ + freezeTableName: true, + timestamp: true, + createdAt: false, + updatedAt: false, + }); + + return BuserSNAdmin; +}; \ No newline at end of file diff --git a/app/model/BuserSNBind.js b/app/model/BuserSNBind.js new file mode 100644 index 0000000..c167ce4 --- /dev/null +++ b/app/model/BuserSNBind.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING } = app.Sequelize; + + const BuserSNBind = app.model.define('buser-snbind', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + },{ + freezeTableName: true, + timestamp: true, + createdAt: false, + updatedAt: false, + }); + + return BuserSNBind; +}; \ No newline at end of file diff --git a/app/model2/BindCSNrecord.js b/app/model2/BindCSNrecord.js new file mode 100644 index 0000000..3097a23 --- /dev/null +++ b/app/model2/BindCSNrecord.js @@ -0,0 +1,20 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, DATE } = app.Sequelize; + + const BindCSNrecord = app.model.define('bind-csnrecord', { + id: { type: INTEGER(11), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + type: INTEGER(1), + created_at: DATE, + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false, + }); + + return BindCSNrecord; +}; \ No newline at end of file diff --git a/app/model2/CSNMsg.js b/app/model2/CSNMsg.js new file mode 100644 index 0000000..768bcb5 --- /dev/null +++ b/app/model2/CSNMsg.js @@ -0,0 +1,21 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, TEXT, DATE } = app.Sequelize; + + const CSNMsg = app.model2.define('csn-msg', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + original_msg: TEXT, + msg_data: TEXT, + created_at: DATE, + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false, + }); + + return CSNMsg; +}; \ No newline at end of file diff --git a/app/model2/CSide.js b/app/model2/CSide.js new file mode 100644 index 0000000..373eec9 --- /dev/null +++ b/app/model2/CSide.js @@ -0,0 +1,34 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, DATE } = app.Sequelize; + + const CSide = app.model2.define('c-side', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + uid: CHAR(15), + salt: CHAR(24), + status: INTEGER(3), + role: INTEGER(3), + avatar: CHAR(15), + account_name: STRING(20), + password: CHAR(64), + user_name: STRING(20), + phone: CHAR(11), + gender: INTEGER(1), + age: INTEGER(3), + email: STRING(254), + address: STRING(300), + post_code: CHAR(6), + created_at: DATE, + updated_at: DATE, + login_at: DATE, + login_status: INTEGER(3) + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: true, + }); + + return CSide; +}; \ No newline at end of file diff --git a/app/model2/CuserSNBind.js b/app/model2/CuserSNBind.js new file mode 100644 index 0000000..a4dbc57 --- /dev/null +++ b/app/model2/CuserSNBind.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING } = app.Sequelize; + + const CuserSNBind = app.model2.define('cuser-snbind', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + },{ + freezeTableName: true, + timestamp: true, + createdAt: false, + updatedAt: false, + }); + + return CuserSNBind; +}; \ No newline at end of file diff --git a/app/model3/SNNumber.js b/app/model3/SNNumber.js new file mode 100644 index 0000000..5298db5 --- /dev/null +++ b/app/model3/SNNumber.js @@ -0,0 +1,20 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, STRING, DATE } = app.Sequelize; + + const SNNumber = app.model3.define('sn-number', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + sn_number: STRING(8), + status: INTEGER(3), + created_at: DATE, + updated_at: DATE, + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: true, + }); + + return SNNumber; +}; \ No newline at end of file diff --git a/app/model4/Account.js b/app/model4/Account.js new file mode 100644 index 0000000..1aaf39b --- /dev/null +++ b/app/model4/Account.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, DATE } = app.Sequelize; + + const Account = app.model4.define('account', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + uid: CHAR(15), + salt: CHAR(24), + contest_uid: CHAR(15), + account_name: STRING(20), + password: CHAR(64), + status: INTEGER(3), + created_at: DATE, + login_status: INTEGER(3) + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false, + }); + + return Account; +}; \ No newline at end of file diff --git a/app/model4/TSNMsg.js b/app/model4/TSNMsg.js new file mode 100644 index 0000000..1458bc1 --- /dev/null +++ b/app/model4/TSNMsg.js @@ -0,0 +1,21 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING, TEXT, DATE } = app.Sequelize; + + const TSNMsg = app.model4.define('tsn-msg', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + original_msg: TEXT, + msg_data: TEXT, + created_at: DATE, + },{ + freezeTableName: true, + timestamp: true, + createdAt: true, + updatedAt: false, + }); + + return TSNMsg; +}; \ No newline at end of file diff --git a/app/model4/TuserSNBind.js b/app/model4/TuserSNBind.js new file mode 100644 index 0000000..5e672ba --- /dev/null +++ b/app/model4/TuserSNBind.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = (app) => { + const { INTEGER, CHAR, STRING } = app.Sequelize; + + const TuserSNBind = app.model4.define('tuser-snbind', { + id: { type: INTEGER(8), primaryKey: true, autoIncrement: true }, + user_uid: CHAR(15), + sn_number: STRING(8), + },{ + freezeTableName: true, + timestamp: true, + createdAt: false, + updatedAt: false, + }); + + return TuserSNBind; +}; \ No newline at end of file diff --git a/app/router.js b/app/router.js new file mode 100644 index 0000000..4300bdf --- /dev/null +++ b/app/router.js @@ -0,0 +1,41 @@ +/** + * @param {Egg.Application} app - egg application + */ +module.exports = app => { + const { router, controller, middleware } = app; + + setTimeout(() => { + // 启动socket服务端 + middleware.socket.socketServer(app); + }, 8000); + + setTimeout(() => { + // 启动webSocket服务端 + middleware.webSocket.webSocketServer(app); + }, 16000); + + // 获取SN号 + router.post('/getSN', controller.home.getSN); + // 搜索SN号 + router.post('/searchSN', controller.home.searchSN); + // 搜索可绑定的SN号 + router.get('/searchBindSN', controller.home.searchBindSN); + // 搜索可绑定的单位用户 + router.get('/searchBindUser', controller.home.searchBindUser); + // 绑定SN号 + router.post('/bindSN', controller.home.bindSN); + // 解绑SN号 + router.post('/unBindingSN', controller.home.unBindingSN); + // 获取绑定记录 + router.post('/getRecord', controller.home.getRecord); + // 存储消息记录 + router.post('/shortMsg', controller.home.shortMsg); + // 获取历史消息 + router.post('/getHistoryMsg', controller.home.getHistoryMsg); + // 删除历史消息 + router.post('/delHistoryMsg', controller.home.delHistoryMsg); + // 获取单位用户 + router.post('/bsideUserManager', controller.home.bsideUserManager); + // 获取可管理的SN号 + router.post('/bsideSNManager', controller.home.bsideSNManager); +}; diff --git a/app/service/home.js b/app/service/home.js new file mode 100644 index 0000000..73d5d2f --- /dev/null +++ b/app/service/home.js @@ -0,0 +1,442 @@ +'use strict'; + +const Service = require('../core/base_service'); + +const { Op } = require('sequelize'); + +const shunt = (uid) => { + return uid[uid.length - 1]; +}; + +const fileName = 'home'; + +class HomeService extends Service { + // 获取SN号 + async getSN(uid) { + const { ctx } = this; + try { + const where = { user_uid: uid }; + const uidLastCode = shunt(uid); + const model = { + "B": ctx.model.BuserSNBind, + "C": ctx.model2.CuserSNBind, + "T": ctx.model4.TuserSNBind, + }; + const result = await model[uidLastCode].findOne({ where }); + return result || false; + } catch (error) { + const blockName = fileName + "--" + "getSN"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 搜索SN号 + async searchSN(snNumber) { + const { ctx } = this; + try { + const where = { sn_number: snNumber }; + const result = await ctx.model3.SNNumber.findOne({ where }); + return result || false; + } catch (error) { + const blockName = fileName + "--" + "searchSN"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 搜索可绑定的SN号 + async searchBindSN(uid) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + const resultAdminSN = await ctx.model.BuserSNAdmin.findOne({ attributes: ['sn_set'], where: { user_uid: uid } }); + if (!resultAdminSN) return false; + const adminSN = []; + resultAdminSN.sn_set.split(',').forEach(element => { + adminSN.push(element); + }); + const where = { sn_number: { [Op.in]: adminSN }, status: 4 }; + const resultBindSN = await ctx.model3.SNNumber.findAll({ attributes: ['sn_number'], where }); + if (resultBindSN.length == 0) return false; + const bindSN = []; + resultBindSN.forEach(element => { + bindSN.push(element.dataValues.sn_number); + }); + const resultData = adminSN.filter(item => bindSN.includes(item)); + return resultData; + } catch (error) { + const blockName = fileName + "--" + "searchBindSN"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 搜索可绑定的单位用户 + async searchBindUser(uid) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + const resultAdminUser = await ctx.model.BSide.findAll({ attributes: ['uid', 'account_name'], where: { status: { [Op.not]: 2 }, organization: result.organization } }); + const uidArr = []; + resultAdminUser.forEach(element => { + uidArr.push(element.dataValues.uid); + }); + const where = { user_uid: { [Op.in]: uidArr } }; + const resultBindUser = await ctx.model.BuserSNBind.findAll({ attributes: ['user_uid'], where }); + if (resultBindUser.length == 0) return resultAdminUser; + const adminUser = []; + resultAdminUser.forEach(element => { + adminUser.push(element.dataValues); + }); + const bindUser = []; + resultBindUser.forEach(element => { + bindUser.push(element.dataValues); + }); + const resultData = []; + resultAdminUser.forEach(item => { + resultBindUser.forEach(element => { + if (item.dataValues.uid !== element.dataValues.user_uid) { + resultData.push(item); + } + }); + }); + return resultData; + } catch (error) { + const blockName = fileName + "--" + "searchBindUser"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 绑定SN号 + async bindSN(uid, body) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + const { snNumber, userUid } = body; + const where = { sn_number: snNumber }; + const sn = await ctx.model3.SNNumber.findOne({ where }); + if (!sn) return false; + const model = { + "B": ctx.model.BuserSNBind, + "C": ctx.model2.CuserSNBind, + "T": ctx.model2.TuserSNBind + }; + const uidLastCode = shunt(userUid); + const bindCheck = await model[uidLastCode].findOne({ where: { user_uid: userUid } }); + if (bindCheck) return false; + if (shunt(userUid) == 'B' && sn.status !== 4 || shunt(userUid) !== 'B' && sn.status !== 0) { + return false; + } else { + const status = shunt(userUid) == 'B' ? 1 : shunt(userUid) == 'C' ? 2 : 3; + const snResult = await ctx.model3.SNNumber.update({ status }, { where }); + const bindForm = { + user_uid: userUid, + sn_number: snNumber + }; + const resultForm = { + user_uid: userUid, + sn_number: snNumber, + type: 1, + created_at: new Date() + }; + const modelName = { + "B": ctx.model.BindBSNrecord, + "C": ctx.model2.BindCSNrecord + }; + const bindResult = await model[uidLastCode].create(bindForm); + const recordResult = await modelName[uidLastCode].create(resultForm); + return snResult[0] && bindResult && recordResult ? true : false; + } + } catch (error) { + const blockName = fileName + "--" + "bindSN"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 解绑SN号 + async unBindingSN(uid, body) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + const { snNumber, userUid } = body; + const snWhere = { sn_number: snNumber }; + const snResult = await ctx.model3.SNNumber.update({ status: 0 }, { where: snWhere }); + if (snResult[0] !== 0) { + const where = { + user_uid: userUid, + sn_number: snNumber + }; + const form = { + user_uid: userUid, + sn_number: snNumber, + type: 0, + created_at: new Date() + }; + const uidLastCode = shunt(userUid); + const model = { + "B": ctx.model.BuserSNBind, + "C": ctx.model2.CuserSNBind, + "T": ctx.model2.TuserSNBind, + }; + const modelName = { + "B": ctx.model.BindBSNrecord, + "C": ctx.model2.BindCSNrecord + }; + const bindResult = await model[uidLastCode].destroy({ where }); + const recordResult = await modelName[uidLastCode].create(form); + return bindResult && recordResult ? true : false; + } else { + return false; + } + } catch (error) { + const blockName = fileName + "--" + "unBindingSN"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 获取绑定记录 + async getRecord(uid, body) { + const { ctx } = this; + try { + let { offset, limit, searchOptions, sortOptions } = body; + offset = (offset - 1) * limit; + let attributes = ['user_uid', 'sn_number', 'type', 'created_at'], + where = { user_uid: uid }, order = [], dbOptions, joinSubstring = [], + substring = ['user_uid', 'sn_number'], key = ['type'], between = ['created_at']; + const uidLastCode = shunt(uid); + attributes.forEach(element => { + if (searchOptions[element]) { + if(searchOptions[element] == '*空') { + if(joinSubstring.includes(element)) { + where[element] = null; + } else { + where[element] = [null, '']; + } + } else if(substring.includes(element)) { + where[element] = { [Op.substring]: searchOptions[element] }; + } else if (key.includes(element)) { + where[element] = searchOptions[element] == "1" ? uidLastCode === 'B' ? 1 : 2 : 0; + } else if (between.includes(element)) { + where[element] = { [Op.between]: [searchOptions[element][0], searchOptions[element][1]] }; + } + } + if (sortOptions[element] == true) { + order.push([element, 'ASC']); + } else if (sortOptions[element] == false) { + order.push([element, 'DESC']); + } + }); + dbOptions = { attributes, offset, limit, where, order }; + const model = { + "B": ctx.model.BSide, + "C": ctx.model2.CSide, + }; + const modelName = { + "B": ctx.model.BindBSNrecord, + "C": ctx.model2.BindCSNrecord, + }; + const user = await model[uidLastCode].findAll({ attributes: ['uid', 'account_name'] }); + const result = await modelName[uidLastCode].findAndCountAll(dbOptions); + result.rows.forEach(element => { + element.dataValues.account_name = ''; + user.filter(item => { + if (item.dataValues.uid == element.dataValues.user_uid) { + element.dataValues.account_name = item.dataValues.account_name; + } + }); + }); + return result.rows.length == 0 ? false : result; + } catch (error) { + const blockName = fileName + "--" + "getRecord"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 存储消息记录 + async shortMsg(form) { + const { ctx } = this; + try { + const where = { sn_number: form.sn_number }; + const SN = await ctx.model3.SNNumber.findOne({ where }); + if (!SN) { + ctx.app.middleware.utils.log('../../../unknownSNLog', form); + return false; + }; + const model = { + 1: ctx.model.BuserSNBind, + 2: ctx.model2.CuserSNBind, + 3: ctx.model4.TuserSNBind, + }; + const bind = await model[SN.dataValues.status].findOne({ where }); + if (!bind) return false; + form.user_uid = bind.dataValues.user_uid; + const uidLastCode = shunt(form.user_uid); + const modelName = { + "B": ctx.model.BSNMsg, + "C": ctx.model2.CSNMsg, + "T": ctx.model4.TSNMsg, + }; + const result = await modelName[uidLastCode].create(form); + return result || false; + } catch (error) { + const blockName = fileName + "--" + "shortMsg"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 获取历史消息 + async getHistoryMsg(uid, body) { + const { ctx } = this; + try { + let { offset, limit, searchOptions, sortOptions } = body; + offset = (offset - 1) * limit; + let attributes = ['original_msg', 'sn_number', 'msg_data', 'created_at'], + where = { user_uid: uid }, order = [], dbOptions, joinSubstring = [], + substring = ['original_msg', 'sn_number', 'msg_data'], key = [], between = ['created_at']; + attributes.forEach(element => { + if (searchOptions[element]) { + if(searchOptions[element] == '*空') { + if(joinSubstring.includes(element)) { + where[element] = null; + } else { + where[element] = [null, '']; + } + } else if (substring.includes(element)) { + where[element] = { [Op.substring]: searchOptions[element] }; + } else if (key.includes(element)) { + where[element] = searchOptions[element] == "1" ? true : false; + } else if (between.includes(element)) { + where[element] = { [Op.between]: [searchOptions[element][0], searchOptions[element][1]] }; + } + } + if (sortOptions[element] == true) { + order.push([element, 'ASC']); + } else if (sortOptions[element] == false) { + order.push([element, 'DESC']); + } + }); + dbOptions = { attributes, offset, limit, where, order }; + const uidLastCode = shunt(uid); + const model = { + "B": ctx.model.BSNMsg, + "C": ctx.model2.CSNMsg, + "T": ctx.model4.TSNMsg, + }; + const result = await model[uidLastCode].findAndCountAll(dbOptions); + return result.rows.length == 0 ? false : result; + } catch (error) { + const blockName = fileName + "--" + "getHistoryMsg"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 删除历史消息 + async delHistoryMsg(uid, modelType, password, requestMsg) { + const { ctx } = this; + try { + const uidLastCode = shunt(uid); + const model = { + "B": ctx.model.BSide, + "C": ctx.model2.CSide, + "T": ctx.model4.Account, + }; + const result = await model[uidLastCode].findOne({ where: { uid } }); + if (!result || result.dataValues.password !== this.shaForm(password, this.decryptRequest(result.dataValues.salt))) return false; + let where = {}; + if (modelType == "single") { + const { sn_number, msg_data, origin_time } = requestMsg; + where = { user_uid: uid, sn_number, msg_data, created_at: origin_time }; + } else if (modelType == "multiple") { + let sn_number = [], msg_data = [], created_at = []; + for (const key in requestMsg) { + requestMsg[key].forEach(element => { + sn_number.push(element.sn_number), + msg_data.push(element.msg_data), + created_at.push(element.origin_time) + }); + } + where = { user_uid: uid, sn_number, msg_data, created_at }; + } else if (modelType == "all") { + where = { user_uid: uid }; + } + const modelName = { + "B": ctx.model.BSNMsg, + "C": ctx.model2.CSNMsg, + "T": ctx.model4.TSNMsg, + }; + const resetList = await modelName[uidLastCode].destroy({ where }); + return resetList.length == 0 ? false : resetList; + } catch (error) { + const blockName = fileName + "--" + "delHistoryMsg"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 获取单位用户 + async bsideUserManager(uid, body) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + let { offset, limit, searchOptions } = body; + offset = (offset - 1) * limit; + let attributes = ['account_name', 'user_name', 'phone'], + where = { organization: result.organization, role: { [Op.not]: 1 } }, dbOptions, joinSubstring = []; + attributes.forEach(element => { + if (searchOptions[element]) { + if(searchOptions[element] == '*空') { + if(joinSubstring.includes(element)) { + where[element] = null; + } else { + where[element] = [null, '']; + } + } else{ + where[element] = { [Op.substring]: searchOptions[element] }; + } + } + }); + dbOptions = { attributes, offset, limit, where }; + const userList = await ctx.model.BSide.findAndCountAll(dbOptions); + return userList.rows.length == 0 ? false : userList; + } catch (error) { + const blockName = fileName + "--" + "bsideUserManager"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } + + // 获取可管理的SN号 + async bsideSNManager(uid) { + const { ctx } = this; + try { + const result = await ctx.model.BSide.findOne({ where: { uid, status: { [Op.not]: 2 }, role: 1 } }); + if (!result || result.organization == null) return false; + let attributes = ['length', 'sn_set'], + where = { user_uid: uid }, dbOptions; + dbOptions = { attributes, where }; + const snMsg = await ctx.model.BuserSNAdmin.findOne(dbOptions); + if (!snMsg) return false; + const snList = snMsg.dataValues.sn_set.split(','); + const snResult = await ctx.model3.SNNumber.findAll({ attributes: ['sn_number', 'status', 'updated_at'], where: { sn_number: { [Op.in]: snList } } }); + return snResult.length == 0 ? false : snResult; + } catch (error) { + const blockName = fileName + "--" + "bsideSNManager"; + ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error); + return 'error'; + } + } +} + +module.exports = HomeService; \ No newline at end of file diff --git a/config/config.default.js b/config/config.default.js new file mode 100644 index 0000000..4d2c045 --- /dev/null +++ b/config/config.default.js @@ -0,0 +1,230 @@ +/* eslint valid-jsdoc: "off" */ + +/** + * @param {Egg.EggAppInfo} appInfo app info + */ + +const process = require('process'), + path = require('path'); + +module.exports = appInfo => { + /** + * built-in config + * @type {Egg.EggAppConfig} + **/ + const config = exports = {}; + + // use for cookie sign key, should change to your own and keep security + config.keys = appInfo.name + '_1772613754664_3442'; + + // add your middleware config here + // config.middleware = []; + + // 修改Egg.js的public路径配置到运行路径下 + config.static = { + prefix: '/', + dir: process.cwd() + '/public', + }; + + // 配置执行时临时文件的路径到运行路径 + config.rundir = process.cwd() + '/run'; + + // 配置普通日志文件地址 + config.logger = { + dir: path.join(process.cwd(), 'logs'), + }; + + // 配置定时任务日志文件地址 + config.customLogger = { + scheduleLogger: { + file: path.join(process.cwd(), 'logs', 'egg-schedule.log'), + }, + }; + + config.security = { + csrf: { + enable: false + }, + }; + + // socket服务端配置 + config.socketServer = { + ip: '127.0.0.1', + port: 8100 + }; + + // webSocket服务端配置 + config.webSocketServer = { + ip: '127.0.0.1', + port: 8110, + // path: '/snShortMessage/' + // path: '/snWebSocket/' + path: '/socket.io/', + allowedOrigins: "http://127.0.0.1" + }; + + config.redis = { + // 开发/测试环境 + clients: { + db0: { + port: 6379, + host: '127.0.0.1', + password: '74191221', + db: 0, + }, + db1: { + port: 6379, + host: '127.0.0.1', + password: '74191221', + db: 1, + }, + db2: { + port: 6379, + host: '127.0.0.1', + password: '74191221', + db: 2, + }, + db3: { + port: 6379, + host: '127.0.0.1', + password: '74191221', + db: 3, + }, + db5: { + port: 6379, + host: '127.0.0.1', + password: '74191221', + db: 5, + }, + } + // 生产环境 + // clients: { + // db0: { + // port: 6379, + // host: '127.0.0.1', + // password: 'bd3@htcc2023', + // db: 2, + // }, + // db1: { + // port: 6379, + // host: '127.0.0.1', + // password: 'bd3@htcc2023', + // db: 3, + // }, + // db2: { + // port: 6379, + // host: '127.0.0.1', + // password: 'bd3@htcc2023', + // db: 4, + // }, + // db3: { + // port: 6379, + // host: '127.0.0.1', + // password: 'bd3@htcc2023', + // db: 5, + // }, + // db5: { + // port: 6379, + // host: '127.0.0.1', + // password: 'bd3@htcc2023', + // db: 7, + // }, + // } + }; + + config.sequelize = { + // 开发/测试环境 + datasources: [ + { + dialect: 'mariadb', + host: 'localhost', + port: 3306, + username: 'root', + password: '74191221', + database: 'bside', + }, + { + dialect: 'mariadb', + host: 'localhost', + port: 3306, + username: 'root', + password: '74191221', + database: 'cside', + delegate: 'model2', + baseDir: 'model2', + }, + { + dialect: 'mariadb', + host: 'localhost', + port: 3306, + username: 'root', + password: '74191221', + database: 'insiders', + delegate: 'model3', + baseDir: 'model3', + }, + { + dialect: 'mariadb', + host: 'localhost', + port: 3306, + username: 'root', + password: '74191221', + database: 'bdContest', + delegate: 'model4', + baseDir: 'model4', + } + ] + // 生产环境 + // datasources: [ + // { + // dialect: 'mariadb', + // host: 'localhost', + // port: 3306, + // username: 'bdqh_platform', + // password: '124689@XXxx', + // database: 'bside', + // }, + // { + // dialect: 'mariadb', + // host: 'localhost', + // port: 3306, + // username: 'bdqh_platform', + // password: '124689@XXxx', + // database: 'cside', + // delegate: 'model2', + // baseDir: 'model2', + // }, + // { + // dialect: 'mariadb', + // host: 'localhost', + // port: 3306, + // username: 'bdqh_platform', + // password: '124689@XXxx', + // database: 'insiders', + // delegate: 'model3', + // baseDir: 'model3', + // }, + // { + // dialect: 'mariadb', + // host: 'localhost', + // port: 3306, + // username: 'bdqh_platform', + // password: '124689@XXxx', + // database: 'bdContest', + // delegate: 'model4', + // baseDir: 'model4', + // } + // ] + }; + + // add your user config here + const userConfig = { + // myAppName: 'egg', + salt: 'shortMessage' + }; + + return { + ...config, + ...userConfig, + }; +}; diff --git a/config/plugin.js b/config/plugin.js new file mode 100644 index 0000000..47d52b6 --- /dev/null +++ b/config/plugin.js @@ -0,0 +1,27 @@ +/** @type Egg.EggPlugin */ +module.exports = { + // had enabled by egg + // static: { + // enable: true, + // } + + CryptoJS : { + enable: true, + package: 'crypto-js', + }, + + redis : { + enable: true, + package: 'egg-redis', + }, + + sequelize : { + enable: true, + package: 'egg-sequelize', + }, + + validate : { + enable: true, + package: 'egg-validate', + }, +}; diff --git a/controllerLog/2026/3/16.txt b/controllerLog/2026/3/16.txt new file mode 100644 index 0000000..e2f45ea --- /dev/null +++ b/controllerLog/2026/3/16.txt @@ -0,0 +1,8 @@ +[2026-3-16>>>17:27:28]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:27:28]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:27:28]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:27:28]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:29:44]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:29:44]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:29:44]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:29:45]>>>home--bsideSNManager>>>>TypeError: Cannot read properties of undefined (reading 'length') diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..1bbed3f --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,5 @@ +{ + "include": [ + "**/*" + ] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..282cd33 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "tqxz-sn-message-platform", + "version": "1.0.0", + "description": "", + "private": true, + "egg": { + "declarations": true + }, + "dependencies": { + "crypto-js": "^4.2.0", + "egg": "^3.17.5", + "egg-redis": "^2.6.0", + "egg-scripts": "^3.0.1", + "egg-sequelize": "^6.0.0", + "egg-validate": "^2.0.2", + "gbk.js": "^0.3.0", + "ioredis": "^5.4.1", + "mariadb": "^3.5.2", + "mysql2": "^3.19.0", + "sequelize": "^6.37.8", + "socket.io": "^4.7.5" + }, + "devDependencies": { + "egg-bin": "6", + "egg-mock": "5", + "eslint": "8", + "eslint-config-egg": "13", + "sequelize-cli": "^6.6.5" + }, + "engines": { + "node": ">=18.0.0" + }, + "scripts": { + "reload": "egg-scripts stop --title=egg-server-tqxz-sn-message-platform && egg-scripts start --port=8120 --workers=1 --daemon --title=egg-server-tqxz-sn-message-platform --ignore-stderr", + "start": "egg-scripts start --port=8120 --workers=1 --daemon --title=egg-server-tqxz-sn-message-platform --ignore-stderr", + "stop": "egg-scripts stop --title=egg-server-tqxz-sn-message-platform", + "dev": "egg-bin dev --port=8120", + "test": "npm run lint -- --fix && npm run test:local", + "test:local": "egg-bin test", + "cov": "egg-bin cov", + "lint": "eslint .", + "ci": "npm run lint && npm run cov" + }, + "repository": { + "type": "git", + "url": "" + }, + "author": "", + "license": "MIT" +} diff --git a/serviceLog/2026/3/16.txt b/serviceLog/2026/3/16.txt new file mode 100644 index 0000000..a8e2246 --- /dev/null +++ b/serviceLog/2026/3/16.txt @@ -0,0 +1,3 @@ +[2026-3-16>>>17:46:6]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:51:52]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-16>>>17:51:52]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } diff --git a/serviceLog/2026/3/17.txt b/serviceLog/2026/3/17.txt new file mode 100644 index 0000000..35d70c6 --- /dev/null +++ b/serviceLog/2026/3/17.txt @@ -0,0 +1,35 @@ +[2026-3-17>>>9:23:42]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } + of undefined (reading 'length') +[2026-3-17>>>9:43:23]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:43:23]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:51:38]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:51:38]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:51:47]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:51:47]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:51:54]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:51:54]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:52:52]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:52:52]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:53:18]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>9:53:18]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:59:15]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>9:59:15]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>10:11:11]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>10:11:11]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:3:21]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:3:21]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>11:16:39]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:16:39]>>>home--searchBindSN>>>>Error: Invalid value { status: 4 } +[2026-3-17>>>11:30:56]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:31:48]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:33:49]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:36:3]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:36:34]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:37:34]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:40:36]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:41:19]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>11:43:23]>>>home--searchBindUser>>>>TypeError: Cannot read properties of undefined (reading 'length') +[2026-3-17>>>12:4:12]>>>home--bindSN>>>>TypeError: Cannot read properties of null (reading 'value') +[2026-3-17>>>12:4:36]>>>home--bindSN>>>>TypeError: Cannot read properties of null (reading 'value') +[2026-3-17>>>15:4:17]>>>home--bindSN>>>>TypeError: Cannot read properties of null (reading 'value') +[2026-3-17>>>15:17:51]>>>home--searchBindUser>>>>ReferenceError: item is not defined diff --git a/serviceLog/2026/3/27.txt b/serviceLog/2026/3/27.txt new file mode 100644 index 0000000..724b052 --- /dev/null +++ b/serviceLog/2026/3/27.txt @@ -0,0 +1,2 @@ +[2026-3-27>>>9:49:20]>>>home--getHistoryMsg>>>>SequelizeDatabaseError: (conn:78, no: 1267, SQLState: HY000) Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation 'like' +sql: SELECT count(*) AS `count` FROM `bsn-msg` AS `bsn-msg` WHERE `bsn-msg`.`user_uid` = '20240613698218B' AND `bsn-msg`.`original_msg` LIKE '%测试%'; - parameters:[] diff --git a/test/app/controller/home.test.js b/test/app/controller/home.test.js new file mode 100644 index 0000000..ea43dbb --- /dev/null +++ b/test/app/controller/home.test.js @@ -0,0 +1,23 @@ +const { strict: assert } = require('node:assert'); +const path = require('node:path'); +const { statSync } = require('node:fs'); +const { app } = require('egg-mock/bootstrap'); + +describe('test/app/controller/home.test.js', () => { + it('should assert', async () => { + const pkg = require('../../../package.json'); + assert(app.config.keys.startsWith(pkg.name)); + }); + + it('should typings exists', async () => { + const typings = path.join(__dirname, '../../../typings'); + assert(statSync(typings)); + }); + + it('should GET /', async () => { + return app.httpRequest() + .get('/') + .expect('hi, egg') + .expect(200); + }); +}); diff --git a/unknownSNLog/2026/3/17.txt b/unknownSNLog/2026/3/17.txt new file mode 100644 index 0000000..1847265 --- /dev/null +++ b/unknownSNLog/2026/3/17.txt @@ -0,0 +1,5 @@ +[2026-3-17>>>16:12:0]>>>[object Object] +[2026-3-17>>>16:12:20]>>>[object Object] +[2026-3-17>>>16:14:3]>>>[object Object] +[2026-3-17>>>16:26:36]>>>[object Object] +[2026-3-17>>>17:31:20]>>>[object Object]