完善项目

This commit is contained in:
xuqiuyun
2025-09-28 17:58:43 +08:00
parent ec3f472641
commit 5b615473e0
59 changed files with 5428 additions and 593 deletions

View File

@@ -214,6 +214,84 @@ const swaggerDefinition = {
updated_at: { type: 'string', format: 'date-time', description: '更新时间' }
}
},
InsuranceType: {
type: 'object',
properties: {
id: { type: 'integer', description: '险种ID' },
name: { type: 'string', description: '险种名称' },
description: { type: 'string', description: '险种描述' },
applicable_livestock: { type: 'string', description: '适用牲畜类型' },
insurance_term: { type: 'integer', description: '保险期限(月)' },
policy_form: { type: 'string', description: '保单形式' },
coverage_amount_min: { type: 'number', format: 'decimal', description: '最低保额' },
coverage_amount_max: { type: 'number', format: 'decimal', description: '最高保额' },
premium_rate: { type: 'number', format: 'decimal', description: '保险费率' },
service_area: { type: 'string', description: '服务区域' },
add_time: { type: 'string', format: 'date-time', description: '添加时间' },
on_sale_status: { type: 'boolean', description: '在售状态' },
sort_order: { type: 'integer', description: '排序顺序' },
remarks: { type: 'string', description: '备注' },
status: { type: 'string', enum: ['active', 'inactive'], description: '险种状态' },
created_by: { type: 'integer', description: '创建人ID' },
updated_by: { type: 'integer', description: '更新人ID' },
created_at: { type: 'string', format: 'date-time', description: '创建时间' },
updated_at: { type: 'string', format: 'date-time', description: '更新时间' }
}
},
CreateInsuranceTypeRequest: {
type: 'object',
required: ['name', 'coverage_amount_min', 'coverage_amount_max', 'premium_rate'],
properties: {
name: { type: 'string', description: '险种名称', minLength: 1, maxLength: 100 },
description: { type: 'string', description: '险种描述' },
applicable_livestock: { type: 'string', description: '适用牲畜类型', maxLength: 100 },
insurance_term: { type: 'integer', description: '保险期限(月)', minimum: 1 },
policy_form: { type: 'string', description: '保单形式', maxLength: 50 },
coverage_amount_min: { type: 'number', format: 'decimal', description: '最低保额', minimum: 0 },
coverage_amount_max: { type: 'number', format: 'decimal', description: '最高保额', minimum: 0 },
premium_rate: { type: 'number', format: 'decimal', description: '保险费率', minimum: 0, maximum: 1 },
service_area: { type: 'string', description: '服务区域' },
add_time: { type: 'string', format: 'date-time', description: '添加时间' },
on_sale_status: { type: 'boolean', description: '在售状态', default: true },
sort_order: { type: 'integer', description: '排序顺序', default: 0 },
remarks: { type: 'string', description: '备注' },
status: { type: 'string', enum: ['active', 'inactive'], description: '险种状态', default: 'active' }
}
},
UpdateInsuranceTypeRequest: {
type: 'object',
properties: {
name: { type: 'string', description: '险种名称', minLength: 1, maxLength: 100 },
description: { type: 'string', description: '险种描述' },
applicable_livestock: { type: 'string', description: '适用牲畜类型', maxLength: 100 },
insurance_term: { type: 'integer', description: '保险期限(月)', minimum: 1 },
policy_form: { type: 'string', description: '保单形式', maxLength: 50 },
coverage_amount_min: { type: 'number', format: 'decimal', description: '最低保额', minimum: 0 },
coverage_amount_max: { type: 'number', format: 'decimal', description: '最高保额', minimum: 0 },
premium_rate: { type: 'number', format: 'decimal', description: '保险费率', minimum: 0, maximum: 1 },
service_area: { type: 'string', description: '服务区域' },
add_time: { type: 'string', format: 'date-time', description: '添加时间' },
on_sale_status: { type: 'boolean', description: '在售状态' },
sort_order: { type: 'integer', description: '排序顺序' },
remarks: { type: 'string', description: '备注' },
status: { type: 'string', enum: ['active', 'inactive'], description: '险种状态' }
}
},
UpdateInsuranceTypeStatusRequest: {
type: 'object',
properties: {
status: { type: 'string', enum: ['active', 'inactive'], description: '险种状态' },
on_sale_status: { type: 'boolean', description: '在售状态' }
}
},
Pagination: {
type: 'object',
properties: {
page: { type: 'integer', description: '当前页码' },
limit: { type: 'integer', description: '每页数量' },
total: { type: 'integer', description: '总记录数' }
}
},
Error: {
type: 'object',
properties: {
@@ -293,6 +371,7 @@ const swaggerDefinition = {
tags: [
{ name: '认证', description: '用户认证相关接口' },
{ name: '用户管理', description: '用户管理相关接口' },
{ name: '险种管理', description: '保险险种管理相关接口' },
{ name: '保险申请', description: '保险申请管理相关接口' },
{ name: '保单管理', description: '保单管理相关接口' },
{ name: '理赔管理', description: '理赔管理相关接口' },

View File

@@ -5,7 +5,15 @@ const responseFormat = require('../utils/response');
// 获取保险类型列表
const getInsuranceTypes = async (req, res) => {
try {
const { page = 1, pageSize = 10, name, status } = req.query;
const {
page = 1,
pageSize = 10,
name,
status,
applicable_livestock,
service_area,
on_sale_status
} = req.query;
const offset = (page - 1) * pageSize;
const whereClause = {};
@@ -15,12 +23,21 @@ const getInsuranceTypes = async (req, res) => {
if (status) {
whereClause.status = status;
}
if (applicable_livestock) {
whereClause.applicable_livestock = { [Op.like]: `%${applicable_livestock}%` };
}
if (service_area) {
whereClause.service_area = { [Op.like]: `%${service_area}%` };
}
if (on_sale_status !== undefined && on_sale_status !== '') {
whereClause.on_sale_status = on_sale_status === 'true';
}
const { count, rows } = await InsuranceType.findAndCountAll({
where: whereClause,
limit: parseInt(pageSize),
offset: offset,
order: [['created_at', 'DESC']]
order: [['add_time', 'DESC'], ['created_at', 'DESC']]
});
res.json(responseFormat.pagination(rows, {
@@ -57,9 +74,17 @@ const createInsuranceType = async (req, res) => {
const {
name,
description,
applicable_livestock,
insurance_term,
policy_form,
coverage_amount_min,
coverage_amount_max,
premium_rate,
service_area,
add_time,
on_sale_status = true,
sort_order = 0,
remarks,
status = 'active'
} = req.body;
@@ -72,9 +97,17 @@ const createInsuranceType = async (req, res) => {
const insuranceType = await InsuranceType.create({
name,
description,
applicable_livestock,
insurance_term,
policy_form,
coverage_amount_min,
coverage_amount_max,
premium_rate,
service_area,
add_time: add_time || new Date(),
on_sale_status,
sort_order,
remarks,
status,
created_by: req.user?.id
});
@@ -97,9 +130,17 @@ const updateInsuranceType = async (req, res) => {
const {
name,
description,
applicable_livestock,
insurance_term,
policy_form,
coverage_amount_min,
coverage_amount_max,
premium_rate,
service_area,
add_time,
on_sale_status,
sort_order,
remarks,
status
} = req.body;
@@ -123,10 +164,18 @@ const updateInsuranceType = async (req, res) => {
await insuranceType.update({
name: name || insuranceType.name,
description: description || insuranceType.description,
coverage_amount_min: coverage_amount_min || insuranceType.coverage_amount_min,
coverage_amount_max: coverage_amount_max || insuranceType.coverage_amount_max,
premium_rate: premium_rate || insuranceType.premium_rate,
description: description !== undefined ? description : insuranceType.description,
applicable_livestock: applicable_livestock !== undefined ? applicable_livestock : insuranceType.applicable_livestock,
insurance_term: insurance_term !== undefined ? insurance_term : insuranceType.insurance_term,
policy_form: policy_form !== undefined ? policy_form : insuranceType.policy_form,
coverage_amount_min: coverage_amount_min !== undefined ? coverage_amount_min : insuranceType.coverage_amount_min,
coverage_amount_max: coverage_amount_max !== undefined ? coverage_amount_max : insuranceType.coverage_amount_max,
premium_rate: premium_rate !== undefined ? premium_rate : insuranceType.premium_rate,
service_area: service_area !== undefined ? service_area : insuranceType.service_area,
add_time: add_time !== undefined ? add_time : insuranceType.add_time,
on_sale_status: on_sale_status !== undefined ? on_sale_status : insuranceType.on_sale_status,
sort_order: sort_order !== undefined ? sort_order : insuranceType.sort_order,
remarks: remarks !== undefined ? remarks : insuranceType.remarks,
status: status || insuranceType.status,
updated_by: req.user?.id
});
@@ -152,16 +201,22 @@ const deleteInsuranceType = async (req, res) => {
return res.status(404).json(responseFormat.error('险种不存在'));
}
// 检查是否有相关的保险申请或保单
// const hasApplications = await insuranceType.countInsuranceApplications();
// if (hasApplications > 0) {
// return res.status(400).json(responseFormat.error('该险种下存在保险申请,无法删除'));
// }
// 检查是否有相关的保险申请
const hasApplications = await insuranceType.countApplications();
if (hasApplications > 0) {
return res.status(400).json(responseFormat.error('该险种下存在保险申请,无法删除', 400));
}
await insuranceType.destroy();
res.json(responseFormat.success(null, '删除险种成功'));
} catch (error) {
console.error('删除险种错误:', error);
// 处理外键约束错误
if (error.name === 'SequelizeForeignKeyConstraintError') {
return res.status(400).json(responseFormat.error('该险种下存在相关数据,无法删除', 400));
}
res.status(500).json(responseFormat.error('删除险种失败'));
}
};
@@ -170,14 +225,18 @@ const deleteInsuranceType = async (req, res) => {
const updateInsuranceTypeStatus = async (req, res) => {
try {
const { id } = req.params;
const { status } = req.body;
const { status, on_sale_status } = req.body;
const insuranceType = await InsuranceType.findByPk(id);
if (!insuranceType) {
return res.status(404).json(responseFormat.error('险种不存在'));
}
await insuranceType.update({ status, updated_by: req.user?.id });
const updateData = { updated_by: req.user?.id };
if (status !== undefined) updateData.status = status;
if (on_sale_status !== undefined) updateData.on_sale_status = on_sale_status;
await insuranceType.update(updateData);
res.json(responseFormat.success(insuranceType, '更新险种状态成功'));
} catch (error) {
console.error('更新险种状态错误:', error);

View File

@@ -8,10 +8,35 @@ const { Op } = require('sequelize');
// 获取生资理赔列表
const getLivestockClaims = async (req, res) => {
try {
console.log('🚀 [后端] 开始处理理赔列表查询请求');
console.log('📥 [后端] 接收到的查询参数:', {
接收时间: new Date().toLocaleString(),
完整URL: req.originalUrl,
查询字符串: req.url,
原始查询参数: JSON.stringify(req.query, null, 2),
查询参数类型: typeof req.query,
查询参数键: Object.keys(req.query),
请求方法: req.method,
请求路径: req.path,
用户信息: req.user ? { id: req.user.id, username: req.user.username } : '未登录'
});
console.log('🔍 [详细调试] 请求信息:');
console.log('req.url:', req.url);
console.log('req.originalUrl:', req.originalUrl);
console.log('req.baseUrl:', req.baseUrl);
console.log('req.path:', req.path);
console.log('查询字符串:', req.url.split('?')[1] || '无');
console.log('原始查询参数:', req.query);
console.log('查询参数类型:', typeof req.query);
console.log('查询参数键:', Object.keys(req.query));
console.log('查询参数JSON:', JSON.stringify(req.query));
const {
claim_no,
policy_no,
farmer_name,
reporter_name,
contact_phone,
claim_status,
claim_type,
start_date,
@@ -20,21 +45,49 @@ const getLivestockClaims = async (req, res) => {
limit = 10
} = req.query;
console.log('🔍 [后端] 解析后的查询参数:', {
理赔单号: claim_no,
保单号: policy_no,
报案人: reporter_name,
联系电话: contact_phone,
理赔状态: claim_status,
理赔类型: claim_type,
开始日期: start_date,
结束日期: end_date,
页码: page,
每页条数: limit
});
const whereClause = {};
// 理赔编号筛选
// 理赔编号筛选 - 精确匹配
if (claim_no) {
whereClause.claim_no = { [Op.like]: `%${claim_no}%` };
whereClause.claim_no = claim_no;
console.log('🔍 [后端] 添加理赔编号筛选条件(精确匹配):', whereClause.claim_no);
}
// 理赔状态筛选
if (claim_status) {
whereClause.claim_status = claim_status;
console.log('🔍 [后端] 添加理赔状态筛选条件:', whereClause.claim_status);
}
// 理赔类型筛选
if (claim_type) {
whereClause.claim_type = claim_type;
console.log('🔍 [后端] 添加理赔类型筛选条件:', whereClause.claim_type);
}
// 报案人筛选
if (reporter_name) {
whereClause.reporter_name = { [Op.like]: `%${reporter_name}%` };
console.log('🔍 [后端] 添加报案人筛选条件:', whereClause.reporter_name);
}
// 联系电话筛选
if (contact_phone) {
whereClause.contact_phone = { [Op.like]: `%${contact_phone}%` };
console.log('🔍 [后端] 添加联系电话筛选条件:', whereClause.contact_phone);
}
// 日期范围筛选
@@ -42,17 +95,30 @@ const getLivestockClaims = async (req, res) => {
whereClause.incident_date = {
[Op.between]: [new Date(start_date), new Date(end_date)]
};
console.log('🔍 [后端] 添加日期范围筛选条件:', whereClause.incident_date);
}
const offset = (page - 1) * limit;
const { count, rows } = await LivestockClaim.findAndCountAll({
console.log('📊 [后端] 构建的查询条件:', {
构建时间: new Date().toLocaleString(),
WHERE条件: JSON.stringify(whereClause, null, 2),
分页信息: {
页码: page,
每页条数: limit,
偏移量: offset
}
});
console.log('🗄️ [后端] 开始执行数据库查询...');
const queryConfig = {
where: whereClause,
include: [
{
model: LivestockPolicy,
as: 'policy',
attributes: ['id', 'policy_no', 'farmer_name', 'farmer_phone', 'livestock_count'],
attributes: ['id', 'policy_no', 'policyholder_name', 'policyholder_phone', 'livestock_count'],
where: policy_no ? { policy_no: { [Op.like]: `%${policy_no}%` } } : {},
required: !!policy_no,
include: [
@@ -77,23 +143,66 @@ const getLivestockClaims = async (req, res) => {
order: [['created_at', 'DESC']],
offset,
limit: parseInt(limit)
};
console.log('🗄️ [后端] 数据库查询配置:', {
查询时间: new Date().toLocaleString(),
查询配置: JSON.stringify(queryConfig, null, 2)
});
// 如果有农户姓名筛选,需要在关联查询后再过滤
let filteredRows = rows;
if (farmer_name) {
filteredRows = rows.filter(claim =>
claim.policy && claim.policy.farmer_name.includes(farmer_name)
);
}
console.log('🚀 [后端] 即将执行查询,最终配置:', JSON.stringify(queryConfig, null, 2));
res.json(responseFormat.pagination(filteredRows, {
const { count, rows } = await LivestockClaim.findAndCountAll(queryConfig);
console.log('✅ [后端] 数据库查询完成:', {
查询时间: new Date().toLocaleString(),
返回总数: count,
返回记录数: rows.length,
记录ID列表: rows.map(r => ({ id: r.id, claim_no: r.claim_no }))
});
console.log('📋 [后端] 详细查询结果:', {
查询完成时间: new Date().toLocaleString(),
查询结果统计: {
总记录数: count,
当前页记录数: rows.length,
查询耗时: '已完成'
},
数据样例: rows.length > 0 ? {
第一条记录ID: rows[0].id,
第一条记录理赔单号: rows[0].claim_no,
第一条记录状态: rows[0].claim_status
} : '无数据'
});
const responseData = responseFormat.pagination(rows, {
page: parseInt(page),
limit: parseInt(limit),
total: count
}, '获取生资理赔列表成功'));
}, '获取生资理赔列表成功');
console.log('📤 [后端->前端] 准备发送响应:', {
响应时间: new Date().toLocaleString(),
响应状态: 'success',
响应数据结构: {
status: responseData.status,
message: responseData.message,
data类型: Array.isArray(responseData.data) ? 'Array' : typeof responseData.data,
data长度: responseData.data?.length,
pagination: responseData.pagination
},
完整响应: JSON.stringify(responseData, null, 2)
});
res.json(responseData);
} catch (error) {
console.error('获取生资理赔列表错误:', error);
console.error('💥 [后端] 获取生资理赔列表错误:', {
错误时间: new Date().toLocaleString(),
错误类型: error.name,
错误信息: error.message,
错误堆栈: error.stack,
SQL错误: error.sql || '无SQL信息'
});
res.status(500).json(responseFormat.error('获取生资理赔列表失败'));
}
};
@@ -355,10 +464,88 @@ const getLivestockClaimStats = async (req, res) => {
}
};
// 更新生资理赔
const updateLivestockClaim = async (req, res) => {
try {
const { id } = req.params;
const updateData = req.body;
const claim = await LivestockClaim.findByPk(id);
if (!claim) {
return res.status(404).json(responseFormat.error('生资理赔不存在'));
}
// 更新理赔信息
await claim.update({
...updateData,
updated_by: req.user?.id
});
// 获取更新后的完整信息
const updatedClaim = await LivestockClaim.findByPk(id, {
include: [
{
model: LivestockPolicy,
as: 'policy',
attributes: ['id', 'policy_no', 'policyholder_name', 'policyholder_phone'],
include: [
{
model: LivestockType,
as: 'livestock_type',
attributes: ['id', 'name']
}
]
},
{
model: User,
as: 'creator',
attributes: ['id', 'real_name', 'username']
},
{
model: User,
as: 'reviewer',
attributes: ['id', 'real_name', 'username']
}
]
});
res.json(responseFormat.success(updatedClaim, '生资理赔更新成功'));
} catch (error) {
console.error('更新生资理赔错误:', error);
res.status(500).json(responseFormat.error('更新生资理赔失败'));
}
};
// 删除生资理赔
const deleteLivestockClaim = async (req, res) => {
try {
const { id } = req.params;
const claim = await LivestockClaim.findByPk(id);
if (!claim) {
return res.status(404).json(responseFormat.error('生资理赔不存在'));
}
// 检查是否可以删除(只有待处理状态的理赔可以删除)
if (claim.claim_status !== 'pending') {
return res.status(400).json(responseFormat.error('只有待处理状态的理赔可以删除'));
}
await claim.destroy();
res.json(responseFormat.success(null, '生资理赔删除成功'));
} catch (error) {
console.error('删除生资理赔错误:', error);
res.status(500).json(responseFormat.error('删除生资理赔失败'));
}
};
module.exports = {
getLivestockClaims,
createLivestockClaim,
getLivestockClaimById,
updateLivestockClaim,
deleteLivestockClaim,
reviewLivestockClaim,
updateLivestockClaimPayment,
getLivestockClaimStats

View File

@@ -0,0 +1,308 @@
# 险种管理API使用示例
## 概述
本文档提供了险种管理API的详细使用示例包括请求格式、响应格式和错误处理。
## 基础信息
- **基础URL**: `http://localhost:3000/api`
- **认证方式**: Bearer Token (JWT)
- **内容类型**: `application/json`
## 认证
所有API请求都需要在请求头中包含有效的JWT令牌
```http
Authorization: Bearer <your-jwt-token>
```
## API端点
### 1. 获取险种列表
**请求**
```http
GET /api/insurance-types?page=1&pageSize=10&name=牛&status=active
Authorization: Bearer <your-jwt-token>
```
**响应示例**
```json
{
"success": true,
"message": "获取险种列表成功",
"data": [
{
"id": 1,
"name": "牛只意外伤害保险",
"description": "为牛只提供意外伤害保障",
"applicable_livestock": "牛",
"insurance_term": "1年",
"policy_form": "团体保险",
"on_sale_status": true,
"coverage_amount_min": 1000.00,
"coverage_amount_max": 50000.00,
"premium_rate": 0.05,
"status": "active",
"add_time": "2024-01-15T08:30:00.000Z",
"created_at": "2024-01-15T08:30:00.000Z",
"updated_at": "2024-01-15T08:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
}
}
```
### 2. 获取单个险种详情
**请求**
```http
GET /api/insurance-types/1
Authorization: Bearer <your-jwt-token>
```
**响应示例**
```json
{
"success": true,
"message": "获取险种详情成功",
"data": {
"id": 1,
"name": "牛只意外伤害保险",
"description": "为牛只提供意外伤害保障",
"applicable_livestock": "牛",
"insurance_term": "1年",
"policy_form": "团体保险",
"on_sale_status": true,
"coverage_amount_min": 1000.00,
"coverage_amount_max": 50000.00,
"premium_rate": 0.05,
"status": "active",
"add_time": "2024-01-15T08:30:00.000Z",
"created_at": "2024-01-15T08:30:00.000Z",
"updated_at": "2024-01-15T08:30:00.000Z"
}
}
```
### 3. 创建险种
**请求**
```http
POST /api/insurance-types
Authorization: Bearer <your-jwt-token>
Content-Type: application/json
{
"name": "羊只疾病保险",
"description": "为羊只提供疾病保障",
"applicable_livestock": "羊",
"insurance_term": "1年",
"policy_form": "个体保险",
"coverage_amount_min": 500.00,
"coverage_amount_max": 20000.00,
"premium_rate": 0.08
}
```
**响应示例**
```json
{
"success": true,
"message": "创建险种成功",
"data": {
"id": 2,
"name": "羊只疾病保险",
"description": "为羊只提供疾病保障",
"applicable_livestock": "羊",
"insurance_term": "1年",
"policy_form": "个体保险",
"on_sale_status": false,
"coverage_amount_min": 500.00,
"coverage_amount_max": 20000.00,
"premium_rate": 0.08,
"status": "active",
"add_time": "2024-01-15T09:00:00.000Z",
"created_at": "2024-01-15T09:00:00.000Z",
"updated_at": "2024-01-15T09:00:00.000Z"
}
}
```
### 4. 更新险种
**请求**
```http
PUT /api/insurance-types/2
Authorization: Bearer <your-jwt-token>
Content-Type: application/json
{
"name": "羊只综合保险",
"description": "为羊只提供疾病和意外伤害综合保障",
"premium_rate": 0.10
}
```
**响应示例**
```json
{
"success": true,
"message": "更新险种成功",
"data": {
"id": 2,
"name": "羊只综合保险",
"description": "为羊只提供疾病和意外伤害综合保障",
"applicable_livestock": "羊",
"insurance_term": "1年",
"policy_form": "个体保险",
"on_sale_status": false,
"coverage_amount_min": 500.00,
"coverage_amount_max": 20000.00,
"premium_rate": 0.10,
"status": "active",
"add_time": "2024-01-15T09:00:00.000Z",
"created_at": "2024-01-15T09:00:00.000Z",
"updated_at": "2024-01-15T09:15:00.000Z"
}
}
```
### 5. 更新险种状态
**请求**
```http
PATCH /api/insurance-types/2/status
Authorization: Bearer <your-jwt-token>
Content-Type: application/json
{
"status": "active",
"on_sale_status": true
}
```
**响应示例**
```json
{
"success": true,
"message": "更新险种状态成功",
"data": {
"id": 2,
"name": "羊只综合保险",
"description": "为羊只提供疾病和意外伤害综合保障",
"applicable_livestock": "羊",
"insurance_term": "1年",
"policy_form": "个体保险",
"on_sale_status": true,
"coverage_amount_min": 500.00,
"coverage_amount_max": 20000.00,
"premium_rate": 0.10,
"status": "active",
"add_time": "2024-01-15T09:00:00.000Z",
"created_at": "2024-01-15T09:00:00.000Z",
"updated_at": "2024-01-15T09:20:00.000Z"
}
}
```
### 6. 删除险种
**请求**
```http
DELETE /api/insurance-types/2
Authorization: Bearer <your-jwt-token>
```
**响应示例**
```json
{
"success": true,
"message": "删除险种成功"
}
```
## 错误处理
### 常见错误响应
#### 401 未授权
```json
{
"success": false,
"message": "未授权访问",
"error": "Unauthorized"
}
```
#### 403 权限不足
```json
{
"success": false,
"message": "权限不足",
"error": "Forbidden"
}
```
#### 404 资源不存在
```json
{
"success": false,
"message": "险种不存在",
"error": "Not Found"
}
```
#### 400 请求参数错误
```json
{
"success": false,
"message": "险种名称已存在",
"error": "Bad Request"
}
```
#### 500 服务器内部错误
```json
{
"success": false,
"message": "服务器内部错误",
"error": "Internal Server Error"
}
```
## 查询参数说明
### 获取险种列表支持的查询参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| page | integer | 否 | 1 | 页码最小值为1 |
| pageSize | integer | 否 | 10 | 每页数量范围1-100 |
| name | string | 否 | - | 险种名称,支持模糊搜索 |
| status | string | 否 | - | 险种状态可选值active, inactive |
| applicable_livestock | string | 否 | - | 适用牲畜类型,支持模糊搜索 |
| service_area | string | 否 | - | 服务区域,支持模糊搜索 |
| on_sale_status | boolean | 否 | - | 在售状态true或false |
## 使用注意事项
1. **认证令牌**: 所有请求都需要有效的JWT令牌
2. **权限检查**: 用户需要具有相应的险种管理权限
3. **数据验证**: 创建和更新时会进行数据格式验证
4. **唯一性检查**: 险种名称必须唯一
5. **分页限制**: 每页最多返回100条记录
6. **状态管理**: 险种状态和在售状态可以独立管理
## 测试工具推荐
- **Postman**: 用于API测试和调试
- **curl**: 命令行工具,适合脚本化测试
- **Swagger UI**: 在线API文档和测试界面 (http://localhost:3000/api-docs)

View File

@@ -0,0 +1,690 @@
openapi: 3.0.0
info:
title: 险种管理API
description: 保险系统险种管理功能相关API接口文档
version: 1.0.0
contact:
name: 开发团队
email: dev@example.com
servers:
- url: http://localhost:3000/api
description: 开发环境
paths:
/insurance-types:
get:
summary: 获取险种列表
description: 分页获取险种列表,支持多种筛选条件
tags:
- 险种管理
security:
- bearerAuth: []
parameters:
- name: page
in: query
description: 页码
required: false
schema:
type: integer
default: 1
minimum: 1
- name: pageSize
in: query
description: 每页数量
required: false
schema:
type: integer
default: 10
minimum: 1
maximum: 100
- name: name
in: query
description: 险种名称(模糊搜索)
required: false
schema:
type: string
- name: status
in: query
description: 险种状态
required: false
schema:
type: string
enum: [active, inactive]
- name: applicable_livestock
in: query
description: 适用牲畜类型(模糊搜索)
required: false
schema:
type: string
- name: service_area
in: query
description: 服务区域(模糊搜索)
required: false
schema:
type: string
- name: on_sale_status
in: query
description: 在售状态
required: false
schema:
type: boolean
responses:
'200':
description: 获取成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
example: "获取险种列表成功"
data:
type: array
items:
$ref: '#/components/schemas/InsuranceType'
pagination:
$ref: '#/components/schemas/Pagination'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: 创建险种
description: 创建新的保险险种
tags:
- 险种管理
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateInsuranceTypeRequest'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
example: "创建险种成功"
data:
$ref: '#/components/schemas/InsuranceType'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/insurance-types/{id}:
get:
summary: 获取险种详情
description: 根据ID获取单个险种的详细信息
tags:
- 险种管理
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
description: 险种ID
schema:
type: integer
responses:
'200':
description: 获取成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
example: "获取保险类型详情成功"
data:
$ref: '#/components/schemas/InsuranceType'
'404':
$ref: '#/components/responses/NotFound'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
put:
summary: 更新险种
description: 更新指定ID的险种信息
tags:
- 险种管理
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
description: 险种ID
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateInsuranceTypeRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
example: "更新险种成功"
data:
$ref: '#/components/schemas/InsuranceType'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
summary: 删除险种
description: 删除指定ID的险种
tags:
- 险种管理
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
description: 险种ID
schema:
type: integer
responses:
'200':
description: 删除成功
content:
application/json:
schema:
type: object
properties:
code:
type: integer
example: 200
status:
type: string
example: "success"
data:
type: null
example: null
message:
type: string
example: "删除险种成功"
timestamp:
type: string
format: date-time
example: "2025-09-28T06:28:03.150Z"
'400':
description: 删除失败 - 外键约束错误
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: 400
status: error
data: null
message: "该险种下存在保险申请,无法删除"
timestamp: "2025-09-28T06:28:02.881Z"
'404':
description: 险种不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: 404
status: error
data: null
message: "险种不存在"
timestamp: "2025-09-28T06:28:02.881Z"
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/insurance-types/{id}/status:
patch:
summary: 更新险种状态
description: 更新指定ID险种的状态或在售状态
tags:
- 险种管理
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
description: 险种ID
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateInsuranceTypeStatusRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
example: "更新险种状态成功"
data:
$ref: '#/components/schemas/InsuranceType'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
InsuranceType:
type: object
properties:
id:
type: integer
description: 险种ID
example: 1
name:
type: string
description: 险种名称
example: "牛羊保险"
description:
type: string
description: 险种描述
example: "针对牛羊等大型牲畜的综合保险产品"
applicable_livestock:
type: string
description: 适用牲畜类型
example: "牛、羊"
insurance_term:
type: integer
description: 保险期限(月)
example: 12
policy_form:
type: string
description: 保单形式
example: "电子保单"
coverage_amount_min:
type: number
format: decimal
description: 最低保额
example: 1000.00
coverage_amount_max:
type: number
format: decimal
description: 最高保额
example: 50000.00
premium_rate:
type: number
format: decimal
description: 保险费率
example: 0.0350
service_area:
type: string
description: 服务区域
example: "宁夏回族自治区"
add_time:
type: string
format: date-time
description: 添加时间
example: "2024-01-15T10:30:00.000Z"
on_sale_status:
type: boolean
description: 在售状态
example: true
sort_order:
type: integer
description: 排序顺序
example: 0
remarks:
type: string
description: 备注
example: "特殊说明信息"
status:
type: string
enum: [active, inactive]
description: 险种状态
example: "active"
created_by:
type: integer
description: 创建人ID
example: 1
updated_by:
type: integer
description: 更新人ID
example: 1
created_at:
type: string
format: date-time
description: 创建时间
example: "2024-01-15T10:30:00.000Z"
updated_at:
type: string
format: date-time
description: 更新时间
example: "2024-01-15T10:30:00.000Z"
CreateInsuranceTypeRequest:
type: object
required:
- name
- coverage_amount_min
- coverage_amount_max
- premium_rate
properties:
name:
type: string
description: 险种名称
example: "牛羊保险"
minLength: 1
maxLength: 100
description:
type: string
description: 险种描述
example: "针对牛羊等大型牲畜的综合保险产品"
applicable_livestock:
type: string
description: 适用牲畜类型
example: "牛、羊"
maxLength: 100
insurance_term:
type: integer
description: 保险期限(月)
example: 12
minimum: 1
policy_form:
type: string
description: 保单形式
example: "电子保单"
maxLength: 50
coverage_amount_min:
type: number
format: decimal
description: 最低保额
example: 1000.00
minimum: 0
coverage_amount_max:
type: number
format: decimal
description: 最高保额
example: 50000.00
minimum: 0
premium_rate:
type: number
format: decimal
description: 保险费率
example: 0.0350
minimum: 0
maximum: 1
service_area:
type: string
description: 服务区域
example: "宁夏回族自治区"
add_time:
type: string
format: date-time
description: 添加时间
example: "2024-01-15T10:30:00.000Z"
on_sale_status:
type: boolean
description: 在售状态
example: true
default: true
sort_order:
type: integer
description: 排序顺序
example: 0
default: 0
remarks:
type: string
description: 备注
example: "特殊说明信息"
status:
type: string
enum: [active, inactive]
description: 险种状态
example: "active"
default: "active"
UpdateInsuranceTypeRequest:
type: object
properties:
name:
type: string
description: 险种名称
example: "牛羊保险"
minLength: 1
maxLength: 100
description:
type: string
description: 险种描述
example: "针对牛羊等大型牲畜的综合保险产品"
applicable_livestock:
type: string
description: 适用牲畜类型
example: "牛、羊"
maxLength: 100
insurance_term:
type: integer
description: 保险期限(月)
example: 12
minimum: 1
policy_form:
type: string
description: 保单形式
example: "电子保单"
maxLength: 50
coverage_amount_min:
type: number
format: decimal
description: 最低保额
example: 1000.00
minimum: 0
coverage_amount_max:
type: number
format: decimal
description: 最高保额
example: 50000.00
minimum: 0
premium_rate:
type: number
format: decimal
description: 保险费率
example: 0.0350
minimum: 0
maximum: 1
service_area:
type: string
description: 服务区域
example: "宁夏回族自治区"
add_time:
type: string
format: date-time
description: 添加时间
example: "2024-01-15T10:30:00.000Z"
on_sale_status:
type: boolean
description: 在售状态
example: true
sort_order:
type: integer
description: 排序顺序
example: 0
remarks:
type: string
description: 备注
example: "特殊说明信息"
status:
type: string
enum: [active, inactive]
description: 险种状态
example: "active"
UpdateInsuranceTypeStatusRequest:
type: object
properties:
status:
type: string
enum: [active, inactive]
description: 险种状态
example: "active"
on_sale_status:
type: boolean
description: 在售状态
example: true
Pagination:
type: object
properties:
page:
type: integer
description: 当前页码
example: 1
limit:
type: integer
description: 每页数量
example: 10
total:
type: integer
description: 总记录数
example: 100
responses:
BadRequest:
description: 请求参数错误
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
example: "请求参数错误"
Unauthorized:
description: 未授权
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
example: "未授权访问"
Forbidden:
description: 权限不足
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
example: "权限不足"
NotFound:
description: 资源不存在
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
example: "险种不存在"
InternalServerError:
description: 服务器内部错误
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: false
message:
type: string
example: "服务器内部错误"

View File

@@ -29,6 +29,38 @@ const InsuranceType = sequelize.define('InsuranceType', {
allowNull: true,
comment: '保险类型描述'
},
applicable_livestock: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '适用生资(如:牛、羊、猪等)'
},
insurance_term: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '保险期限(月)',
validate: {
min: {
args: [1],
msg: '保险期限不能小于1个月'
}
}
},
policy_form: {
type: DataTypes.STRING(50),
allowNull: true,
comment: '保单形式(电子保单、纸质保单等)'
},
on_sale_status: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
comment: '在售状态true-在售false-停售)'
},
add_time: {
type: DataTypes.DATE,
allowNull: true,
comment: '添加时间'
},
coverage_amount_min: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,

View File

@@ -19,6 +19,21 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
}
}
},
reporter_name: {
type: DataTypes.STRING(100),
allowNull: false,
comment: '报案人姓名'
},
contact_phone: {
type: DataTypes.STRING(20),
allowNull: false,
comment: '联系电话'
},
policy_no: {
type: DataTypes.STRING(50),
allowNull: false,
comment: '保单号'
},
policy_id: {
type: DataTypes.INTEGER,
allowNull: false,
@@ -29,9 +44,32 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
}
},
claim_type: {
type: DataTypes.ENUM('disease', 'natural_disaster', 'accident', 'theft', 'other'),
type: DataTypes.ENUM('death', 'disease', 'accident', 'natural_disaster'),
allowNull: false,
comment: '理赔类型disease-疾病natural_disaster-自然灾害accident-意外事故theft-盗窃other-其他'
comment: '理赔类型:death-死亡,disease-疾病,accident-意外事故,natural_disaster-自然灾害'
},
affected_count: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
comment: '受影响牲畜数量',
validate: {
min: {
args: [1],
msg: '受影响牲畜数量不能小于1'
}
}
},
claim_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,
comment: '理赔金额',
validate: {
min: {
args: [0],
msg: '理赔金额不能小于0'
}
}
},
incident_date: {
type: DataTypes.DATE,
@@ -63,28 +101,6 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
}
}
},
affected_count: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '受影响牲畜数量',
validate: {
min: {
args: [1],
msg: '受影响牲畜数量不能小于1'
}
}
},
claim_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: false,
comment: '理赔金额',
validate: {
min: {
args: [0],
msg: '理赔金额不能小于0'
}
}
},
claim_status: {
type: DataTypes.ENUM('pending', 'investigating', 'approved', 'rejected', 'paid'),
allowNull: false,
@@ -100,15 +116,10 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
key: 'id'
}
},
investigation_notes: {
investigation_report: {
type: DataTypes.TEXT,
allowNull: true,
comment: '调查备注'
},
investigation_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '调查日期'
comment: '调查报告'
},
reviewer_id: {
type: DataTypes.INTEGER,
@@ -129,7 +140,12 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
allowNull: true,
comment: '审核日期'
},
settlement_amount: {
payment_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '赔付日期'
},
payment_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: '实际赔付金额',
@@ -140,11 +156,6 @@ const LivestockClaim = sequelize.define('LivestockClaim', {
}
}
},
settlement_date: {
type: DataTypes.DATE,
allowNull: true,
comment: '赔付日期'
},
supporting_documents: {
type: DataTypes.JSON,
allowNull: true,

View File

@@ -212,7 +212,7 @@ LivestockClaim.belongsTo(User, {
as: 'creator'
});
LivestockClaim.belongsTo(User, {
foreignKey: 'reviewed_by',
foreignKey: 'reviewer_id',
as: 'reviewer'
});

View File

@@ -3,34 +3,328 @@ const router = express.Router();
const insuranceTypeController = require('../controllers/insuranceTypeController');
const { jwtAuth, checkPermission } = require('../middleware/auth');
/**
* @swagger
* /api/insurance-types:
* get:
* summary: 获取险种列表
* description: 分页获取险种列表,支持多种筛选条件
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* parameters:
* - name: page
* in: query
* description: 页码
* required: false
* schema:
* type: integer
* default: 1
* minimum: 1
* - name: pageSize
* in: query
* description: 每页数量
* required: false
* schema:
* type: integer
* default: 10
* minimum: 1
* maximum: 100
* - name: name
* in: query
* description: 险种名称(模糊搜索)
* required: false
* schema:
* type: string
* - name: status
* in: query
* description: 险种状态
* required: false
* schema:
* type: string
* enum: [active, inactive]
* - name: applicable_livestock
* in: query
* description: 适用牲畜类型(模糊搜索)
* required: false
* schema:
* type: string
* - name: service_area
* in: query
* description: 服务区域(模糊搜索)
* required: false
* schema:
* type: string
* - name: on_sale_status
* in: query
* description: 在售状态
* required: false
* schema:
* type: boolean
* responses:
* '200':
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "获取险种列表成功"
* data:
* type: array
* items:
* $ref: '#/components/schemas/InsuranceType'
* pagination:
* $ref: '#/components/schemas/Pagination'
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '500':
* description: 服务器内部错误
* post:
* summary: 创建险种
* description: 创建新的保险险种
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CreateInsuranceTypeRequest'
* responses:
* '201':
* description: 创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "创建险种成功"
* data:
* $ref: '#/components/schemas/InsuranceType'
* '400':
* description: 请求参数错误
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '500':
* description: 服务器内部错误
*/
// 获取险种列表
router.get('/', jwtAuth, checkPermission('insurance_type', 'read'),
insuranceTypeController.getInsuranceTypes
);
/**
* @swagger
* /api/insurance-types/{id}:
* get:
* summary: 获取单个险种
* description: 根据ID获取险种详细信息
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* parameters:
* - name: id
* in: path
* description: 险种ID
* required: true
* schema:
* type: integer
* responses:
* '200':
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "获取险种详情成功"
* data:
* $ref: '#/components/schemas/InsuranceType'
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '404':
* description: 险种不存在
* '500':
* description: 服务器内部错误
*/
// 获取单个险种详情
router.get('/:id', jwtAuth, checkPermission('insurance_type', 'read'),
insuranceTypeController.getInsuranceTypeById
);
// 创建险种
router.post('/', jwtAuth, checkPermission('insurance_type', 'create'),
insuranceTypeController.createInsuranceType
);
router.post('/', jwtAuth, checkPermission('insurance_type', 'create'), insuranceTypeController.createInsuranceType);
/**
* @swagger
* /api/insurance-types/{id}:
* put:
* summary: 更新险种
* description: 根据ID更新险种信息
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* parameters:
* - name: id
* in: path
* description: 险种ID
* required: true
* schema:
* type: integer
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UpdateInsuranceTypeRequest'
* responses:
* '200':
* description: 更新成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "更新险种成功"
* data:
* $ref: '#/components/schemas/InsuranceType'
* '400':
* description: 请求参数错误
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '404':
* description: 险种不存在
* '500':
* description: 服务器内部错误
* delete:
* summary: 删除险种
* description: 根据ID删除险种
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* parameters:
* - name: id
* in: path
* description: 险种ID
* required: true
* schema:
* type: integer
* responses:
* '200':
* description: 删除成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "删除险种成功"
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '404':
* description: 险种不存在
* '500':
* description: 服务器内部错误
*/
// 更新险种
router.put('/:id', jwtAuth, checkPermission('insurance_type', 'update'),
insuranceTypeController.updateInsuranceType
);
router.put('/:id', jwtAuth, checkPermission('insurance_type', 'update'), insuranceTypeController.updateInsuranceType);
// 删除险种
router.delete('/:id', jwtAuth, checkPermission('insurance_type', 'delete'),
insuranceTypeController.deleteInsuranceType
);
router.delete('/:id', jwtAuth, checkPermission('insurance_type', 'delete'), insuranceTypeController.deleteInsuranceType);
/**
* @swagger
* /api/insurance-types/{id}/status:
* patch:
* summary: 更新险种状态
* description: 更新险种的状态和在售状态
* tags:
* - 险种管理
* security:
* - bearerAuth: []
* parameters:
* - name: id
* in: path
* description: 险种ID
* required: true
* schema:
* type: integer
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UpdateInsuranceTypeStatusRequest'
* responses:
* '200':
* description: 更新成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: "更新险种状态成功"
* data:
* $ref: '#/components/schemas/InsuranceType'
* '400':
* description: 请求参数错误
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '403':
* $ref: '#/components/responses/ForbiddenError'
* '404':
* description: 险种不存在
* '500':
* description: 服务器内部错误
*/
// 更新险种状态
router.patch('/:id/status', jwtAuth, checkPermission('insurance_type', 'update'),
insuranceTypeController.updateInsuranceTypeStatus
);
router.patch('/:id/status', jwtAuth, checkPermission('insurance_type', 'update'), insuranceTypeController.updateInsuranceTypeStatus);
module.exports = router;

View File

@@ -6,10 +6,27 @@ const {
getLivestockClaimById,
reviewLivestockClaim,
updateLivestockClaimPayment,
getLivestockClaimStats
getLivestockClaimStats,
updateLivestockClaim,
deleteLivestockClaim
} = require('../controllers/livestockClaimController');
const { authenticateToken, requirePermission } = require('../middleware/auth');
// 测试查询参数端点(无认证)
router.get('/test-params', (req, res) => {
console.log('🧪 [测试端点] 查询参数测试:');
console.log('req.url:', req.url);
console.log('req.originalUrl:', req.originalUrl);
console.log('req.query:', req.query);
console.log('req.params:', req.params);
res.json({
url: req.url,
originalUrl: req.originalUrl,
query: req.query,
params: req.params
});
});
// 获取生资理赔列表
router.get('/', authenticateToken, requirePermission('livestock_claim:read'), getLivestockClaims);
@@ -22,6 +39,12 @@ router.get('/:id', authenticateToken, requirePermission('livestock_claim:read'),
// 创建生资理赔申请
router.post('/', authenticateToken, requirePermission('livestock_claim:create'), createLivestockClaim);
// 更新生资理赔信息
router.put('/:id', authenticateToken, requirePermission('livestock_claim:update'), updateLivestockClaim);
// 删除生资理赔
router.delete('/:id', authenticateToken, requirePermission('livestock_claim:delete'), deleteLivestockClaim);
// 审核生资理赔
router.patch('/:id/review', authenticateToken, requirePermission('livestock_claim:review'), reviewLivestockClaim);

View File

@@ -0,0 +1,23 @@
const axios = require('axios');
async function testParams() {
try {
console.log('🧪 测试查询参数传递...');
const response = await axios.get('http://localhost:3000/api/livestock-claims/test-params', {
params: {
claim_no: 'LC2024001',
page: 1,
pageSize: 10
}
});
console.log('✅ 测试端点响应:');
console.log(JSON.stringify(response.data, null, 2));
} catch (error) {
console.error('❌ 测试失败:', error.response?.data || error.message);
}
}
testParams();

View File

@@ -0,0 +1,282 @@
/**
* 险种管理API测试脚本
* 使用Node.js和axios进行API测试
*/
const axios = require('axios');
// 配置
const BASE_URL = 'http://localhost:3000/api';
const TEST_USER = {
username: 'admin',
password: '123456'
};
let authToken = '';
let testInsuranceTypeId = null;
// 创建axios实例
const api = axios.create({
baseURL: BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
// 请求拦截器 - 添加认证头
api.interceptors.request.use(config => {
if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
}
return config;
});
// 响应拦截器 - 处理错误
api.interceptors.response.use(
response => response,
error => {
console.error('API请求错误:', error.response?.data || error.message);
return Promise.reject(error);
}
);
// 测试函数
async function runTests() {
console.log('🚀 开始险种管理API测试...\n');
try {
// 1. 用户登录
await testLogin();
// 2. 获取险种列表
await testGetInsuranceTypes();
// 3. 创建险种
await testCreateInsuranceType();
// 4. 获取单个险种
await testGetInsuranceTypeById();
// 5. 更新险种
await testUpdateInsuranceType();
// 6. 更新险种状态
await testUpdateInsuranceTypeStatus();
// 7. 删除险种
await testDeleteInsuranceType();
console.log('✅ 所有测试完成!');
} catch (error) {
console.error('❌ 测试失败:', error.message);
process.exit(1);
}
}
// 1. 测试用户登录
async function testLogin() {
console.log('📝 测试用户登录...');
try {
const response = await api.post('/auth/login', TEST_USER);
if (response.data.success && response.data.data.token) {
authToken = response.data.data.token;
console.log('✅ 登录成功');
} else {
throw new Error('登录失败未获取到token');
}
} catch (error) {
throw new Error(`登录失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 2. 测试获取险种列表
async function testGetInsuranceTypes() {
console.log('📋 测试获取险种列表...');
try {
const response = await api.get('/insurance-types', {
params: {
page: 1,
pageSize: 10,
status: 'active'
}
});
if (response.data.success) {
console.log(`✅ 获取险种列表成功,共 ${response.data.pagination.total} 条记录`);
console.log(` 当前页: ${response.data.pagination.page}/${response.data.pagination.totalPages}`);
} else {
throw new Error('获取险种列表失败');
}
} catch (error) {
throw new Error(`获取险种列表失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 3. 测试创建险种
async function testCreateInsuranceType() {
console.log(' 测试创建险种...');
const testData = {
name: `测试险种_${Date.now()}`,
description: '这是一个测试用的险种',
applicable_livestock: '牛',
insurance_term: '1年',
policy_form: '团体保险',
coverage_amount_min: 1000.00,
coverage_amount_max: 50000.00,
premium_rate: 0.05
};
try {
const response = await api.post('/insurance-types', testData);
if (response.data.success && response.data.data.id) {
testInsuranceTypeId = response.data.data.id;
console.log(`✅ 创建险种成功ID: ${testInsuranceTypeId}`);
console.log(` 险种名称: ${response.data.data.name}`);
} else {
throw new Error('创建险种失败');
}
} catch (error) {
throw new Error(`创建险种失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 4. 测试获取单个险种
async function testGetInsuranceTypeById() {
console.log('🔍 测试获取单个险种...');
if (!testInsuranceTypeId) {
throw new Error('没有可用的测试险种ID');
}
try {
const response = await api.get(`/insurance-types/${testInsuranceTypeId}`);
if (response.data.success && response.data.data) {
console.log(`✅ 获取险种详情成功`);
console.log(` 险种名称: ${response.data.data.name}`);
console.log(` 适用牲畜: ${response.data.data.applicable_livestock}`);
console.log(` 保险期限: ${response.data.data.insurance_term}`);
} else {
throw new Error('获取险种详情失败');
}
} catch (error) {
throw new Error(`获取险种详情失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 5. 测试更新险种
async function testUpdateInsuranceType() {
console.log('✏️ 测试更新险种...');
if (!testInsuranceTypeId) {
throw new Error('没有可用的测试险种ID');
}
const updateData = {
description: '这是一个更新后的测试险种描述',
premium_rate: 0.08
};
try {
const response = await api.put(`/insurance-types/${testInsuranceTypeId}`, updateData);
if (response.data.success && response.data.data) {
console.log(`✅ 更新险种成功`);
console.log(` 新描述: ${response.data.data.description}`);
console.log(` 新费率: ${response.data.data.premium_rate}`);
} else {
throw new Error('更新险种失败');
}
} catch (error) {
throw new Error(`更新险种失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 6. 测试更新险种状态
async function testUpdateInsuranceTypeStatus() {
console.log('🔄 测试更新险种状态...');
if (!testInsuranceTypeId) {
throw new Error('没有可用的测试险种ID');
}
const statusData = {
status: 'active',
on_sale_status: true
};
try {
const response = await api.patch(`/insurance-types/${testInsuranceTypeId}/status`, statusData);
if (response.data.success && response.data.data) {
console.log(`✅ 更新险种状态成功`);
console.log(` 状态: ${response.data.data.status}`);
console.log(` 在售状态: ${response.data.data.on_sale_status}`);
} else {
throw new Error('更新险种状态失败');
}
} catch (error) {
throw new Error(`更新险种状态失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 7. 测试删除险种
async function testDeleteInsuranceType() {
console.log('🗑️ 测试删除险种...');
if (!testInsuranceTypeId) {
throw new Error('没有可用的测试险种ID');
}
try {
const response = await api.delete(`/insurance-types/${testInsuranceTypeId}`);
if (response.data.success) {
console.log(`✅ 删除险种成功ID: ${testInsuranceTypeId}`);
} else {
throw new Error('删除险种失败');
}
} catch (error) {
throw new Error(`删除险种失败: ${error.response?.data?.message || error.message}`);
}
console.log('');
}
// 运行测试
if (require.main === module) {
runTests().catch(error => {
console.error('测试运行失败:', error.message);
process.exit(1);
});
}
module.exports = {
runTests,
testLogin,
testGetInsuranceTypes,
testCreateInsuranceType,
testGetInsuranceTypeById,
testUpdateInsuranceType,
testUpdateInsuranceTypeStatus,
testDeleteInsuranceType
};