继续完善保险项目和养殖端小程序

This commit is contained in:
xuqiuyun
2025-09-29 18:35:03 +08:00
parent 4af8368097
commit 4e8d4dc92d
192 changed files with 4886 additions and 35384 deletions

View File

@@ -1,142 +0,0 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const Claim = sequelize.define('Claim', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
comment: '理赔ID'
},
claim_no: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
comment: '理赔编号',
validate: {
notEmpty: {
msg: '理赔编号不能为空'
}
}
},
policy_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '关联的保单ID',
references: {
model: 'policies',
key: 'id'
}
},
customer_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '客户ID',
references: {
model: 'users',
key: 'id'
}
},
claim_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,
comment: '理赔金额',
validate: {
min: {
args: [0],
msg: '理赔金额不能小于0'
}
}
},
claim_date: {
type: DataTypes.DATE,
allowNull: false,
comment: '理赔发生日期'
},
incident_description: {
type: DataTypes.TEXT,
allowNull: false,
comment: '事故描述',
validate: {
notEmpty: {
msg: '事故描述不能为空'
}
}
},
claim_status: {
type: DataTypes.ENUM('pending', 'approved', 'rejected', 'processing', 'paid'),
allowNull: false,
defaultValue: 'pending',
comment: '理赔状态pending-待审核approved-已批准rejected-已拒绝processing-处理中paid-已支付'
},
review_notes: {
type: DataTypes.TEXT,
allowNull: true,
comment: '审核备注'
},
reviewer_id: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '审核人ID',
references: {
model: 'users',
key: 'id'
}
},
review_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '审核日期'
},
payment_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '支付日期'
},
supporting_documents: {
type: DataTypes.JSON,
allowNull: true,
comment: '支持文件JSON数组包含文件URL和描述'
},
created_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '创建人ID'
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '更新人ID'
}
}, {
tableName: 'claims',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
indexes: [
{
name: 'idx_claim_no',
fields: ['claim_no'],
unique: true
},
{
name: 'idx_claim_policy',
fields: ['policy_id']
},
{
name: 'idx_claim_customer',
fields: ['customer_id']
},
{
name: 'idx_claim_status',
fields: ['claim_status']
},
{
name: 'idx_claim_date',
fields: ['claim_date']
}
],
comment: '理赔表'
});
module.exports = Claim;

View File

@@ -1,86 +0,0 @@
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

