完善保险端前后端

This commit is contained in:
shenquanyi
2025-09-24 18:12:37 +08:00
parent 111ebaec84
commit b17bdcc24c
56 changed files with 9862 additions and 1111 deletions

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

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

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

View File

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