完善保险端

This commit is contained in:
xuqiuyun
2025-10-11 08:59:57 +08:00
parent 9b8d177e34
commit 434fa135d1
8 changed files with 461 additions and 161 deletions

View File

@@ -315,9 +315,10 @@ const getInsuranceCategories = async (req, res) => {
// 导出保险申请数据
const exportApplications = async (req, res) => {
try {
const ExcelJS = require('exceljs');
const {
page = 1,
limit = 1000,
limit = 10000, // 增加导出数量限制
applicantName,
insuranceType,
insuranceCategory,
@@ -344,13 +345,15 @@ const exportApplications = async (req, res) => {
include: [
{
model: InsuranceType,
as: 'insuranceTypeInfo',
attributes: ['name', 'description']
as: 'insurance_type',
attributes: ['id', 'name', 'description'],
required: false
},
{
model: User,
as: 'createdByUser',
attributes: ['username', 'real_name']
as: 'reviewer',
attributes: ['id', 'username', 'real_name'],
required: false
}
],
order: [['created_at', 'DESC']],
@@ -358,38 +361,101 @@ const exportApplications = async (req, res) => {
offset: (parseInt(page) - 1) * parseInt(limit)
});
// 简单的CSV格式导出
const csvHeader = '申请编号,申请人姓名,身份证号,联系电话,参保类型,保险类型,保险金额,保险期限,地址,状态,申请时间,备注\n';
const csvData = applications.map(app => {
const statusMap = {
'pending': '待审核',
'initial_approved': '初审通过',
'under_review': '复审中',
'approved': '已通过',
'rejected': '已拒绝'
};
return [
app.application_number || '',
app.applicant_name || '',
app.id_card || '',
app.phone || '',
app.insurance_category || '',
app.insurance_type || '',
app.insurance_amount || '',
app.insurance_period || '',
app.address || '',
statusMap[app.status] || app.status,
app.created_at ? new Date(app.created_at).toLocaleString('zh-CN') : '',
app.remarks || ''
].map(field => `"${String(field).replace(/"/g, '""')}"`).join(',');
}).join('\n');
// 将Sequelize实例转换为纯对象
const plainApplications = applications.map(app => app.toJSON());
const csvContent = csvHeader + csvData;
// 创建Excel工作簿
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('保险申请列表');
// 状态映射
const statusMap = {
'pending': '待审核',
'initial_approved': '初审通过',
'under_review': '复审中',
'approved': '已通过',
'rejected': '已拒绝'
};
// 定义列(包含所有字段)
worksheet.columns = [
{ header: 'ID', key: 'id', width: 8 },
{ header: '申请编号', key: 'application_no', width: 18 },
{ header: '客户姓名', key: 'customer_name', width: 12 },
{ header: '身份证号', key: 'customer_id_card', width: 20 },
{ header: '联系电话', key: 'customer_phone', width: 15 },
{ header: '客户地址', key: 'customer_address', width: 30 },
{ header: '参保类型', key: 'insurance_category', width: 12 },
{ header: '保险类型ID', key: 'insurance_type_id', width: 12 },
{ header: '保险类型名称', key: 'insurance_type_name', width: 15 },
{ header: '保险类型说明', key: 'insurance_type_description', width: 25 },
{ header: '申请数量', key: 'application_quantity', width: 12 },
{ header: '申请金额', key: 'application_amount', width: 15 },
{ header: '申请日期', key: 'application_date', width: 20 },
{ header: '状态', key: 'status', width: 12 },
{ header: '审核人ID', key: 'reviewer_id', width: 10 },
{ header: '审核人姓名', key: 'reviewer_name', width: 12 },
{ header: '审核日期', key: 'review_date', width: 20 },
{ header: '审核意见', key: 'review_notes', width: 30 },
{ header: '文档附件', key: 'documents', width: 30 },
{ header: '备注', key: 'remarks', width: 30 },
{ header: '创建时间', key: 'createdAt', width: 20 },
{ header: '更新时间', key: 'updatedAt', width: 20 }
];
// 设置表头样式
worksheet.getRow(1).font = { bold: true, size: 12 };
worksheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' };
// 添加数据行
plainApplications.forEach(app => {
worksheet.addRow({
id: app.id || '',
application_no: app.application_no || '',
customer_name: app.customer_name || '',
customer_id_card: app.customer_id_card || '',
customer_phone: app.customer_phone || '',
customer_address: app.customer_address || '',
insurance_category: app.insurance_category || '',
insurance_type_id: app.insurance_type_id || '',
insurance_type_name: app.insurance_type?.name || '',
insurance_type_description: app.insurance_type?.description || '',
application_quantity: app.application_quantity || '',
application_amount: app.application_amount || '',
application_date: app.application_date || '',
status: statusMap[app.status] || app.status || '',
reviewer_id: app.reviewer_id || '',
reviewer_name: app.reviewer?.real_name || '',
review_date: app.review_date || '',
review_notes: app.review_notes || '',
documents: app.documents || '',
remarks: app.remarks || '',
createdAt: app.createdAt || '',
updatedAt: app.updatedAt || ''
});
});
// 设置数据行样式
worksheet.eachRow((row, rowNumber) => {
if (rowNumber > 1) {
row.alignment = { vertical: 'middle', horizontal: 'left' };
}
});
// 生成Excel文件
const buffer = await workbook.xlsx.writeBuffer();
// 设置响应头
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', `attachment; filename="insurance_applications_${new Date().toISOString().slice(0, 10)}.xlsx"`);
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
res.setHeader('Content-Disposition', `attachment; filename="insurance_applications_${new Date().toISOString().slice(0, 10)}.csv"`);
res.send('\uFEFF' + csvContent); // 添加BOM以支持中文
// 发送文件
res.send(buffer);
} catch (error) {
console.error('导出保险申请数据错误:', error);
res.status(500).json(responseFormat.error('导出保险申请数据失败'));

View File

@@ -544,59 +544,144 @@ const deleteLivestockClaim = async (req, res) => {
// 导出理赔列表到Excel
const exportToExcel = async (req, res) => {
try {
const { claim_number, claimant_name, status } = req.query;
const ExcelJS = require('exceljs');
const { claim_no, reporter_name, claim_status } = req.query;
const where = {};
if (claim_number) where.claim_number = { [Op.like]: `%${claim_number}%` };
if (claimant_name) where.claimant_name = { [Op.like]: `%${claimant_name}%` };
if (status) where.status = status;
if (claim_no) where.claim_no = { [Op.like]: `%${claim_no}%` };
if (reporter_name) where.reporter_name = { [Op.like]: `%${reporter_name}%` };
if (claim_status) where.claim_status = claim_status;
const claims = await LivestockClaim.findAll({
where,
include: [{
model: LivestockPolicy,
as: 'policy',
attributes: ['policy_number']
}],
order: [['createdAt', 'DESC']],
raw: true,
nest: true
include: [
{
model: LivestockPolicy,
as: 'policy',
attributes: ['id', 'policy_no', 'policyholder_name'],
required: false
},
{
model: User,
as: 'reviewer',
attributes: ['id', 'real_name', 'username'],
required: false
},
{
model: User,
as: 'creator',
attributes: ['id', 'real_name', 'username'],
required: false
}
],
order: [['created_at', 'DESC']],
limit: 10000
});
const statusMap = { pending: '待审核', approved: '已批准', rejected: '已拒绝', settled: '已理赔' };
// 将Sequelize实例转换为纯对象
const plainClaims = claims.map(claim => claim.toJSON());
const exportData = claims.map(claim => ({
claim_number: claim.claim_number || '',
policy_number: claim.policy?.policy_number || '',
claimant_name: claim.claimant_name || '',
claim_amount: claim.claim_amount || 0,
approved_amount: claim.approved_amount || 0,
claim_reason: claim.claim_reason || '',
status: ExcelExport.formatStatus(claim.status, statusMap),
claim_date: ExcelExport.formatDate(claim.claim_date),
settled_date: ExcelExport.formatDate(claim.settled_date),
createdAt: ExcelExport.formatDate(claim.createdAt)
}));
// 状态映射
const statusMap = {
'pending': '待审核',
'investigating': '调查中',
'approved': '已批准',
'rejected': '已拒绝',
'paid': '已支付'
};
const columns = [
{ header: '理赔编号', key: 'claim_number', width: 20 },
{ header: '保单编号', key: 'policy_number', width: 20 },
{ header: '理赔人', key: 'claimant_name', width: 15 },
// 理赔类型映射
const claimTypeMap = {
'death': '死亡',
'disease': '疾病',
'accident': '意外事故',
'natural_disaster': '自然灾害'
};
// 创建Excel工作簿
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('生资理赔列表');
// 定义列(包含所有字段)
worksheet.columns = [
{ header: 'ID', key: 'id', width: 8 },
{ header: '理赔编号', key: 'claim_no', width: 18 },
{ header: '报案人姓名', key: 'reporter_name', width: 12 },
{ header: '联系电话', key: 'contact_phone', width: 15 },
{ header: '保单号', key: 'policy_no', width: 18 },
{ header: '保单持有人', key: 'policy_holder', width: 12 },
{ header: '理赔类型', key: 'claim_type', width: 12 },
{ header: '受影响数量', key: 'affected_count', width: 12 },
{ header: '理赔金额', key: 'claim_amount', width: 15 },
{ header: '批准金额', key: 'approved_amount', width: 15 },
{ header: '理赔原因', key: 'claim_reason', width: 30 },
{ header: '状态', key: 'status', width: 12 },
{ header: '理赔日期', key: 'claim_date', width: 15 },
{ header: '结算日期', key: 'settled_date', width: 15 },
{ header: '创建时间', key: 'createdAt', width: 20 }
{ header: '事故日期', key: 'incident_date', width: 20 },
{ header: '报案日期', key: 'report_date', width: 20 },
{ header: '事故描述', key: 'incident_description', width: 35 },
{ header: '事故地点', key: 'incident_location', width: 25 },
{ header: '理赔状态', key: 'claim_status', width: 12 },
{ header: '调查报告', key: 'investigation_report', width: 30 },
{ header: '审核人', key: 'reviewer_name', width: 12 },
{ header: '审核备注', key: 'review_notes', width: 30 },
{ header: '审核日期', key: 'review_date', width: 20 },
{ header: '赔付日期', key: 'payment_date', width: 20 },
{ header: '赔付金额', key: 'payment_amount', width: 15 },
{ header: '创建人', key: 'creator_name', width: 12 },
{ header: '创建时间', key: 'created_at', width: 20 },
{ header: '更新时间', key: 'updated_at', width: 20 }
];
const buffer = await ExcelExport.exportToExcel(exportData, columns, '理赔列表');
// 设置表头样式
worksheet.getRow(1).font = { bold: true, size: 12 };
worksheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' };
// 添加数据行
plainClaims.forEach(claim => {
worksheet.addRow({
id: claim.id || '',
claim_no: claim.claim_no || '',
reporter_name: claim.reporter_name || '',
contact_phone: claim.contact_phone || '',
policy_no: claim.policy_no || '',
policy_holder: claim.policy?.policyholder_name || '',
claim_type: claimTypeMap[claim.claim_type] || claim.claim_type || '',
affected_count: claim.affected_count || '',
claim_amount: claim.claim_amount || '',
incident_date: claim.incident_date || '',
report_date: claim.report_date || '',
incident_description: claim.incident_description || '',
incident_location: claim.incident_location || '',
claim_status: statusMap[claim.claim_status] || claim.claim_status || '',
investigation_report: claim.investigation_report || '',
reviewer_name: claim.reviewer?.real_name || '',
review_notes: claim.review_notes || '',
review_date: claim.review_date || '',
payment_date: claim.payment_date || '',
payment_amount: claim.payment_amount || '',
creator_name: claim.creator?.real_name || '',
created_at: claim.created_at || '',
updated_at: claim.updated_at || ''
});
});
// 设置数据行样式
worksheet.eachRow((row, rowNumber) => {
if (rowNumber > 1) {
row.alignment = { vertical: 'middle', horizontal: 'left' };
}
});
// 生成Excel文件
const buffer = await workbook.xlsx.writeBuffer();
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', `attachment; filename=livestock_claims_${Date.now()}.xlsx`);
res.send(buffer);
} catch (error) {
console.error('导出理赔记录失败:', error);
console.error('导出生资理赔记录失败:', error);
res.status(500).json(responseFormat.error('导出失败'));
}
};

View File

@@ -367,6 +367,7 @@ const deletePolicy = async (req, res) => {
// 导出保单列表到Excel
const exportToExcel = async (req, res) => {
try {
const ExcelJS = require('exceljs');
const { policy_number, policyholder_name, status } = req.query;
const where = {};
@@ -378,41 +379,94 @@ const exportToExcel = async (req, res) => {
where,
include: [{
model: InsuranceType,
as: 'InsuranceType',
attributes: ['name']
as: 'insurance_type', // 修正:使用正确的关联别名
attributes: ['id', 'name', 'description'],
required: false
}],
order: [['created_at', 'DESC']],
raw: true,
nest: true
limit: 10000
});
const statusMap = { active: '生效中', pending: '待生效', expired: '已过期', cancelled: '已取消' };
// 将Sequelize实例转换为纯对象
const plainPolicies = policies.map(policy => policy.toJSON());
const exportData = policies.map(policy => ({
policy_number: policy.policy_number || '',
policyholder_name: policy.policyholder_name || '',
insurance_type_name: policy.InsuranceType?.name || '',
coverage_amount: policy.coverage_amount || 0,
premium_amount: policy.premium_amount || 0,
start_date: ExcelExport.formatDate(policy.start_date),
end_date: ExcelExport.formatDate(policy.end_date),
status: ExcelExport.formatStatus(policy.status, statusMap),
created_at: ExcelExport.formatDate(policy.created_at)
}));
// 状态映射
const statusMap = {
'active': '生效中',
'pending': '待生效',
'expired': '已过期',
'cancelled': '已取消'
};
const columns = [
{ header: '保单编号', key: 'policy_number', width: 20 },
{ header: '投保人', key: 'policyholder_name', width: 15 },
{ header: '险种', key: 'insurance_type_name', width: 20 },
{ header: '保额', key: 'coverage_amount', width: 15 },
{ header: '保费', key: 'premium_amount', width: 15 },
{ header: '开始日期', key: 'start_date', width: 15 },
{ header: '结束日期', key: 'end_date', width: 15 },
// 创建Excel工作簿
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('保单列表');
// 定义列(包含所有字段)
worksheet.columns = [
{ header: 'ID', key: 'id', width: 8 },
{ header: '保单编号', key: 'policy_number', width: 18 },
{ header: '投保人姓名', key: 'policyholder_name', width: 15 },
{ header: '被保人姓名', key: 'insured_name', width: 15 },
{ header: '保险类型ID', key: 'insurance_type_id', width: 12 },
{ header: '保险类型名称', key: 'insurance_type_name', width: 18 },
{ header: '保险类型说明', key: 'insurance_type_description', width: 25 },
{ header: '保障金额', key: 'coverage_amount', width: 15 },
{ header: '保费金额', key: 'premium_amount', width: 15 },
{ header: '开始日期', key: 'start_date', width: 20 },
{ header: '结束日期', key: 'end_date', width: 20 },
{ header: '状态', key: 'status', width: 12 },
{ header: '创建时间', key: 'created_at', width: 20 }
{ header: '联系电话', key: 'phone', width: 15 },
{ header: '电子邮箱', key: 'email', width: 25 },
{ header: '地址', key: 'address', width: 30 },
{ header: '备注', key: 'remarks', width: 30 },
{ header: '创建时间', key: 'created_at', width: 20 },
{ header: '更新时间', key: 'updated_at', width: 20 }
];
const buffer = await ExcelExport.exportToExcel(exportData, columns, '保单列表');
// 设置表头样式
worksheet.getRow(1).font = { bold: true, size: 12 };
worksheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' };
// 添加数据行
plainPolicies.forEach(policy => {
worksheet.addRow({
id: policy.id || '',
policy_number: policy.policy_no || '', // 修正:使用 policy_no
policyholder_name: policy.policyholder_name || '',
insured_name: policy.insured_name || '',
insurance_type_id: policy.insurance_type_id || '',
insurance_type_name: policy.insurance_type?.name || '',
insurance_type_description: policy.insurance_type?.description || '',
coverage_amount: policy.coverage_amount || '',
premium_amount: policy.premium_amount || '',
start_date: policy.start_date || '',
end_date: policy.end_date || '',
status: statusMap[policy.policy_status] || policy.policy_status || '', // 修正:使用 policy_status
phone: policy.phone || '',
email: policy.email || '',
address: policy.address || '',
remarks: policy.remarks || '',
created_at: policy.created_at || '',
updated_at: policy.updated_at || ''
});
});
// 设置数据行样式
worksheet.eachRow((row, rowNumber) => {
if (rowNumber > 1) {
row.alignment = { vertical: 'middle', horizontal: 'left' };
}
});
// 生成Excel文件
const buffer = await workbook.xlsx.writeBuffer();
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', `attachment; filename=policies_${Date.now()}.xlsx`);
res.send(buffer);

View File

@@ -24,6 +24,22 @@ class SupervisoryTaskController {
sortOrder = 'DESC'
} = req.query;
// 状态映射:英文到中文
const statusMap = {
'pending': '待处理',
'processing': '处理中',
'completed': '已完成',
'rejected': '已取消'
};
// 优先级映射:英文到中文
const priorityMap = {
'low': '低',
'medium': '中',
'high': '高',
'urgent': '紧急'
};
// 构建查询条件
const where = {};
@@ -36,11 +52,13 @@ class SupervisoryTaskController {
}
if (taskStatus) {
where.taskStatus = taskStatus;
// 如果传入的是英文状态,转换为中文
where.taskStatus = statusMap[taskStatus] || taskStatus;
}
if (priority) {
where.priority = priority;
// 如果传入的是英文优先级,转换为中文
where.priority = priorityMap[priority] || priority;
}
// 日期范围筛选