修改养殖端小程序,保险前后端和小程序

This commit is contained in:
xuqiuyun
2025-09-19 18:13:07 +08:00
parent eb3c4604d3
commit 35db747d4f
89 changed files with 16231 additions and 1500 deletions

View File

@@ -0,0 +1,210 @@
const { User, Role, InsuranceApplication, Policy, Claim, InsuranceType } = require('../models');
const responseFormat = require('../utils/response');
const { Op } = require('sequelize');
// 获取数据览仓概览数据
const getOverview = async (req, res) => {
try {
const [
totalUsers,
totalApplications,
totalPolicies,
totalClaims,
activePolicies,
approvedClaims,
pendingClaims
] = await Promise.all([
User.count(),
InsuranceApplication.count(),
Policy.count(),
Claim.count(),
Policy.count({ where: { policy_status: 'active' } }),
Claim.count({ where: { claim_status: 'approved' } }),
Claim.count({ where: { claim_status: 'pending' } })
]);
res.json(responseFormat.success({
totalUsers,
totalApplications,
totalPolicies,
totalClaims,
activePolicies,
approvedClaims,
pendingClaims
}, '获取数据览仓概览成功'));
} catch (error) {
console.error('获取数据览仓概览错误:', error);
res.status(500).json(responseFormat.error('获取数据览仓概览失败'));
}
};
// 获取保险类型分布数据
const getInsuranceTypeDistribution = async (req, res) => {
try {
const types = await InsuranceType.findAll({
attributes: ['id', 'name', 'description'],
where: { status: 'active' }
});
const distribution = await Promise.all(
types.map(async type => {
const count = await InsuranceApplication.count({
where: { insurance_type_id: type.id }
});
return {
id: type.id,
name: type.name,
description: type.description,
count
};
})
);
res.json(responseFormat.success(distribution, '获取保险类型分布成功'));
} catch (error) {
console.error('获取保险类型分布错误:', error);
res.status(500).json(responseFormat.error('获取保险类型分布失败'));
}
};
// 获取申请状态分布数据
const getApplicationStatusDistribution = async (req, res) => {
try {
const [
pendingCount,
approvedCount,
rejectedCount,
underReviewCount
] = await Promise.all([
InsuranceApplication.count({ where: { status: 'pending' } }),
InsuranceApplication.count({ where: { status: 'approved' } }),
InsuranceApplication.count({ where: { status: 'rejected' } }),
InsuranceApplication.count({ where: { status: 'under_review' } })
]);
res.json(responseFormat.success([
{ status: 'pending', name: '待处理', count: pendingCount },
{ status: 'under_review', name: '审核中', count: underReviewCount },
{ status: 'approved', name: '已批准', count: approvedCount },
{ status: 'rejected', name: '已拒绝', count: rejectedCount }
], '获取申请状态分布成功'));
} catch (error) {
console.error('获取申请状态分布错误:', error);
res.status(500).json(responseFormat.error('获取申请状态分布失败'));
}
};
// 获取近7天趋势数据
const getTrendData = async (req, res) => {
try {
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
// 生成近7天的日期数组
const dateArray = [];
for (let i = 6; i >= 0; i--) {
const date = new Date(sevenDaysAgo);
date.setDate(date.getDate() + i);
dateArray.push(date.toISOString().split('T')[0]); // 格式化为YYYY-MM-DD
}
// 获取每天的新增数据
const dailyData = await Promise.all(
dateArray.map(async date => {
const startDate = new Date(`${date} 00:00:00`);
const endDate = new Date(`${date} 23:59:59`);
const [newApplications, newPolicies, newClaims] = await Promise.all([
InsuranceApplication.count({
where: {
created_at: {
[Op.between]: [startDate, endDate]
}
}
}),
Policy.count({
where: {
created_at: {
[Op.between]: [startDate, endDate]
}
}
}),
Claim.count({
where: {
created_at: {
[Op.between]: [startDate, endDate]
}
}
})
]);
return {
date,
newApplications,
newPolicies,
newClaims
};
})
);
res.json(responseFormat.success(dailyData, '获取趋势数据成功'));
} catch (error) {
console.error('获取趋势数据错误:', error);
res.status(500).json(responseFormat.error('获取趋势数据失败'));
}
};
// 获取赔付统计数据
const getClaimStats = async (req, res) => {
try {
const claims = await Claim.findAll({
attributes: ['id', 'claim_amount', 'policy_id'],
include: [{
model: Policy,
as: 'policy',
attributes: ['policy_no', 'insurance_type_id']
}]
});
// 按保险类型分组统计赔付金额
const typeStats = {};
claims.forEach(claim => {
const typeId = claim.policy?.insurance_type_id;
if (typeId) {
if (!typeStats[typeId]) {
typeStats[typeId] = { id: typeId, totalAmount: 0, count: 0 };
}
typeStats[typeId].totalAmount += parseFloat(claim.claim_amount || 0);
typeStats[typeId].count += 1;
}
});
// 获取保险类型名称
const typeIds = Object.keys(typeStats).map(id => parseInt(id));
const types = await InsuranceType.findAll({
attributes: ['id', 'name'],
where: { id: typeIds }
});
types.forEach(type => {
if (typeStats[type.id]) {
typeStats[type.id].name = type.name;
}
});
const result = Object.values(typeStats);
res.json(responseFormat.success(result, '获取赔付统计成功'));
} catch (error) {
console.error('获取赔付统计错误:', error);
res.status(500).json(responseFormat.error('获取赔付统计失败'));
}
};
module.exports = {
getOverview,
getInsuranceTypeDistribution,
getApplicationStatusDistribution,
getTrendData,
getClaimStats
};

