完善保险端前后端
This commit is contained in:
86
insurance_backend/models/Device.js
Normal file
86
insurance_backend/models/Device.js
Normal file
@@ -0,0 +1,86 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
/**
|
||||
* 设备模型
|
||||
* 用于管理保险相关的设备信息
|
||||
*/
|
||||
const Device = sequelize.define('Device', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
comment: '设备ID'
|
||||
},
|
||||
device_number: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '设备编号'
|
||||
},
|
||||
device_name: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '设备名称'
|
||||
},
|
||||
device_type: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '设备类型'
|
||||
},
|
||||
device_model: {
|
||||
type: DataTypes.STRING(100),
|
||||
comment: '设备型号'
|
||||
},
|
||||
manufacturer: {
|
||||
type: DataTypes.STRING(100),
|
||||
comment: '制造商'
|
||||
},
|
||||
installation_location: {
|
||||
type: DataTypes.STRING(200),
|
||||
comment: '安装位置'
|
||||
},
|
||||
installation_date: {
|
||||
type: DataTypes.DATE,
|
||||
comment: '安装日期'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('normal', 'warning', 'error', 'offline'),
|
||||
defaultValue: 'normal',
|
||||
comment: '设备状态:normal-正常,warning-警告,error-故障,offline-离线'
|
||||
},
|
||||
farm_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '所属养殖场ID'
|
||||
},
|
||||
barn_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '所属栏舍ID'
|
||||
},
|
||||
created_by: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '创建人ID'
|
||||
},
|
||||
updated_by: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '更新人ID'
|
||||
},
|
||||
created_at: {
|
||||
type: DataTypes.DATE,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '创建时间'
|
||||
},
|
||||
updated_at: {
|
||||
type: DataTypes.DATE,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '更新时间'
|
||||
}
|
||||
}, {
|
||||
tableName: 'devices',
|
||||
timestamps: true,
|
||||
createdAt: 'created_at',
|
||||
updatedAt: 'updated_at',
|
||||
comment: '设备信息表'
|
||||
});
|
||||
|
||||
module.exports = Device;
|
||||
114
insurance_backend/models/DeviceAlert.js
Normal file
114
insurance_backend/models/DeviceAlert.js
Normal file
@@ -0,0 +1,114 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
/**
|
||||
* 设备预警模型
|
||||
* 用于管理设备预警信息
|
||||
*/
|
||||
const DeviceAlert = sequelize.define('DeviceAlert', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
comment: '预警ID'
|
||||
},
|
||||
device_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '设备ID'
|
||||
},
|
||||
alert_type: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '预警类型'
|
||||
},
|
||||
alert_level: {
|
||||
type: DataTypes.ENUM('info', 'warning', 'critical'),
|
||||
allowNull: false,
|
||||
comment: '预警级别:info-信息,warning-警告,critical-严重'
|
||||
},
|
||||
alert_title: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: false,
|
||||
comment: '预警标题'
|
||||
},
|
||||
alert_content: {
|
||||
type: DataTypes.TEXT,
|
||||
comment: '预警内容'
|
||||
},
|
||||
alert_time: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '预警时间'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('pending', 'processing', 'resolved', 'ignored'),
|
||||
defaultValue: 'pending',
|
||||
comment: '处理状态:pending-待处理,processing-处理中,resolved-已解决,ignored-已忽略'
|
||||
},
|
||||
handler_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '处理人ID'
|
||||
},
|
||||
handle_time: {
|
||||
type: DataTypes.DATE,
|
||||
comment: '处理时间'
|
||||
},
|
||||
handle_note: {
|
||||
type: DataTypes.TEXT,
|
||||
comment: '处理备注'
|
||||
},
|
||||
farm_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '所属养殖场ID'
|
||||
},
|
||||
barn_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
comment: '所属栏舍ID'
|
||||
},
|
||||
is_read: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false,
|
||||
comment: '是否已读'
|
||||
},
|
||||
read_time: {
|
||||
type: DataTypes.DATE,
|
||||
comment: '阅读时间'
|
||||
},
|
||||
created_at: {
|
||||
type: DataTypes.DATE,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '创建时间'
|
||||
},
|
||||
updated_at: {
|
||||
type: DataTypes.DATE,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '更新时间'
|
||||
}
|
||||
}, {
|
||||
tableName: 'device_alerts',
|
||||
timestamps: true,
|
||||
createdAt: 'created_at',
|
||||
updatedAt: 'updated_at',
|
||||
comment: '设备预警表',
|
||||
indexes: [
|
||||
{
|
||||
fields: ['device_id']
|
||||
},
|
||||
{
|
||||
fields: ['alert_level']
|
||||
},
|
||||
{
|
||||
fields: ['status']
|
||||
},
|
||||
{
|
||||
fields: ['alert_time']
|
||||
},
|
||||
{
|
||||
fields: ['farm_id']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
module.exports = DeviceAlert;
|
||||
270
insurance_backend/models/OperationLog.js
Normal file
270
insurance_backend/models/OperationLog.js
Normal file
@@ -0,0 +1,270 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
const OperationLog = sequelize.define('OperationLog', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true
|
||||
},
|
||||
user_id: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'users',
|
||||
key: 'id'
|
||||
},
|
||||
comment: '操作用户ID'
|
||||
},
|
||||
operation_type: {
|
||||
type: DataTypes.ENUM(
|
||||
'login', // 登录
|
||||
'logout', // 登出
|
||||
'create', // 创建
|
||||
'update', // 更新
|
||||
'delete', // 删除
|
||||
'view', // 查看
|
||||
'export', // 导出
|
||||
'import', // 导入
|
||||
'approve', // 审批
|
||||
'reject', // 拒绝
|
||||
'system_config', // 系统配置
|
||||
'user_manage', // 用户管理
|
||||
'role_manage', // 角色管理
|
||||
'other' // 其他
|
||||
),
|
||||
allowNull: false,
|
||||
comment: '操作类型'
|
||||
},
|
||||
operation_module: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '操作模块(如:用户管理、设备管理、预警管理等)'
|
||||
},
|
||||
operation_content: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: false,
|
||||
comment: '操作内容描述'
|
||||
},
|
||||
operation_target: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: true,
|
||||
comment: '操作目标(如:用户ID、设备ID等)'
|
||||
},
|
||||
request_method: {
|
||||
type: DataTypes.ENUM('GET', 'POST', 'PUT', 'DELETE', 'PATCH'),
|
||||
allowNull: true,
|
||||
comment: 'HTTP请求方法'
|
||||
},
|
||||
request_url: {
|
||||
type: DataTypes.STRING(500),
|
||||
allowNull: true,
|
||||
comment: '请求URL'
|
||||
},
|
||||
request_params: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '请求参数(JSON格式)',
|
||||
get() {
|
||||
const value = this.getDataValue('request_params');
|
||||
return value ? JSON.parse(value) : null;
|
||||
},
|
||||
set(value) {
|
||||
this.setDataValue('request_params', value ? JSON.stringify(value) : null);
|
||||
}
|
||||
},
|
||||
response_status: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '响应状态码'
|
||||
},
|
||||
ip_address: {
|
||||
type: DataTypes.STRING(45),
|
||||
allowNull: true,
|
||||
comment: 'IP地址(支持IPv6)'
|
||||
},
|
||||
user_agent: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '用户代理信息'
|
||||
},
|
||||
execution_time: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '执行时间(毫秒)'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('success', 'failed', 'error'),
|
||||
defaultValue: 'success',
|
||||
comment: '操作状态'
|
||||
},
|
||||
error_message: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '错误信息'
|
||||
}
|
||||
}, {
|
||||
tableName: 'operation_logs',
|
||||
timestamps: true,
|
||||
underscored: true,
|
||||
indexes: [
|
||||
{ fields: ['user_id'] },
|
||||
{ fields: ['operation_type'] },
|
||||
{ fields: ['operation_module'] },
|
||||
{ fields: ['created_at'] },
|
||||
{ fields: ['status'] },
|
||||
{ fields: ['ip_address'] }
|
||||
]
|
||||
});
|
||||
|
||||
// 定义关联关系
|
||||
OperationLog.associate = function(models) {
|
||||
// 操作日志属于用户
|
||||
OperationLog.belongsTo(models.User, {
|
||||
foreignKey: 'user_id',
|
||||
as: 'user',
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE'
|
||||
});
|
||||
};
|
||||
|
||||
// 静态方法:记录操作日志
|
||||
OperationLog.logOperation = async function(logData) {
|
||||
try {
|
||||
const log = await this.create({
|
||||
user_id: logData.userId,
|
||||
operation_type: logData.operationType,
|
||||
operation_module: logData.operationModule,
|
||||
operation_content: logData.operationContent,
|
||||
operation_target: logData.operationTarget,
|
||||
request_method: logData.requestMethod,
|
||||
request_url: logData.requestUrl,
|
||||
request_params: logData.requestParams,
|
||||
response_status: logData.responseStatus,
|
||||
ip_address: logData.ipAddress,
|
||||
user_agent: logData.userAgent,
|
||||
execution_time: logData.executionTime,
|
||||
status: logData.status || 'success',
|
||||
error_message: logData.errorMessage
|
||||
});
|
||||
return log;
|
||||
} catch (error) {
|
||||
console.error('记录操作日志失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 静态方法:获取操作日志列表
|
||||
OperationLog.getLogsList = async function(options = {}) {
|
||||
const {
|
||||
page = 1,
|
||||
limit = 20,
|
||||
userId,
|
||||
operationType,
|
||||
operationModule,
|
||||
status,
|
||||
startDate,
|
||||
endDate,
|
||||
keyword
|
||||
} = options;
|
||||
|
||||
const where = {};
|
||||
|
||||
// 构建查询条件
|
||||
if (userId) where.user_id = userId;
|
||||
if (operationType) where.operation_type = operationType;
|
||||
if (operationModule) where.operation_module = operationModule;
|
||||
if (status) where.status = status;
|
||||
|
||||
// 时间范围查询
|
||||
if (startDate || endDate) {
|
||||
where.created_at = {};
|
||||
if (startDate) where.created_at[sequelize.Op.gte] = new Date(startDate);
|
||||
if (endDate) where.created_at[sequelize.Op.lte] = new Date(endDate);
|
||||
}
|
||||
|
||||
// 关键词搜索
|
||||
if (keyword) {
|
||||
where[sequelize.Op.or] = [
|
||||
{ operation_content: { [sequelize.Op.like]: `%${keyword}%` } },
|
||||
{ operation_target: { [sequelize.Op.like]: `%${keyword}%` } }
|
||||
];
|
||||
}
|
||||
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const result = await this.findAndCountAll({
|
||||
where,
|
||||
include: [{
|
||||
model: sequelize.models.User,
|
||||
as: 'user',
|
||||
attributes: ['id', 'username', 'real_name']
|
||||
}],
|
||||
order: [['created_at', 'DESC']],
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset)
|
||||
});
|
||||
|
||||
return {
|
||||
logs: result.rows,
|
||||
total: result.count,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
totalPages: Math.ceil(result.count / limit)
|
||||
};
|
||||
};
|
||||
|
||||
// 静态方法:获取操作统计
|
||||
OperationLog.getOperationStats = async function(options = {}) {
|
||||
const { startDate, endDate, userId } = options;
|
||||
|
||||
const where = {};
|
||||
if (userId) where.user_id = userId;
|
||||
|
||||
if (startDate || endDate) {
|
||||
where.created_at = {};
|
||||
if (startDate) where.created_at[sequelize.Op.gte] = new Date(startDate);
|
||||
if (endDate) where.created_at[sequelize.Op.lte] = new Date(endDate);
|
||||
}
|
||||
|
||||
// 按操作类型统计
|
||||
const typeStats = await this.findAll({
|
||||
where,
|
||||
attributes: [
|
||||
'operation_type',
|
||||
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
|
||||
],
|
||||
group: ['operation_type'],
|
||||
raw: true
|
||||
});
|
||||
|
||||
// 按操作模块统计
|
||||
const moduleStats = await this.findAll({
|
||||
where,
|
||||
attributes: [
|
||||
'operation_module',
|
||||
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
|
||||
],
|
||||
group: ['operation_module'],
|
||||
raw: true
|
||||
});
|
||||
|
||||
// 按状态统计
|
||||
const statusStats = await this.findAll({
|
||||
where,
|
||||
attributes: [
|
||||
'status',
|
||||
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
|
||||
],
|
||||
group: ['status'],
|
||||
raw: true
|
||||
});
|
||||
|
||||
return {
|
||||
typeStats,
|
||||
moduleStats,
|
||||
statusStats
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = OperationLog;
|
||||
@@ -12,6 +12,9 @@ const InstallationTask = require('./InstallationTask');
|
||||
const LivestockType = require('./LivestockType');
|
||||
const LivestockPolicy = require('./LivestockPolicy');
|
||||
const LivestockClaim = require('./LivestockClaim');
|
||||
const Device = require('./Device');
|
||||
const DeviceAlert = require('./DeviceAlert');
|
||||
const OperationLog = require('./OperationLog');
|
||||
|
||||
// 定义模型关联关系
|
||||
|
||||
@@ -150,6 +153,46 @@ LivestockClaim.belongsTo(User, {
|
||||
as: 'reviewer'
|
||||
});
|
||||
|
||||
// 设备和用户关联
|
||||
Device.belongsTo(User, {
|
||||
foreignKey: 'created_by',
|
||||
as: 'creator'
|
||||
});
|
||||
Device.belongsTo(User, {
|
||||
foreignKey: 'updated_by',
|
||||
as: 'updater'
|
||||
});
|
||||
|
||||
// 设备预警和设备关联
|
||||
DeviceAlert.belongsTo(Device, {
|
||||
foreignKey: 'device_id',
|
||||
as: 'device'
|
||||
});
|
||||
Device.hasMany(DeviceAlert, {
|
||||
foreignKey: 'device_id',
|
||||
as: 'alerts'
|
||||
});
|
||||
|
||||
// 设备预警和用户关联
|
||||
DeviceAlert.belongsTo(User, {
|
||||
foreignKey: 'handler_id',
|
||||
as: 'handler'
|
||||
});
|
||||
User.hasMany(DeviceAlert, {
|
||||
foreignKey: 'handler_id',
|
||||
as: 'handled_alerts'
|
||||
});
|
||||
|
||||
// 操作日志和用户关联
|
||||
OperationLog.belongsTo(User, {
|
||||
foreignKey: 'user_id',
|
||||
as: 'user'
|
||||
});
|
||||
User.hasMany(OperationLog, {
|
||||
foreignKey: 'user_id',
|
||||
as: 'operation_logs'
|
||||
});
|
||||
|
||||
// 导出所有模型
|
||||
module.exports = {
|
||||
sequelize,
|
||||
@@ -164,5 +207,8 @@ module.exports = {
|
||||
InstallationTask,
|
||||
LivestockType,
|
||||
LivestockPolicy,
|
||||
LivestockClaim
|
||||
LivestockClaim,
|
||||
Device,
|
||||
DeviceAlert,
|
||||
OperationLog
|
||||
};
|
||||
Reference in New Issue
Block a user