卫星通信服务平台

This commit is contained in:
2026-03-27 17:57:44 +08:00
commit 21bcbf78f8
35 changed files with 1915 additions and 0 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
coverage

4
.eslintrc Normal file
View File

@@ -0,0 +1,4 @@
{
"extends": "eslint-config-egg",
"root": true
}

15
.gitignore vendored Normal file
View File

@@ -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/

31
README.md Normal file
View File

@@ -0,0 +1,31 @@
# tqxz-sn-message-platform
## QuickStart
<!-- add docs here for user -->
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

464
app/controller/home.js Normal file
View File

@@ -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;

50
app/core/base_service.js Normal file
View File

@@ -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;

View File

@@ -0,0 +1,8 @@
// socket事件监听器
const EventEmitter = require('events');
const socketEmitter = new EventEmitter();
module.exports = () => {
return socketEmitter;
};

View File

@@ -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');
});
}

View File

@@ -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('新内容已追加到文件');
});
}
});
};

View File

@@ -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: {}
});
});
};

21
app/model/BSNMsg.js Normal file
View File

@@ -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;
};

30
app/model/BSide.js Normal file
View File

@@ -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;
};

View File

@@ -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;
};

19
app/model/BuserSNAdmin.js Normal file
View File

@@ -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;
};

18
app/model/BuserSNBind.js Normal file
View File

@@ -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;
};

View File

@@ -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;
};

21
app/model2/CSNMsg.js Normal file
View File

@@ -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;
};

34
app/model2/CSide.js Normal file
View File

@@ -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;
};

18
app/model2/CuserSNBind.js Normal file
View File

@@ -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;
};

20
app/model3/SNNumber.js Normal file
View File

@@ -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;
};

24
app/model4/Account.js Normal file
View File

@@ -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;
};

21
app/model4/TSNMsg.js Normal file
View File

@@ -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;
};

18
app/model4/TuserSNBind.js Normal file
View File

@@ -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;
};

41
app/router.js Normal file
View File

@@ -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);
};

442
app/service/home.js Normal file
View File

@@ -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;

230
config/config.default.js Normal file
View File

@@ -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,
};
};

27
config/plugin.js Normal file
View File

@@ -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',
},
};

View File

@@ -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')

5
jsconfig.json Normal file
View File

@@ -0,0 +1,5 @@
{
"include": [
"**/*"
]
}

50
package.json Normal file
View File

@@ -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"
}

3
serviceLog/2026/3/16.txt Normal file
View File

@@ -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 }

35
serviceLog/2026/3/17.txt Normal file
View File

@@ -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

2
serviceLog/2026/3/27.txt Normal file
View File

@@ -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:[]

View File

@@ -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);
});
});

View File

@@ -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]