View File

@@ -0,0 +1,161 @@
const { User, Role, Menu } = require('../models');
/**
* 获取菜单列表
* @param {Object} req - Express请求对象
* @param {Object} res - Express响应对象
*/
exports.getMenus = async (req, res) => {
try {
// 获取用户ID从JWT中解析或通过其他方式获取
const userId = req.user?.id; // 假设通过认证中间件解析后存在
// 如果没有用户ID返回基础菜单
if (!userId) {
const menus = await Menu.findAll({
where: {
parent_id: null,
show: true,
status: 'active'
},
include: [
{
model: Menu,
as: 'children',
where: {
show: true,
status: 'active'
},
required: false,
order: [['order', 'ASC']]
}
],
order: [['order', 'ASC']]
});
return res.json({
code: 200,
status: 'success',
data: menus,
message: '获取菜单成功'
});
}
// 获取用户信息和角色
const user = await User.findByPk(userId, {
include: [
{
model: Role,
attributes: ['id', 'name', 'permissions']
}
]
});
if (!user) {
return res.status(404).json({
code: 404,
status: 'error',
message: '用户不存在'
});
}
// 获取角色的权限列表
const userPermissions = user.Role?.permissions || [];
// 查询菜单,这里简化处理,实际应用中可能需要根据权限过滤
const menus = await Menu.findAll({
where: {
parent_id: null,
show: true,
status: 'active'
},
include: [
{
model: Menu,
as: 'children',
where: {
show: true,
status: 'active'
},
required: false,
order: [['order', 'ASC']]
}
],
order: [['order', 'ASC']]
});
// 这里可以添加根据权限过滤菜单的逻辑
// 简化示例,假设所有用户都能看到所有激活的菜单
return res.json({
code: 200,
status: 'success',
data: menus,
message: '获取菜单成功'
});
} catch (error) {
console.error('获取菜单失败:', error);
return res.status(500).json({
code: 500,
status: 'error',
message: '服务器内部错误'
});
}
};
/**
* 获取所有菜单(包括非激活状态,仅管理员可用)
* @param {Object} req - Express请求对象
* @param {Object} res - Express响应对象
*/
exports.getAllMenus = async (req, res) => {
try {
// 检查用户是否为管理员(简化示例)
const user = await User.findByPk(req.user?.id, {
include: [
{
model: Role,
attributes: ['id', 'name', 'permissions']
}
]
});
if (!user || !user.Role || !user.Role.permissions.includes('*:*')) {
return res.status(403).json({
code: 403,
status: 'error',
message: '没有权限查看所有菜单'
});
}
// 查询所有菜单
const menus = await Menu.findAll({
where: {
parent_id: null
},
include: [
{
model: Menu,
as: 'children',
required: false,
order: [['order', 'ASC']]
}
],
order: [['order', 'ASC']]
});
return res.json({
code: 200,
status: 'success',
data: menus,
message: '获取所有菜单成功'
});
} catch (error) {
console.error('获取所有菜单失败:', error);
return res.status(500).json({
code: 500,
status: 'error',
message: '服务器内部错误'
});
}
};