完善小程序
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
const { DeviceAlert, Device, User } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const logger = require('../utils/logger');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
/**
|
||||
* 设备预警控制器
|
||||
@@ -416,6 +417,103 @@ class DeviceAlertController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出设备预警列表到Excel
|
||||
*/
|
||||
static async exportToExcel(req, res) {
|
||||
try {
|
||||
const { alert_level, alert_type, status, is_read } = req.query;
|
||||
|
||||
// 构建查询条件
|
||||
const where = {};
|
||||
if (alert_level) where.alert_level = alert_level;
|
||||
if (alert_type) where.alert_type = alert_type;
|
||||
if (status) where.status = status;
|
||||
if (is_read !== undefined) where.is_read = is_read === 'true';
|
||||
|
||||
// 查询所有符合条件的数据
|
||||
const alerts = await DeviceAlert.findAll({
|
||||
where,
|
||||
include: [{
|
||||
model: Device,
|
||||
as: 'Device',
|
||||
attributes: ['device_name', 'device_number', 'installation_location']
|
||||
}],
|
||||
order: [['alert_time', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
// 状态映射
|
||||
const levelMap = {
|
||||
info: '信息',
|
||||
warning: '警告',
|
||||
critical: '严重'
|
||||
};
|
||||
|
||||
const typeMap = {
|
||||
temperature: '温度异常',
|
||||
humidity: '湿度异常',
|
||||
offline: '设备离线',
|
||||
maintenance: '设备维护'
|
||||
};
|
||||
|
||||
const statusMap = {
|
||||
pending: '待处理',
|
||||
processing: '处理中',
|
||||
resolved: '已解决'
|
||||
};
|
||||
|
||||
// 准备导出数据
|
||||
const exportData = alerts.map(alert => ({
|
||||
alert_title: alert.alert_title || '',
|
||||
alert_level: ExcelExport.formatStatus(alert.alert_level, levelMap),
|
||||
alert_type: ExcelExport.formatStatus(alert.alert_type, typeMap),
|
||||
alert_content: alert.alert_content || '',
|
||||
device_name: alert.Device?.device_name || '',
|
||||
device_number: alert.Device?.device_number || '',
|
||||
installation_location: alert.Device?.installation_location || '',
|
||||
status: ExcelExport.formatStatus(alert.status, statusMap),
|
||||
is_read: alert.is_read ? '已读' : '未读',
|
||||
alert_time: ExcelExport.formatDate(alert.alert_time),
|
||||
read_time: ExcelExport.formatDate(alert.read_time)
|
||||
}));
|
||||
|
||||
// 定义列
|
||||
const columns = [
|
||||
{ header: '预警标题', key: 'alert_title', width: 30 },
|
||||
{ header: '预警级别', key: 'alert_level', width: 12 },
|
||||
{ header: '预警类型', key: 'alert_type', width: 15 },
|
||||
{ header: '预警内容', key: 'alert_content', width: 40 },
|
||||
{ header: '设备名称', key: 'device_name', width: 20 },
|
||||
{ header: '设备编号', key: 'device_number', width: 20 },
|
||||
{ header: '安装位置', key: 'installation_location', width: 30 },
|
||||
{ header: '处理状态', key: 'status', width: 12 },
|
||||
{ header: '阅读状态', key: 'is_read', width: 10 },
|
||||
{ header: '预警时间', key: 'alert_time', width: 20 },
|
||||
{ header: '阅读时间', key: 'read_time', width: 20 }
|
||||
];
|
||||
|
||||
// 生成Excel
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '设备预警列表');
|
||||
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=device_alerts_${Date.now()}.xlsx`);
|
||||
|
||||
// 发送文件
|
||||
res.send(buffer);
|
||||
|
||||
} catch (error) {
|
||||
logger.error('导出设备预警失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '导出失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DeviceAlertController;
|
||||
@@ -2,6 +2,7 @@ const InstallationTask = require('../models/InstallationTask');
|
||||
const User = require('../models/User');
|
||||
const { Op, sequelize } = require('sequelize');
|
||||
const logger = require('../utils/logger');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
class InstallationTaskController {
|
||||
|
||||
@@ -472,6 +473,99 @@ class InstallationTaskController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 导出待安装任务列表到Excel
|
||||
async exportToExcel(req, res) {
|
||||
try {
|
||||
const { policyNumber, keyword } = req.query;
|
||||
|
||||
// 构建查询条件(使用数据库字段名,因为raw:true模式)
|
||||
const whereConditions = {};
|
||||
|
||||
if (policyNumber) {
|
||||
whereConditions.policy_number = { [Op.like]: `%${policyNumber}%` };
|
||||
}
|
||||
|
||||
// 关键字搜索
|
||||
if (keyword) {
|
||||
whereConditions[Op.or] = [
|
||||
{ application_number: { [Op.like]: `%${keyword}%` } },
|
||||
{ policy_number: { [Op.like]: `%${keyword}%` } },
|
||||
{ customer_name: { [Op.like]: `%${keyword}%` } },
|
||||
{ installation_address: { [Op.like]: `%${keyword}%` } }
|
||||
];
|
||||
}
|
||||
|
||||
// 查询所有符合条件的数据
|
||||
const tasks = await InstallationTask.findAll({
|
||||
where: whereConditions,
|
||||
order: [['created_at', 'DESC']]
|
||||
});
|
||||
|
||||
console.log(`导出查询到 ${tasks.length} 条数据`);
|
||||
|
||||
// 准备导出数据(Sequelize自动转换为驼峰格式)
|
||||
const exportData = tasks.map(task => {
|
||||
const data = task.toJSON ? task.toJSON() : task;
|
||||
return {
|
||||
applicationNumber: data.applicationNumber || '',
|
||||
policyNumber: data.policyNumber || '',
|
||||
productName: data.productName || '',
|
||||
customerName: data.customerName || '',
|
||||
idType: data.idType || '',
|
||||
idNumber: data.idNumber || '',
|
||||
livestockSupplyType: data.livestockSupplyType || '',
|
||||
installationStatus: data.installationStatus || '',
|
||||
priority: data.priority || '',
|
||||
installationAddress: data.installationAddress || '',
|
||||
contactPhone: data.contactPhone || '',
|
||||
taskGeneratedTime: ExcelExport.formatDate(data.taskGeneratedTime),
|
||||
installationCompletedTime: ExcelExport.formatDate(data.installationCompletedTime),
|
||||
createdAt: ExcelExport.formatDate(data.created_at || data.createdAt),
|
||||
updatedAt: ExcelExport.formatDate(data.updated_at || data.updatedAt)
|
||||
};
|
||||
});
|
||||
|
||||
// 定义列
|
||||
const columns = [
|
||||
{ header: '申请单号', key: 'applicationNumber', width: 20 },
|
||||
{ header: '保单编号', key: 'policyNumber', width: 20 },
|
||||
{ header: '产品名称', key: 'productName', width: 25 },
|
||||
{ header: '客户姓名', key: 'customerName', width: 15 },
|
||||
{ header: '证件类型', key: 'idType', width: 12 },
|
||||
{ header: '证件号码', key: 'idNumber', width: 20 },
|
||||
{ header: '养殖生资种类', key: 'livestockSupplyType', width: 20 },
|
||||
{ header: '安装状态', key: 'installationStatus', width: 12 },
|
||||
{ header: '优先级', key: 'priority', width: 10 },
|
||||
{ header: '安装地址', key: 'installationAddress', width: 30 },
|
||||
{ header: '联系电话', key: 'contactPhone', width: 15 },
|
||||
{ header: '任务生成时间', key: 'taskGeneratedTime', width: 20 },
|
||||
{ header: '安装完成时间', key: 'installationCompletedTime', width: 20 },
|
||||
{ header: '创建时间', key: 'createdAt', width: 20 },
|
||||
{ header: '更新时间', key: 'updatedAt', width: 20 }
|
||||
];
|
||||
|
||||
// 生成Excel
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '待安装任务列表');
|
||||
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=installation_tasks_${Date.now()}.xlsx`);
|
||||
|
||||
// 发送文件
|
||||
res.send(buffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('导出待安装任务失败:', error);
|
||||
logger.error('导出待安装任务失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
status: 'error',
|
||||
message: '导出失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new InstallationTaskController();
|
||||
@@ -1,6 +1,7 @@
|
||||
const { InsuranceType } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const responseFormat = require('../utils/response');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
// 获取保险类型列表
|
||||
const getInsuranceTypes = async (req, res) => {
|
||||
@@ -457,11 +458,59 @@ const updateInsuranceTypeStatus = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 导出保险类型列表到Excel
|
||||
const exportToExcel = async (req, res) => {
|
||||
try {
|
||||
const { name, status } = req.query;
|
||||
|
||||
const where = {};
|
||||
if (name) where.name = { [Op.like]: `%${name}%` };
|
||||
if (status) where.status = status;
|
||||
|
||||
const types = await InsuranceType.findAll({
|
||||
where,
|
||||
order: [['created_at', 'DESC']],
|
||||
raw: true
|
||||
});
|
||||
|
||||
const statusMap = { active: '启用', inactive: '停用' };
|
||||
|
||||
const exportData = types.map(type => ({
|
||||
name: type.name || '',
|
||||
coverage_amount: type.coverage_amount || 0,
|
||||
premium_rate: type.premium_rate || 0,
|
||||
applicable_livestock: type.applicable_livestock || '',
|
||||
description: type.description || '',
|
||||
status: ExcelExport.formatStatus(type.status, statusMap),
|
||||
created_at: ExcelExport.formatDate(type.created_at)
|
||||
}));
|
||||
|
||||
const columns = [
|
||||
{ header: '险种名称', key: 'name', width: 20 },
|
||||
{ header: '保额', key: 'coverage_amount', width: 15 },
|
||||
{ header: '费率', key: 'premium_rate', width: 10 },
|
||||
{ header: '适用牲畜', key: 'applicable_livestock', width: 20 },
|
||||
{ header: '描述', key: 'description', width: 40 },
|
||||
{ header: '状态', key: 'status', width: 10 },
|
||||
{ header: '创建时间', key: 'created_at', width: 20 }
|
||||
];
|
||||
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '保险类型列表');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=insurance_types_${Date.now()}.xlsx`);
|
||||
res.send(buffer);
|
||||
} catch (error) {
|
||||
console.error('导出保险类型失败:', error);
|
||||
res.status(500).json(responseFormat.error('导出失败'));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getInsuranceTypes,
|
||||
getInsuranceTypeById,
|
||||
createInsuranceType,
|
||||
updateInsuranceType,
|
||||
deleteInsuranceType,
|
||||
updateInsuranceTypeStatus
|
||||
updateInsuranceTypeStatus,
|
||||
exportToExcel
|
||||
};
|
||||
@@ -4,6 +4,7 @@ const LivestockType = require('../models/LivestockType');
|
||||
const User = require('../models/User');
|
||||
const responseFormat = require('../utils/response');
|
||||
const { Op } = require('sequelize');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
// 获取生资理赔列表
|
||||
const getLivestockClaims = async (req, res) => {
|
||||
@@ -540,6 +541,66 @@ const deleteLivestockClaim = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 导出理赔列表到Excel
|
||||
const exportToExcel = async (req, res) => {
|
||||
try {
|
||||
const { claim_number, claimant_name, 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;
|
||||
|
||||
const claims = await LivestockClaim.findAll({
|
||||
where,
|
||||
include: [{
|
||||
model: LivestockPolicy,
|
||||
as: 'policy',
|
||||
attributes: ['policy_number']
|
||||
}],
|
||||
order: [['createdAt', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
const statusMap = { pending: '待审核', approved: '已批准', rejected: '已拒绝', settled: '已理赔' };
|
||||
|
||||
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 columns = [
|
||||
{ header: '理赔编号', key: 'claim_number', width: 20 },
|
||||
{ header: '保单编号', key: 'policy_number', width: 20 },
|
||||
{ header: '理赔人', key: 'claimant_name', width: 15 },
|
||||
{ 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 }
|
||||
];
|
||||
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '理赔列表');
|
||||
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);
|
||||
res.status(500).json(responseFormat.error('导出失败'));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getLivestockClaims,
|
||||
createLivestockClaim,
|
||||
@@ -548,5 +609,6 @@ module.exports = {
|
||||
deleteLivestockClaim,
|
||||
reviewLivestockClaim,
|
||||
updateLivestockClaimPayment,
|
||||
getLivestockClaimStats
|
||||
getLivestockClaimStats,
|
||||
exportToExcel
|
||||
};
|
||||
@@ -3,6 +3,7 @@ const LivestockType = require('../models/LivestockType');
|
||||
const User = require('../models/User');
|
||||
const responseFormat = require('../utils/response');
|
||||
const { Op } = require('sequelize');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
// 获取生资保单列表
|
||||
const getLivestockPolicies = async (req, res) => {
|
||||
@@ -337,6 +338,69 @@ const deleteLivestockPolicy = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 导出生资保单列表到Excel
|
||||
const exportToExcel = async (req, res) => {
|
||||
try {
|
||||
const { policy_no, farmer_name, policy_status } = req.query;
|
||||
|
||||
const where = {};
|
||||
if (policy_no) where.policy_no = { [Op.like]: `%${policy_no}%` };
|
||||
if (farmer_name) where.farmer_name = { [Op.like]: `%${farmer_name}%` };
|
||||
if (policy_status) where.policy_status = policy_status;
|
||||
|
||||
const policies = await LivestockPolicy.findAll({
|
||||
where,
|
||||
include: [{
|
||||
model: LivestockType,
|
||||
as: 'livestockType',
|
||||
attributes: ['name']
|
||||
}],
|
||||
order: [['created_at', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
const statusMap = { active: '生效中', pending: '待生效', expired: '已过期', cancelled: '已取消' };
|
||||
const paymentMap = { unpaid: '未支付', paid: '已支付', partial: '部分支付' };
|
||||
|
||||
const exportData = policies.map(policy => ({
|
||||
policy_no: policy.policy_no || '',
|
||||
farmer_name: policy.farmer_name || '',
|
||||
farmer_phone: policy.farmer_phone || '',
|
||||
livestock_type: policy.livestockType?.name || '',
|
||||
insured_amount: policy.insured_amount || 0,
|
||||
premium_amount: policy.premium_amount || 0,
|
||||
policy_status: ExcelExport.formatStatus(policy.policy_status, statusMap),
|
||||
payment_status: ExcelExport.formatStatus(policy.payment_status, paymentMap),
|
||||
start_date: ExcelExport.formatDate(policy.start_date),
|
||||
end_date: ExcelExport.formatDate(policy.end_date),
|
||||
created_at: ExcelExport.formatDate(policy.created_at)
|
||||
}));
|
||||
|
||||
const columns = [
|
||||
{ header: '保单号', key: 'policy_no', width: 20 },
|
||||
{ header: '农户姓名', key: 'farmer_name', width: 15 },
|
||||
{ header: '联系电话', key: 'farmer_phone', width: 15 },
|
||||
{ header: '牲畜类型', key: 'livestock_type', width: 15 },
|
||||
{ header: '保额', key: 'insured_amount', width: 15 },
|
||||
{ header: '保费', key: 'premium_amount', width: 15 },
|
||||
{ header: '保单状态', key: 'policy_status', width: 12 },
|
||||
{ header: '支付状态', key: 'payment_status', width: 12 },
|
||||
{ header: '起始日期', key: 'start_date', width: 15 },
|
||||
{ header: '结束日期', key: 'end_date', width: 15 },
|
||||
{ header: '创建时间', key: 'created_at', width: 20 }
|
||||
];
|
||||
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '生资保单列表');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=livestock_policies_${Date.now()}.xlsx`);
|
||||
res.send(buffer);
|
||||
} catch (error) {
|
||||
console.error('导出生资保单失败:', error);
|
||||
res.status(500).json(responseFormat.error('导出失败'));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getLivestockPolicies,
|
||||
createLivestockPolicy,
|
||||
@@ -344,5 +408,6 @@ module.exports = {
|
||||
updateLivestockPolicy,
|
||||
updateLivestockPolicyStatus,
|
||||
deleteLivestockPolicy,
|
||||
getLivestockPolicyStats
|
||||
getLivestockPolicyStats,
|
||||
exportToExcel
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
const { OperationLog, User } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const ExcelJS = require('exceljs');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
/**
|
||||
* 操作日志控制器
|
||||
@@ -339,6 +340,99 @@ class OperationLogController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出操作日志列表到Excel
|
||||
*/
|
||||
async exportToExcel(req, res) {
|
||||
try {
|
||||
const { username, operation_type, operation_module, startDate, endDate } = req.query;
|
||||
|
||||
// 构建查询条件
|
||||
const where = {};
|
||||
if (username) {
|
||||
where['$User.username$'] = { [Op.like]: `%${username}%` };
|
||||
}
|
||||
if (operation_type) where.operation_type = operation_type;
|
||||
if (operation_module) where.operation_module = operation_module;
|
||||
if (startDate && endDate) {
|
||||
where.created_at = {
|
||||
[Op.between]: [new Date(startDate), new Date(endDate)]
|
||||
};
|
||||
}
|
||||
|
||||
// 查询所有符合条件的数据
|
||||
const logs = await OperationLog.findAll({
|
||||
where,
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'User',
|
||||
attributes: ['username', 'real_name']
|
||||
}],
|
||||
order: [['created_at', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
// 操作类型映射
|
||||
const typeMap = {
|
||||
login: '登录',
|
||||
logout: '登出',
|
||||
create: '创建',
|
||||
update: '更新',
|
||||
delete: '删除',
|
||||
view: '查看',
|
||||
export: '导出'
|
||||
};
|
||||
|
||||
const statusMap = {
|
||||
success: '成功',
|
||||
failure: '失败'
|
||||
};
|
||||
|
||||
// 准备导出数据
|
||||
const exportData = logs.map(log => ({
|
||||
username: log.User?.username || '',
|
||||
real_name: log.User?.real_name || '',
|
||||
operation_type: ExcelExport.formatStatus(log.operation_type, typeMap),
|
||||
operation_module: log.operation_module || '',
|
||||
operation_desc: log.operation_desc || '',
|
||||
ip_address: log.ip_address || '',
|
||||
status: ExcelExport.formatStatus(log.status, statusMap),
|
||||
created_at: ExcelExport.formatDate(log.created_at)
|
||||
}));
|
||||
|
||||
// 定义列
|
||||
const columns = [
|
||||
{ header: '用户名', key: 'username', width: 15 },
|
||||
{ header: '真实姓名', key: 'real_name', width: 15 },
|
||||
{ header: '操作类型', key: 'operation_type', width: 12 },
|
||||
{ header: '操作模块', key: 'operation_module', width: 20 },
|
||||
{ header: '操作描述', key: 'operation_desc', width: 40 },
|
||||
{ header: 'IP地址', key: 'ip_address', width: 20 },
|
||||
{ header: '状态', key: 'status', width: 10 },
|
||||
{ header: '操作时间', key: 'created_at', width: 20 }
|
||||
];
|
||||
|
||||
// 生成Excel
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '操作日志');
|
||||
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=operation_logs_${Date.now()}.xlsx`);
|
||||
|
||||
// 发送文件
|
||||
res.send(buffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('导出操作日志失败:', error);
|
||||
res.status(500).json({
|
||||
status: 'error',
|
||||
message: '导出失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new OperationLogController();
|
||||
@@ -1,6 +1,7 @@
|
||||
const { Policy, InsuranceApplication, InsuranceType, User } = require('../models');
|
||||
const responseFormat = require('../utils/response');
|
||||
const { Op } = require('sequelize');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
// 获取保单列表
|
||||
const getPolicies = async (req, res) => {
|
||||
@@ -363,6 +364,64 @@ const deletePolicy = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 导出保单列表到Excel
|
||||
const exportToExcel = async (req, res) => {
|
||||
try {
|
||||
const { policy_number, policyholder_name, status } = req.query;
|
||||
|
||||
const where = {};
|
||||
if (policy_number) where.policy_number = { [Op.like]: `%${policy_number}%` };
|
||||
if (policyholder_name) where.policyholder_name = { [Op.like]: `%${policyholder_name}%` };
|
||||
if (status) where.status = status;
|
||||
|
||||
const policies = await Policy.findAll({
|
||||
where,
|
||||
include: [{
|
||||
model: InsuranceType,
|
||||
as: 'InsuranceType',
|
||||
attributes: ['name']
|
||||
}],
|
||||
order: [['created_at', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
const statusMap = { active: '生效中', pending: '待生效', expired: '已过期', cancelled: '已取消' };
|
||||
|
||||
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 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 },
|
||||
{ header: '状态', key: 'status', width: 12 },
|
||||
{ header: '创建时间', key: 'created_at', width: 20 }
|
||||
];
|
||||
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '保单列表');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=policies_${Date.now()}.xlsx`);
|
||||
res.send(buffer);
|
||||
} catch (error) {
|
||||
console.error('导出保单失败:', error);
|
||||
res.status(500).json(responseFormat.error('导出失败'));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getPolicies,
|
||||
createPolicy,
|
||||
@@ -370,5 +429,6 @@ module.exports = {
|
||||
updatePolicy,
|
||||
updatePolicyStatus,
|
||||
deletePolicy,
|
||||
getPolicyStats
|
||||
getPolicyStats,
|
||||
exportToExcel
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
const { SupervisoryTask, User } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
/**
|
||||
* 监管任务控制器
|
||||
@@ -522,6 +523,93 @@ class SupervisoryTaskController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出监管任务列表到Excel
|
||||
*/
|
||||
static async exportToExcel(req, res) {
|
||||
try {
|
||||
const { policyNumber, customerName } = req.query;
|
||||
|
||||
// 构建查询条件
|
||||
const where = {};
|
||||
|
||||
if (policyNumber) {
|
||||
where.policyNumber = { [Op.like]: `%${policyNumber}%` };
|
||||
}
|
||||
|
||||
if (customerName) {
|
||||
where.customerName = { [Op.like]: `%${customerName}%` };
|
||||
}
|
||||
|
||||
// 查询所有符合条件的数据
|
||||
const tasks = await SupervisoryTask.findAll({
|
||||
where,
|
||||
order: [['createdAt', 'DESC']],
|
||||
raw: true
|
||||
});
|
||||
|
||||
// 状态映射
|
||||
const statusMap = {
|
||||
pending: '待处理',
|
||||
processing: '处理中',
|
||||
completed: '已完成',
|
||||
rejected: '已拒绝'
|
||||
};
|
||||
|
||||
const priorityMap = {
|
||||
low: '低',
|
||||
medium: '中',
|
||||
high: '高',
|
||||
urgent: '紧急'
|
||||
};
|
||||
|
||||
// 准备导出数据
|
||||
const exportData = tasks.map(task => ({
|
||||
policyNumber: task.policyNumber || '',
|
||||
customerName: task.customerName || '',
|
||||
productName: task.productName || '',
|
||||
insurancePeriod: task.insurancePeriod || '',
|
||||
applicableAmount: task.applicableAmount || '',
|
||||
taskStatus: ExcelExport.formatStatus(task.taskStatus, statusMap),
|
||||
priority: ExcelExport.formatStatus(task.priority, priorityMap),
|
||||
createdAt: ExcelExport.formatDate(task.createdAt),
|
||||
updatedAt: ExcelExport.formatDate(task.updatedAt)
|
||||
}));
|
||||
|
||||
// 定义列
|
||||
const columns = [
|
||||
{ header: '保单编号', key: 'policyNumber', width: 20 },
|
||||
{ header: '客户姓名', key: 'customerName', width: 15 },
|
||||
{ header: '产品名称', key: 'productName', width: 25 },
|
||||
{ header: '保险期间', key: 'insurancePeriod', width: 25 },
|
||||
{ header: '适用金额', key: 'applicableAmount', width: 15 },
|
||||
{ header: '任务状态', key: 'taskStatus', width: 12 },
|
||||
{ header: '优先级', key: 'priority', width: 12 },
|
||||
{ header: '创建时间', key: 'createdAt', width: 20 },
|
||||
{ header: '更新时间', key: 'updatedAt', width: 20 }
|
||||
];
|
||||
|
||||
// 生成Excel
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '监管任务列表');
|
||||
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=supervision_tasks_${Date.now()}.xlsx`);
|
||||
|
||||
// 发送文件
|
||||
res.send(buffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('导出监管任务失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
status: 'error',
|
||||
message: '导出失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SupervisoryTaskController;
|
||||
@@ -2,6 +2,7 @@ const { User, Role } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const responseFormat = require('../utils/response');
|
||||
const crypto = require('crypto');
|
||||
const ExcelExport = require('../utils/excelExport');
|
||||
|
||||
// 获取用户列表
|
||||
const getUsers = async (req, res) => {
|
||||
@@ -486,6 +487,84 @@ const getFixedTokenInfo = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 导出用户列表到Excel
|
||||
const exportToExcel = async (req, res) => {
|
||||
try {
|
||||
const { search, status } = req.query;
|
||||
|
||||
const whereClause = {};
|
||||
if (search) {
|
||||
whereClause[Op.or] = [
|
||||
{ username: { [Op.like]: `%${search}%` } },
|
||||
{ real_name: { [Op.like]: `%${search}%` } },
|
||||
{ email: { [Op.like]: `%${search}%` } },
|
||||
{ phone: { [Op.like]: `%${search}%` } }
|
||||
];
|
||||
}
|
||||
if (status) whereClause.status = status;
|
||||
|
||||
// 查询所有符合条件的数据
|
||||
const users = await User.findAll({
|
||||
where: whereClause,
|
||||
include: [{
|
||||
model: Role,
|
||||
as: 'role',
|
||||
attributes: ['name']
|
||||
}],
|
||||
order: [['created_at', 'DESC']],
|
||||
raw: true,
|
||||
nest: true
|
||||
});
|
||||
|
||||
// 状态映射
|
||||
const statusMap = {
|
||||
active: '活跃',
|
||||
inactive: '禁用',
|
||||
suspended: '暂停'
|
||||
};
|
||||
|
||||
// 准备导出数据
|
||||
const exportData = users.map(user => ({
|
||||
id: user.id || '',
|
||||
username: user.username || '',
|
||||
real_name: user.real_name || '',
|
||||
email: user.email || '',
|
||||
phone: user.phone || '',
|
||||
role_name: user.role?.name || '',
|
||||
status: ExcelExport.formatStatus(user.status, statusMap),
|
||||
created_at: ExcelExport.formatDate(user.created_at),
|
||||
updated_at: ExcelExport.formatDate(user.updated_at)
|
||||
}));
|
||||
|
||||
// 定义列
|
||||
const columns = [
|
||||
{ header: 'ID', key: 'id', width: 10 },
|
||||
{ header: '用户名', key: 'username', width: 15 },
|
||||
{ header: '真实姓名', key: 'real_name', width: 15 },
|
||||
{ header: '邮箱', key: 'email', width: 25 },
|
||||
{ header: '手机号', key: 'phone', width: 15 },
|
||||
{ header: '角色', key: 'role_name', width: 12 },
|
||||
{ header: '状态', key: 'status', width: 10 },
|
||||
{ header: '创建时间', key: 'created_at', width: 20 },
|
||||
{ header: '更新时间', key: 'updated_at', width: 20 }
|
||||
];
|
||||
|
||||
// 生成Excel
|
||||
const buffer = await ExcelExport.exportToExcel(exportData, columns, '用户列表');
|
||||
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename=users_${Date.now()}.xlsx`);
|
||||
|
||||
// 发送文件
|
||||
res.send(buffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('导出用户列表失败:', error);
|
||||
res.status(500).json(responseFormat.error('导出失败'));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getUsers,
|
||||
getUser,
|
||||
@@ -500,5 +579,6 @@ module.exports = {
|
||||
generateFixedToken,
|
||||
regenerateFixedToken,
|
||||
deleteFixedToken,
|
||||
getFixedTokenInfo
|
||||
getFixedTokenInfo,
|
||||
exportToExcel
|
||||
};
|
||||
Reference in New Issue
Block a user