@@ -1,217 +0,0 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const LivestockPolicy = sequelize.define('LivestockPolicy', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
comment: '生资保单ID'
},
policy_no: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
comment: '保单编号',
validate: {
notEmpty: {
msg: '保单编号不能为空'
}
}
},
livestock_type_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '牲畜类型ID',
references: {
model: 'livestock_types',
key: 'id'
}
},
policyholder_name: {
type: DataTypes.STRING(100),
allowNull: false,
comment: '投保人姓名',
validate: {
notEmpty: {
msg: '投保人姓名不能为空'
}
}
},
policyholder_id_card: {
type: DataTypes.STRING(18),
allowNull: false,
comment: '投保人身份证号',
validate: {
notEmpty: {
msg: '投保人身份证号不能为空'
}
}
},
policyholder_phone: {
type: DataTypes.STRING(20),
allowNull: false,
comment: '投保人手机号',
validate: {
notEmpty: {
msg: '投保人手机号不能为空'
}
}
},
policyholder_address: {
type: DataTypes.STRING(500),
allowNull: false,
comment: '投保人地址',
validate: {
notEmpty: {
msg: '投保人地址不能为空'
}
}
},
farm_name: {
type: DataTypes.STRING(200),
allowNull: true,
comment: '养殖场名称'
},
farm_address: {
type: DataTypes.STRING(500),
allowNull: true,
comment: '养殖场地址'
},
farm_license: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '养殖场许可证号'
},
livestock_count: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '投保牲畜数量',
validate: {
min: {
args: [1],
msg: '投保牲畜数量不能小于1'
}
}
},
unit_value: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
comment: '单头价值',
validate: {
min: {
args: [0],
msg: '单头价值不能小于0'
}
}
},
total_value: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,
comment: '总保额',
validate: {
min: {
args: [0],
msg: '总保额不能小于0'
}
}
},
premium_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,
comment: '保费金额',
validate: {
min: {
args: [0],
msg: '保费金额不能小于0'
}
}
},
start_date: {
type: DataTypes.DATE,
allowNull: false,
comment: '保险开始日期'
},
end_date: {
type: DataTypes.DATE,
allowNull: false,
comment: '保险结束日期'
},
policy_status: {
type: DataTypes.ENUM('active', 'expired', 'cancelled', 'suspended'),
allowNull: false,
defaultValue: 'active',
comment: '保单状态active-有效expired-已过期cancelled-已取消suspended-已暂停'
},
payment_status: {
type: DataTypes.ENUM('paid', 'unpaid', 'partial'),
allowNull: false,
defaultValue: 'unpaid',
comment: '支付状态paid-已支付unpaid-未支付partial-部分支付'
},
payment_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '支付日期'
},
policy_document_url: {
type: DataTypes.STRING(500),
allowNull: true,
comment: '保单文档URL'
},
notes: {
type: DataTypes.TEXT,
allowNull: true,
comment: '备注信息'
},
created_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '创建人ID',
references: {
model: 'users',
key: 'id'
}
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '更新人ID',
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'livestock_policies',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
indexes: [
{
name: 'idx_livestock_policy_no',
fields: ['policy_no'],
unique: true
},
{
name: 'idx_livestock_policy_policyholder',
fields: ['policyholder_name']
},
{
name: 'idx_livestock_policy_status',
fields: ['policy_status']
},
{
name: 'idx_livestock_policy_payment_status',
fields: ['payment_status']
},
{
name: 'idx_livestock_policy_dates',
fields: ['start_date', 'end_date']
}
],
comment: '生资保单表'
});
module.exports = LivestockPolicy;

View File

@@ -1,101 +0,0 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const LivestockType = sequelize.define('LivestockType', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
comment: '牲畜类型ID'
},
name: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
comment: '牲畜类型名称',
validate: {
notEmpty: {
msg: '牲畜类型名称不能为空'
}
}
},
code: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true,
comment: '牲畜类型代码'
},
description: {
type: DataTypes.TEXT,
allowNull: true,
comment: '牲畜类型描述'
},
unit_price_min: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
defaultValue: 0.00,
comment: '单头最低价值',
validate: {
min: {
args: [0],
msg: '单头最低价值不能小于0'
}
}
},
unit_price_max: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
defaultValue: 50000.00,
comment: '单头最高价值',
validate: {
min: {
args: [0],
msg: '单头最高价值不能小于0'
}
}
},
premium_rate: {
type: DataTypes.DECIMAL(5, 4),
allowNull: false,
defaultValue: 0.0050,
comment: '保险费率',
validate: {
min: {
args: [0],
msg: '保费费率不能小于0'
},
max: {
args: [1],
msg: '保费费率不能大于1'
}
}
},
status: {
type: DataTypes.ENUM('active', 'inactive'),
allowNull: false,
defaultValue: 'active',
comment: '状态'
}
}, {
tableName: 'livestock_types',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
indexes: [
{
name: 'idx_livestock_type_name',
fields: ['name']
},
{
name: 'idx_livestock_type_code',
fields: ['code']
},
{
name: 'idx_livestock_type_status',
fields: ['status']
}
],
comment: '牲畜类型表'
});
module.exports = LivestockType;

View File

