1
This commit is contained in:
@@ -509,6 +509,158 @@ module.exports = {
|
||||
const { ids } = body;
|
||||
const result = await plaAccountService.batchParseLocation(ids);
|
||||
return ctx.success(result);
|
||||
},
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /admin_api/account/check-authorization:
|
||||
* post:
|
||||
* summary: 检查账号授权状态
|
||||
* description: 根据账号ID或SN码检查账号的授权状态(剩余天数、是否过期等)
|
||||
* tags: [后台-账号管理]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* id:
|
||||
* type: integer
|
||||
* description: 账号ID(可选,如果提供id则不需要sn_code)
|
||||
* sn_code:
|
||||
* type: string
|
||||
* description: 设备SN码(可选,如果提供sn_code则不需要id)
|
||||
* responses:
|
||||
* 200:
|
||||
* description: 检查成功
|
||||
*/
|
||||
'POST /account/check-authorization': async (ctx) => {
|
||||
const { id, sn_code } = ctx.getBody();
|
||||
const models = await Framework.getModels();
|
||||
const { pla_account } = models;
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
if (!id && !sn_code) {
|
||||
return ctx.fail('请提供账号ID或SN码');
|
||||
}
|
||||
|
||||
const where = id ? { id } : { sn_code };
|
||||
const account = await pla_account.findOne({ where });
|
||||
|
||||
if (!account) {
|
||||
return ctx.fail('账号不存在');
|
||||
}
|
||||
|
||||
const accountData = account.toJSON();
|
||||
const authDate = accountData.authorization_date;
|
||||
const authDays = accountData.authorization_days || 0;
|
||||
|
||||
// 计算剩余天数
|
||||
let remaining_days = 0;
|
||||
let is_expired = false;
|
||||
let end_date = null;
|
||||
|
||||
if (authDate && authDays > 0) {
|
||||
const startDate = dayjs(authDate);
|
||||
end_date = startDate.add(authDays, 'day').toDate();
|
||||
const now = dayjs();
|
||||
const remaining = dayjs(end_date).diff(now, 'day', true);
|
||||
remaining_days = Math.max(0, Math.ceil(remaining));
|
||||
is_expired = remaining_days <= 0;
|
||||
}
|
||||
|
||||
return ctx.success({
|
||||
id: accountData.id,
|
||||
sn_code: accountData.sn_code,
|
||||
name: accountData.name,
|
||||
authorization_date: authDate,
|
||||
authorization_days: authDays,
|
||||
remaining_days: remaining_days,
|
||||
end_date: end_date,
|
||||
is_expired: is_expired,
|
||||
is_authorized: !is_expired && remaining_days > 0
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /admin_api/account/update-authorization:
|
||||
* post:
|
||||
* summary: 更新账号授权信息
|
||||
* description: 更新账号的授权日期和授权天数
|
||||
* tags: [后台-账号管理]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - id
|
||||
* properties:
|
||||
* id:
|
||||
* type: integer
|
||||
* description: 账号ID
|
||||
* authorization_date:
|
||||
* type: string
|
||||
* format: date-time
|
||||
* description: 授权日期(可选,不提供则使用当前时间)
|
||||
* authorization_days:
|
||||
* type: integer
|
||||
* description: 授权天数(必填)
|
||||
* responses:
|
||||
* 200:
|
||||
* description: 更新成功
|
||||
*/
|
||||
'POST /account/update-authorization': async (ctx) => {
|
||||
const { id, authorization_date, authorization_days } = ctx.getBody();
|
||||
const models = await Framework.getModels();
|
||||
const { pla_account } = models;
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
if (!id) {
|
||||
return ctx.fail('账号ID不能为空');
|
||||
}
|
||||
|
||||
if (authorization_days === undefined || authorization_days === null) {
|
||||
return ctx.fail('授权天数不能为空');
|
||||
}
|
||||
|
||||
if (authorization_days < 0) {
|
||||
return ctx.fail('授权天数不能为负数');
|
||||
}
|
||||
|
||||
const account = await pla_account.findOne({ where: { id } });
|
||||
|
||||
if (!account) {
|
||||
return ctx.fail('账号不存在');
|
||||
}
|
||||
|
||||
// 如果提供了授权日期,使用提供的日期;否则使用当前时间
|
||||
const authDate = authorization_date ? new Date(authorization_date) : new Date();
|
||||
|
||||
await account.update({
|
||||
authorization_date: authDate,
|
||||
authorization_days: authorization_days
|
||||
});
|
||||
|
||||
// 计算更新后的剩余天数
|
||||
const end_date = dayjs(authDate).add(authorization_days, 'day').toDate();
|
||||
const now = dayjs();
|
||||
const remaining = dayjs(end_date).diff(now, 'day', true);
|
||||
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||
|
||||
return ctx.success({
|
||||
message: '授权信息更新成功',
|
||||
data: {
|
||||
id: account.id,
|
||||
authorization_date: authDate,
|
||||
authorization_days: authorization_days,
|
||||
remaining_days: remaining_days,
|
||||
end_date: end_date
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ module.exports = {
|
||||
"POST /user/login": async (ctx) => {
|
||||
|
||||
const { sn_code, device_id } = ctx.getBody();
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
const { pla_account,device_status} = await Framework.getModels();
|
||||
|
||||
@@ -79,6 +80,26 @@ module.exports = {
|
||||
return ctx.fail('用户不存在');
|
||||
}
|
||||
|
||||
// 检查授权状态
|
||||
const userData = user.toJSON();
|
||||
const authDate = userData.authorization_date;
|
||||
const authDays = userData.authorization_days || 0;
|
||||
|
||||
if (authDate && authDays > 0) {
|
||||
const startDate = dayjs(authDate);
|
||||
const endDate = startDate.add(authDays, 'day');
|
||||
const now = dayjs();
|
||||
const remaining = endDate.diff(now, 'day', true);
|
||||
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||
|
||||
if (remaining_days <= 0) {
|
||||
return ctx.fail('账号授权已过期,请联系管理员续费');
|
||||
}
|
||||
} else {
|
||||
// 如果没有授权信息,检查是否允许登录(可以根据业务需求决定是否允许)
|
||||
// 这里暂时允许登录,但可以添加配置项控制
|
||||
}
|
||||
|
||||
// 更新设备状态
|
||||
|
||||
const device = await device_status.findOne({ where: { sn_code } });
|
||||
@@ -99,7 +120,20 @@ module.exports = {
|
||||
device_id: user.device_id
|
||||
});
|
||||
|
||||
return ctx.success({ token, user: user.toJSON() });
|
||||
// 计算剩余天数并返回
|
||||
let remaining_days = 0;
|
||||
if (authDate && authDays > 0) {
|
||||
const startDate = dayjs(authDate);
|
||||
const endDate = startDate.add(authDays, 'day');
|
||||
const now = dayjs();
|
||||
const remaining = endDate.diff(now, 'day', true);
|
||||
remaining_days = Math.max(0, Math.ceil(remaining));
|
||||
}
|
||||
|
||||
const userInfo = user.toJSON();
|
||||
userInfo.remaining_days = remaining_days;
|
||||
|
||||
return ctx.success({ token, user: userInfo });
|
||||
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,18 @@ class MqttDispatcher {
|
||||
});
|
||||
}
|
||||
|
||||
// 检查授权状态(对于需要授权的操作)
|
||||
const authorizationService = require('../../services/authorization_service');
|
||||
const authCheck = await authorizationService.checkAuthorization(deviceCode, 'sn_code');
|
||||
if (!authCheck.is_authorized) {
|
||||
console.log(`[MQTT分发器] 设备 ${deviceCode} 授权检查失败: ${authCheck.message}`);
|
||||
return this.sendMqttResponse(mqttClient, uuid, {
|
||||
code: 403,
|
||||
message: authCheck.message,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
// 获取对应的处理器
|
||||
const handler = this.actionHandlers.get(action);
|
||||
if (!handler) {
|
||||
|
||||
@@ -3,6 +3,7 @@ const db = require('../dbProxy');
|
||||
const jobManager = require('../job/index');
|
||||
const ScheduleUtils = require('./utils');
|
||||
const ScheduleConfig = require('./config');
|
||||
const authorizationService = require('../../services/authorization_service');
|
||||
|
||||
|
||||
/**
|
||||
@@ -91,6 +92,12 @@ class CommandManager {
|
||||
throw new Error(`任务不存在: ${task_id}`);
|
||||
}
|
||||
|
||||
// 1.5 检查账号授权状态
|
||||
const authCheck = await authorizationService.checkAuthorization(task.sn_code, 'sn_code');
|
||||
if (!authCheck.is_authorized) {
|
||||
throw new Error(`授权检查失败: ${authCheck.message}`);
|
||||
}
|
||||
|
||||
// 2. 获取指令信息
|
||||
const command_name = command.command_name || command.name || '未知指令';
|
||||
const command_type = command.command_type || command.type;
|
||||
|
||||
@@ -48,6 +48,18 @@ class TaskHandlers {
|
||||
|
||||
console.log(`[任务处理器] 自动投递任务 - 设备: ${sn_code}, 关键词: ${keyword}`);
|
||||
|
||||
// 检查授权状态
|
||||
const authorizationService = require('../../services/authorization_service');
|
||||
const authCheck = await authorizationService.checkAuthorization(sn_code, 'sn_code');
|
||||
if (!authCheck.is_authorized) {
|
||||
console.log(`[任务处理器] 自动投递任务 - 设备: ${sn_code} 授权检查失败: ${authCheck.message}`);
|
||||
return {
|
||||
success: false,
|
||||
deliveredCount: 0,
|
||||
message: authCheck.message
|
||||
};
|
||||
}
|
||||
|
||||
deviceManager.recordTaskStart(sn_code, task);
|
||||
const startTime = Date.now();
|
||||
|
||||
@@ -543,6 +555,18 @@ class TaskHandlers {
|
||||
const { sn_code, taskParams } = task;
|
||||
console.log(`[任务处理器] 自动沟通任务 - 设备: ${sn_code}`);
|
||||
|
||||
// 检查授权状态
|
||||
const authorizationService = require('../../services/authorization_service');
|
||||
const authCheck = await authorizationService.checkAuthorization(sn_code, 'sn_code');
|
||||
if (!authCheck.is_authorized) {
|
||||
console.log(`[任务处理器] 自动沟通任务 - 设备: ${sn_code} 授权检查失败: ${authCheck.message}`);
|
||||
return {
|
||||
success: false,
|
||||
chatCount: 0,
|
||||
message: authCheck.message
|
||||
};
|
||||
}
|
||||
|
||||
deviceManager.recordTaskStart(sn_code, task);
|
||||
const startTime = Date.now();
|
||||
|
||||
|
||||
@@ -264,6 +264,39 @@ module.exports = (db) => {
|
||||
})
|
||||
},
|
||||
|
||||
// 授权相关字段
|
||||
authorization_date: {
|
||||
comment: '授权日期(授权开始时间)',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
authorization_days: {
|
||||
comment: '授权天数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
remaining_days: {
|
||||
comment: '剩余天数(虚拟字段,通过计算得出)',
|
||||
type: Sequelize.VIRTUAL,
|
||||
get: function () {
|
||||
const authDate = this.getDataValue('authorization_date');
|
||||
const authDays = this.getDataValue('authorization_days') || 0;
|
||||
|
||||
if (!authDate || authDays <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const startDate = dayjs(authDate);
|
||||
const endDate = startDate.add(authDays, 'day');
|
||||
const now = dayjs();
|
||||
|
||||
// 计算剩余天数
|
||||
const remaining = endDate.diff(now, 'day', true);
|
||||
return Math.max(0, Math.ceil(remaining));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
80
api/services/authorization_service.js
Normal file
80
api/services/authorization_service.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 授权服务
|
||||
* 提供账号授权检查功能
|
||||
*/
|
||||
|
||||
const db = require('../middleware/dbProxy');
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
class AuthorizationService {
|
||||
/**
|
||||
* 检查账号授权状态
|
||||
* @param {string|number} identifier - 账号标识(sn_code 或 id)
|
||||
* @param {string} identifierType - 标识类型:'sn_code' 或 'id'
|
||||
* @returns {Promise<Object>} 授权检查结果 {is_authorized: boolean, remaining_days: number, message: string}
|
||||
*/
|
||||
async checkAuthorization(identifier, identifierType = 'sn_code') {
|
||||
const pla_account = db.getModel('pla_account');
|
||||
|
||||
const where = {};
|
||||
where[identifierType] = identifier;
|
||||
|
||||
const account = await pla_account.findOne({ where });
|
||||
|
||||
if (!account) {
|
||||
return {
|
||||
is_authorized: false,
|
||||
remaining_days: 0,
|
||||
message: '账号不存在'
|
||||
};
|
||||
}
|
||||
|
||||
const accountData = account.toJSON();
|
||||
const authDate = accountData.authorization_date;
|
||||
const authDays = accountData.authorization_days || 0;
|
||||
|
||||
// 如果没有授权信息,默认不允许
|
||||
if (!authDate || authDays <= 0) {
|
||||
return {
|
||||
is_authorized: false,
|
||||
remaining_days: 0,
|
||||
message: '账号未授权,请联系管理员'
|
||||
};
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
const startDate = dayjs(authDate);
|
||||
const endDate = startDate.add(authDays, 'day');
|
||||
const now = dayjs();
|
||||
const remaining = endDate.diff(now, 'day', true);
|
||||
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||
|
||||
if (remaining_days <= 0) {
|
||||
return {
|
||||
is_authorized: false,
|
||||
remaining_days: 0,
|
||||
message: '账号授权已过期,请联系管理员续费'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
is_authorized: true,
|
||||
remaining_days: remaining_days,
|
||||
message: `授权有效,剩余 ${remaining_days} 天`
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查账号授权状态(快速检查,只返回是否授权)
|
||||
* @param {string|number} identifier - 账号标识(sn_code 或 id)
|
||||
* @param {string} identifierType - 标识类型:'sn_code' 或 'id'
|
||||
* @returns {Promise<boolean>} 是否授权
|
||||
*/
|
||||
async isAuthorized(identifier, identifierType = 'sn_code') {
|
||||
const result = await this.checkAuthorization(identifier, identifierType);
|
||||
return result.is_authorized;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new AuthorizationService();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
const db = require('../middleware/dbProxy');
|
||||
const scheduleManager = require('../middleware/schedule/index.js');
|
||||
const locationService = require('./locationService');
|
||||
const authorizationService = require('./authorization_service');
|
||||
|
||||
class PlaAccountService {
|
||||
/**
|
||||
@@ -382,6 +383,12 @@ class PlaAccountService {
|
||||
throw new Error('账号不存在');
|
||||
}
|
||||
|
||||
// 检查授权状态
|
||||
const authCheck = await authorizationService.checkAuthorization(id, 'id');
|
||||
if (!authCheck.is_authorized) {
|
||||
throw new Error(authCheck.message);
|
||||
}
|
||||
|
||||
// 从 device_status 检查账号是否在线
|
||||
const deviceStatus = await device_status.findByPk(account.sn_code);
|
||||
if (!deviceStatus || !deviceStatus.isOnline) {
|
||||
|
||||
Reference in New Issue
Block a user