@@ -1,85 +0,0 @@
const { sequelize } = require('../config/database');
const { DataTypes } = require('sequelize');
const Menu = sequelize.define('Menu', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false,
validate: {
len: [2, 50]
}
},
key: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
validate: {
len: [2, 50]
}
},
path: {
type: DataTypes.STRING(100),
allowNull: false,
validate: {
len: [1, 100]
}
},
icon: {
type: DataTypes.STRING(50),
allowNull: true
},
parent_id: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'menus',
key: 'id'
},
defaultValue: null
},
component: {
type: DataTypes.STRING(100),
allowNull: true
},
order: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
},
status: {
type: DataTypes.ENUM('active', 'inactive'),
defaultValue: 'active'
},
show: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
}, {
tableName: 'menus',
timestamps: true,
underscored: true,
indexes: [
{ fields: ['key'] },
{ fields: ['parent_id'] },
{ fields: ['status'] },
{ fields: ['order'] }
]
});
// 设置自关联
Menu.hasMany(Menu, {
as: 'children',
foreignKey: 'parent_id'
});
Menu.belongsTo(Menu, {
as: 'parent',
foreignKey: 'parent_id'
});
module.exports = Menu;

View File

@@ -1,42 +0,0 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const MenuPermission = sequelize.define('MenuPermission', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
comment: '关联ID'
},
menu_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '菜单ID'
},
permission_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '权限ID'
},
required: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
comment: '是否必需权限'
}
}, {
tableName: 'menu_permissions',
timestamps: true,
underscored: true,
indexes: [
{
fields: ['menu_id', 'permission_id'],
unique: true,
name: 'uk_menu_permission'
},
{ fields: ['menu_id'] },
{ fields: ['permission_id'] }
]
});
module.exports = MenuPermission;

View File

@@ -1,270 +0,0 @@
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

@@ -1,93 +0,0 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const Permission = sequelize.define('Permission', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
comment: '权限ID'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
comment: '权限名称',
validate: {
len: [2, 100]
}
},
code: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
comment: '权限代码',
validate: {
len: [2, 100],
is: /^[a-zA-Z0-9_:]+$/ // 只允许字母、数字、下划线和冒号
}
},
description: {
type: DataTypes.TEXT,
allowNull: true,
comment: '权限描述'
},
module: {
type: DataTypes.STRING(50),
allowNull: false,
comment: '所属模块',
validate: {
len: [2, 50]
}
},
type: {
type: DataTypes.ENUM('menu', 'operation'),
allowNull: false,
defaultValue: 'operation',
comment: '权限类型menu-菜单权限operation-操作权限'
},
parent_id: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '父权限ID'
},
status: {
type: DataTypes.ENUM('active', 'inactive'),
allowNull: false,
defaultValue: 'active',
comment: '状态'
},
sort_order: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
comment: '排序'
}
}, {
tableName: 'permissions',
timestamps: true,
underscored: true,
indexes: [
{ fields: ['code'], unique: true },
{ fields: ['module'] },
{ fields: ['type'] },
{ fields: ['parent_id'] },
{ fields: ['status'] }
]
});
// 定义自关联关系
Permission.hasMany(Permission, {
as: 'children',
foreignKey: 'parent_id',
onDelete: 'SET NULL',
onUpdate: 'CASCADE'
});
Permission.belongsTo(Permission, {
as: 'parent',
foreignKey: 'parent_id',
onDelete: 'SET NULL',
onUpdate: 'CASCADE'
});
module.exports = Permission;

View File

@@ -78,6 +78,31 @@ const Policy = sequelize.define('Policy', {
allowNull: false,
comment: '保险结束日期'
},
policyholder_name: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '投保人姓名'
},
insured_name: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '被保险人姓名'
},
phone: {
type: DataTypes.STRING(20),
allowNull: true,
comment: '联系电话'
},
email: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '电子邮箱'
},
address: {
type: DataTypes.STRING(500),
allowNull: true,
comment: '联系地址'
},
policy_status: {
type: DataTypes.ENUM('active', 'expired', 'cancelled', 'suspended'),
allowNull: false,