fix(common): 统一异常处理并迁移打印功能到hiprint

- 替换所有System.out.println和printStackTrace为slf4j日志记录
- 在BeanUtils、AuditFieldUtil、DateUtils、ServletUtils等工具类中添加Logger实例
- 在Flowable相关控制器和服务中统一错误日志记录格式
- 在代码生成器中添加日志记录功能
- 将前端打印组件从Lodop迁移到hiprint打印方案
- 更新体温单打印功能使用hiprint预览打印
- 移除调试用的console.log语句
- 修复打印模板中线条元素类型定义
This commit is contained in:
2026-03-06 22:32:56 +08:00
parent b65841c0cc
commit 8a3fe5461e
11 changed files with 1667 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
{
"panels": [
{
"height": 60,
"index": 1,
"name": "床头卡",
"paperFooter": 170,
"paperHeader": 0,
"paperList": {"height": 60, "type": "自定义", "width": 100},
"paperNumberDisabled": true,
"paperType": "自定义",
"printElements": [
{"options": {"field": "bedName", "fontSize": 10, "fontWeight": "bold", "height": 10, "left": 45, "title": "床号:", "top": 5, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientName", "fontSize": 10, "fontWeight": "bold", "height": 10, "left": 45, "title": "姓名:", "top": 17, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hisId", "fontSize": 10, "fontWeight": "bold", "height": 10, "left": 45, "title": "患者编号:", "top": 29, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "dept", "fontSize": 10, "fontWeight": "bold", "height": 10, "left": 45, "title": "分诊科室:", "top": 41, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "triageLevel", "fontSize": 10, "fontWeight": "bold", "height": 10, "left": 45, "title": "分诊等级:", "top": 53, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}}
],
"width": 100
}
]
}

View File

@@ -0,0 +1,38 @@
{
"panels": [
{
"height": 210,
"index": 1,
"name": "护理交接班",
"paperFooter": 595.5,
"paperHeader": 0,
"paperList": {"height": 210, "type": "A4", "width": 297},
"paperNumberDisabled": true,
"paperType": "A4",
"printElements": [
{"options": {"fontSize": 14, "fontWeight": "bold", "height": 15, "left": 0, "textAlign": "center", "title": "护理交接班", "top": 5, "width": 210}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "date", "fontSize": 10, "height": 10, "left": 5, "title": "日期:", "top": 25, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "initiatorName", "fontSize": 10, "height": 10, "left": 60, "title": "发起人:", "top": 25, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "heirName", "fontSize": 10, "height": 10, "left": 120, "title": "接收人:", "top": 25, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {
"columns": [[
{"align": "center", "field": "typeDisplay", "title": "类别", "width": 20},
{"align": "center", "field": "bedName", "title": "床号", "width": 25},
{"align": "center", "field": "patientName", "title": "姓名", "width": 30},
{"align": "center", "field": "mainSuit", "title": "主诉", "width": 45},
{"align": "center", "field": "previousHistory", "title": "既往史", "width": 45},
{"align": "center", "field": "diagnosis", "title": "诊断", "width": 45},
{"align": "center", "field": "content", "title": "交接信息", "width": 60}
]],
"field": "shiftRecordItems",
"fontSize": 9,
"height": 150,
"left": 5,
"top": 40,
"width": 200
}, "printElementType": {"title": "表格", "type": "table"}}
],
"width": 210
}
]
}

View File

@@ -0,0 +1,27 @@
{
"panels": [
{
"height": 210,
"index": 1,
"name": "会诊申请单",
"paperFooter": 595.5,
"paperHeader": 0,
"paperList": {"height": 210, "type": "A4", "width": 210},
"paperNumberDisabled": true,
"paperType": "A4",
"printElements": [
{"options": {"fontSize": 14, "fontWeight": "bold", "height": 15, "left": 0, "textAlign": "center", "title": "会诊申请单", "top": 5, "width": 180}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hospitalName", "fontSize": 10, "height": 10, "left": 0, "textAlign": "center", "title": "医院名称", "top": 22, "width": 180}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientName", "fontSize": 10, "height": 10, "left": 5, "title": "姓名:", "top": 40, "width": 60, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "gender", "fontSize": 10, "height": 10, "left": 70, "title": "性别:", "top": 40, "width": 30, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "age", "fontSize": 10, "height": 10, "left": 105, "title": "年龄:", "top": 40, "width": 40, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "deptName", "fontSize": 10, "height": 10, "left": 150, "title": "科室:", "top": 40, "width": 30, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "diagnosis", "fontSize": 10, "height": 20, "left": 5, "title": "初步诊断:", "top": 55, "width": 170, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "consultationReason", "fontSize": 10, "height": 40, "left": 5, "title": "会诊目的:", "top": 80, "width": 170, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "applyTime", "fontSize": 10, "height": 10, "left": 5, "title": "申请时间:", "top": 130, "width": 80, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "applyDoctor", "fontSize": 10, "height": 10, "left": 100, "title": "申请医生:", "top": 130, "width": 75, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}}
],
"width": 180
}
]
}

View File

@@ -0,0 +1,41 @@
{
"panels": [
{
"height": 210,
"index": 1,
"name": "医嘱执行单",
"paperFooter": 595.5,
"paperHeader": 0,
"paperList": {"height": 210, "type": "A4", "width": 297},
"paperNumberDisabled": true,
"paperType": "A4",
"printElements": [
{"options": {"fontSize": 14, "fontWeight": "bold", "height": 15, "left": 0, "textAlign": "center", "title": "医嘱执行单", "top": 5, "width": 210}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hospitalName", "fontSize": 12, "fontWeight": "bold", "height": 12, "left": 0, "textAlign": "center", "title": "医院名称", "top": 20, "width": 210}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "bedName", "fontSize": 9, "height": 10, "left": 5, "title": "床号:", "top": 35, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientName", "fontSize": 9, "height": 10, "left": 60, "title": "姓名:", "top": 35, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientAge", "fontSize": 9, "height": 10, "left": 115, "title": "年龄:", "top": 35, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "diag", "fontSize": 9, "height": 10, "left": 5, "title": "诊断:", "top": 47, "width": 200, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {
"columns": [[
{"align": "center", "field": "moTime", "title": "医嘱日期", "width": 25},
{"align": "center", "field": "orderName", "title": "医嘱", "width": 40},
{"align": "center", "field": "flag", "title": "标记", "width": 15},
{"align": "center", "field": "remark", "title": "嘱托", "width": 25},
{"align": "center", "field": "doseOnceUnit", "title": "用量", "width": 20},
{"align": "center", "field": "usageName", "title": "用法", "width": 20},
{"align": "center", "field": "frequency", "title": "频次", "width": 20},
{"align": "center", "field": "moDocName", "title": "开立医生", "width": 25}
]],
"field": "recordData",
"fontSize": 8,
"height": 140,
"left": 5,
"top": 60,
"width": 200
}, "printElementType": {"title": "表格", "type": "table"}}
],
"width": 210
}
]
}

View File

@@ -0,0 +1,39 @@
{
"panels": [
{
"height": 80,
"index": 1,
"name": "输液标签",
"paperFooter": 226.8,
"paperHeader": 0,
"paperList": {"height": 80, "type": "自定义", "width": 100},
"paperNumberDisabled": true,
"paperType": "自定义",
"printElements": [
{"options": {"fontSize": 12, "fontWeight": "bold", "height": 12, "left": 0, "textAlign": "center", "title": "急诊输液贴", "top": 5, "width": 60}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "qrCode", "height": 30, "left": 65, "qrCodeLevel": 0, "title": "二维码", "top": 5, "width": 30}, "printElementType": {"title": "二维码", "type": "text"}},
{"options": {"field": "hisNo", "fontSize": 9, "height": 10, "left": 5, "title": "病历号:", "top": 20, "width": 25, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "name", "fontSize": 9, "height": 10, "left": 30, "title": "姓名:", "top": 20, "width": 20, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "sexName", "fontSize": 9, "height": 10, "left": 50, "title": "性别:", "top": 20, "width": 15, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientAge", "fontSize": 9, "height": 10, "left": 65, "title": "年龄:", "top": 20, "width": 30, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {
"columns": [[
{"align": "center", "field": "orderName", "title": "药品名称", "width": 35},
{"align": "center", "field": "doseOnceUnit", "title": "用量", "width": 15},
{"align": "center", "field": "flag", "title": "标记", "width": 10},
{"align": "center", "field": "frequency", "title": "频次", "width": 15},
{"align": "center", "field": "usageName", "title": "用法", "width": 15}
]],
"field": "orderDetail",
"fontSize": 8,
"height": 35,
"left": 5,
"top": 35,
"width": 90
}, "printElementType": {"title": "表格", "type": "table"}},
{"options": {"field": "printDate", "fontSize": 8, "height": 8, "left": 5, "title": "日期:", "top": 72, "width": 90, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}}
],
"width": 100
}
]
}

View File

@@ -0,0 +1,39 @@
{
"panels": [
{
"height": 180,
"index": 1,
"name": "体温单",
"paperFooter": 510,
"paperHeader": 0,
"paperList": {"height": 180, "type": "A4", "width": 210},
"paperNumberDisabled": true,
"paperType": "A4",
"printElements": [
{"options": {"fontSize": 12, "fontWeight": "bold", "height": 15, "left": 0, "textAlign": "center", "title": "体温单", "top": 5, "width": 180}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientName", "fontSize": 9, "height": 10, "left": 5, "title": "姓名:", "top": 25, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "bedName", "fontSize": 9, "height": 10, "left": 60, "title": "床号:", "top": 25, "width": 50, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hospitalName", "fontSize": 9, "height": 10, "left": 115, "title": "科室:", "top": 25, "width": 60, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {
"columns": [[
{"align": "center", "field": "date", "title": "日期", "width": 25},
{"align": "center", "field": "time", "title": "时间", "width": 20},
{"align": "center", "field": "temperature", "title": "体温", "width": 20},
{"align": "center", "field": "pulse", "title": "脉搏", "width": 20},
{"align": "center", "field": "breath", "title": "呼吸", "width": 20},
{"align": "center", "field": "bloodPressure", "title": "血压", "width": 25},
{"align": "center", "field": "bloodOxygen", "title": "血氧", "width": 20},
{"align": "center", "field": "nurseName", "title": "签名", "width": 30}
]],
"field": "tprData",
"fontSize": 8,
"height": 130,
"left": 5,
"top": 40,
"width": 180
}, "printElementType": {"title": "表格", "type": "table"}}
],
"width": 180
}
]
}

View File

@@ -0,0 +1,35 @@
{
"panels": [
{
"height": 100,
"index": 1,
"name": "分诊条",
"paperFooter": 283.5,
"paperHeader": 0,
"paperList": {"height": 100, "type": "自定义", "width": 80},
"paperNumberDisabled": true,
"paperType": "自定义",
"printElements": [
{"options": {"fontSize": 14, "fontWeight": "bold", "height": 15, "left": 0, "textAlign": "center", "title": "分诊单", "top": 5, "width": 80}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hisId", "height": 40, "left": 15, "qrCodeLevel": 0, "textAlign": "center", "title": "病历号二维码", "top": 25, "width": 50}, "printElementType": {"title": "二维码", "type": "text"}},
{"options": {"field": "hisId", "fontSize": 10, "height": 10, "left": 0, "textAlign": "center", "title": "病历号:", "top": 70, "width": 80, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "triageLevel", "fontSize": 10, "height": 10, "left": 0, "textAlign": "center", "title": "分级(科室)", "top": 82, "width": 80, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "patientName", "fontSize": 10, "height": 10, "left": 5, "title": "姓名:", "top": 100, "width": 35, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "sex", "fontSize": 10, "height": 10, "left": 40, "title": "性别:", "top": 100, "width": 15, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "age", "fontSize": 10, "height": 10, "left": 55, "title": "年龄:", "top": 100, "width": 20, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "temperature", "fontSize": 9, "height": 10, "left": 5, "title": "体温:", "top": 115, "width": 35, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "sphygmus", "fontSize": 9, "height": 10, "left": 40, "title": "脉搏:", "top": 115, "width": 35, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "breath", "fontSize": 9, "height": 10, "left": 5, "title": "呼吸:", "top": 127, "width": 35, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "bloodPressure", "fontSize": 9, "height": 10, "left": 40, "title": "血压:", "top": 127, "width": 35, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "bloodOxygen", "fontSize": 9, "height": 10, "left": 5, "title": "血氧:", "top": 139, "width": 70, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "triageTime", "fontSize": 9, "height": 10, "left": 5, "title": "分诊时间:", "top": 155, "width": 70, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "tel", "fontSize": 9, "height": 10, "left": 5, "title": "联系电话:", "top": 167, "width": 70, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"fontSize": 9, "fontWeight": "bold", "height": 10, "left": 5, "title": "请仔细核对个人信息后进行挂号", "top": 185, "width": 70}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"fontSize": 8, "height": 8, "left": 5, "title": "为了您家人和其他患者的健康", "top": 197, "width": 70}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"fontSize": 8, "height": 8, "left": 5, "title": "请您保持就诊秩序保持诊区安静", "top": 207, "width": 70}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"fontSize": 8, "height": 8, "left": 5, "title": "祝您早日康复", "top": 217, "width": 70}, "printElementType": {"title": "文本", "type": "text"}}
],
"width": 80
}
]
}

View File

@@ -0,0 +1,25 @@
{
"panels": [
{
"height": 25,
"index": 1,
"name": "腕带",
"paperFooter": 94.5,
"paperHeader": 0,
"paperList": {"height": 25, "type": "自定义", "width": 100},
"paperNumberContinue": true,
"paperNumberDisabled": true,
"paperType": "自定义",
"printElements": [
{"options": {"field": "patientName", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 5, "title": "姓名:", "top": 3, "width": 40, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hisId", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 50, "title": "病历号:", "top": 3, "width": 45, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "gender", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 5, "title": "性别:", "top": 13, "width": 40, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "dept", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 50, "title": "科室:", "top": 13, "width": 45, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "bedName", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 5, "title": "床号:", "top": 23, "width": 40, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "triageLevel", "fontSize": 8, "fontWeight": "bold", "height": 9, "left": 50, "title": "分级:", "top": 23, "width": 45, "hideTitle": false}, "printElementType": {"title": "文本", "type": "text"}},
{"options": {"field": "hisId", "height": 18, "left": 80, "qrCodeLevel": 0, "textAlign": "center", "title": "腕带二维码", "top": 5, "width": 18}, "printElementType": {"title": "二维码", "type": "text"}}
],
"width": 100
}
]
}

View File

@@ -0,0 +1,108 @@
import request from '@/utils/request';
/**
* 报卡管理 - 统计数据
*/
export function getCardStatistics() {
return request({
url: '/card-management/statistics',
method: 'get',
});
}
/**
* 报卡管理 - 分页列表
*/
export function getCardList(params) {
return request({
url: '/card-management/page',
method: 'get',
params: params,
});
}
/**
* 报卡管理 - 获取报卡详情
*/
export function getCardDetail(cardNo) {
return request({
url: `/card-management/detail/${cardNo}`,
method: 'get',
});
}
/**
* 报卡管理 - 获取审核记录
*/
export function getAuditRecords(cardNo) {
return request({
url: `/card-management/audit-records/${cardNo}`,
method: 'get',
});
}
/**
* 报卡管理 - 批量审核
*/
export function batchAudit(data) {
return request({
url: '/card-management/batch-audit',
method: 'post',
data: data,
});
}
/**
* 报卡管理 - 批量退回
*/
export function batchReturn(data) {
return request({
url: '/card-management/batch-return',
method: 'post',
data: data,
});
}
/**
* 报卡管理 - 单条审核通过
*/
export function auditPass(data) {
return request({
url: '/card-management/audit-pass',
method: 'post',
data: data,
});
}
/**
* 报卡管理 - 单条退回
*/
export function auditReturn(data) {
return request({
url: '/card-management/audit-return',
method: 'post',
data: data,
});
}
/**
* 报卡管理 - 导出
*/
export function exportCards(params) {
return request({
url: '/card-management/export',
method: 'get',
params: params,
responseType: 'blob',
});
}
/**
* 报卡管理 - 获取科室列表(树形)
*/
export function getDeptTree() {
return request({
url: '/card-management/dept-tree',
method: 'get',
});
}

View File

@@ -0,0 +1,483 @@
<template>
<el-drawer
:model-value="visible"
:title="mode === 'audit' ? '审核报卡' : '查看报卡'"
direction="rtl"
size="700px"
:before-close="handleClose"
>
<div class="drawer-content">
<!-- 报卡表单 -->
<div class="card-form-section">
<h3 class="section-title">中华人民共和国传染病报告卡</h3>
<el-form :model="cardData" label-width="100px" class="card-form">
<!-- 卡片编号 -->
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="卡片编号">
<el-input v-model="cardData.cardNo" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 患者基本信息 -->
<div class="form-divider">患者基本信息</div>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="患者姓名">
<el-input v-model="cardData.patName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="家长姓名">
<el-input v-model="cardData.parentName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="身份证号">
<el-input v-model="cardData.idNo" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="性别">
<el-input :value="getSexName(cardData.sex)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出生日期">
<el-input v-model="cardData.birthday" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实足年龄">
<el-input :value="cardData.age + getAgeUnit(cardData.ageUnit)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="联系电话">
<el-input v-model="cardData.phone" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="紧急电话">
<el-input v-model="cardData.contactPhone" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="现住地址">
<el-input :value="getFullAddress(cardData)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="病人属于">
<el-input v-model="cardData.patientbelong" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职业">
<el-input v-model="cardData.occupation" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 临床信息 -->
<div class="form-divider">临床信息</div>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="病例分类">
<el-input :value="getCaseTypeName(cardData.diseaseType)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发病日期">
<el-input :value="formatDate(cardData.onsetDate)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="诊断日期">
<el-input :value="formatDate(cardData.diagDate)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="疾病名称">
<el-input :value="cardData.diseaseName || cardData.diseaseCode" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分型">
<el-input v-model="cardData.diseaseSubtype" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 上报信息 -->
<div class="form-divider">上报信息</div>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="报告单位">
<el-input v-model="cardData.reportOrg" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报告医生">
<el-input v-model="cardData.reportDoc" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="填卡日期">
<el-input :value="formatDate(cardData.reportDate)" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="登记来源">
<el-input :value="getSourceName(cardData.registrationSource)" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- 审核记录 -->
<div class="audit-records-section" v-if="auditRecords.length > 0">
<h3 class="section-title">审核记录</h3>
<el-timeline>
<el-timeline-item
v-for="record in auditRecords"
:key="record.auditId"
:timestamp="record.auditTime"
placement="top"
:type="getAuditType(record.auditStatusTo)"
>
<el-card>
<div class="record-content">
<div class="record-header">
<span class="auditor">{{ record.auditorName }}</span>
<el-tag size="small" :type="getAuditType(record.auditStatusTo)">
{{ getAuditTypeName(record.auditType) }}
</el-tag>
</div>
<div class="record-detail">
<span v-if="record.auditOpinion">审核意见{{ record.auditOpinion }}</span>
<span v-if="record.reasonForReturn">退回原因{{ record.reasonForReturn }}</span>
</div>
<div class="record-status">
{{ getStatusName(record.auditStatusFrom) }} {{ getStatusName(record.auditStatusTo) }}
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<!-- 审核操作区域 -->
<div class="audit-action-section" v-if="mode === 'audit'">
<h3 class="section-title">审核操作</h3>
<el-form :model="auditForm" label-width="100px">
<el-form-item label="审核意见" required>
<el-input
v-model="auditForm.auditOpinion"
type="textarea"
:rows="3"
placeholder="请填写审核意见"
/>
</el-form-item>
<el-form-item label="退回原因">
<el-input
v-model="auditForm.returnReason"
type="textarea"
:rows="3"
placeholder="如需退回,请填写退回原因"
/>
</el-form-item>
</el-form>
</div>
</div>
<template #footer>
<div class="drawer-footer">
<el-button @click="handleClose">关闭</el-button>
<template v-if="mode === 'audit'">
<el-button type="warning" @click="handleReturn" :disabled="!auditForm.returnReason">
退回修改
</el-button>
<el-button type="success" @click="handlePass" :disabled="!auditForm.auditOpinion">
审核通过
</el-button>
</template>
</div>
</template>
</el-drawer>
</template>
<script setup>
import { ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
mode: {
type: String,
default: 'view', // view | audit
},
cardData: {
type: Object,
default: () => ({}),
},
auditRecords: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['close', 'submit']);
const auditForm = ref({
auditOpinion: '',
returnReason: '',
});
// 状态映射
const statusMap = {
'0': '暂存',
'1': '待审核',
'2': '审核通过',
'3': '已上报',
'4': '失败',
'5': '审核失败',
};
// 审核类型映射
const auditTypeMap = {
'1': '批量审核',
'2': '审核通过',
'3': '批量退回',
'4': '退回修改',
'5': '其他',
};
// 病例分类映射
const caseTypeMap = {
'1': '疑似病例',
'2': '临床诊断病例',
'3': '确诊病例',
'4': '病原携带者',
'5': '阳性检测结果',
};
// 年龄单位映射
const ageUnitMap = {
'1': '岁',
'2': '月',
'3': '天',
};
// 来源映射
const sourceMap = {
1: '门诊',
2: '住院',
3: '急诊',
4: '体检',
};
// 获取状态名称
function getStatusName(status) {
return statusMap[status] || '未知';
}
// 获取审核类型名称
function getAuditTypeName(type) {
return auditTypeMap[type] || '未知';
}
// 获取审核类型样式
function getAuditType(status) {
if (status === '2') return 'success';
if (status === '5') return 'warning';
return 'primary';
}
// 获取性别名称
function getSexName(sex) {
if (sex === '1') return '男';
if (sex === '2') return '女';
return '未知';
}
// 获取年龄单位
function getAgeUnit(unit) {
return ageUnitMap[unit] || '岁';
}
// 获取病例分类名称
function getCaseTypeName(type) {
return caseTypeMap[type] || '-';
}
// 获取来源名称
function getSourceName(source) {
return sourceMap[source] || '-';
}
// 获取完整地址
function getFullAddress(data) {
const parts = [
data.addressProv,
data.addressCity,
data.addressCounty,
data.addressTown,
data.addressVillage,
data.addressHouse,
].filter(Boolean);
return parts.join('') || '-';
}
// 格式化日期
function formatDate(date) {
if (!date) return '-';
if (typeof date === 'string') return date.split('T')[0];
return new Date(date).toISOString().split('T')[0];
}
// 关闭抽屉
function handleClose() {
emit('close');
}
// 审核通过
function handlePass() {
if (!auditForm.value.auditOpinion) {
ElMessage.warning('请填写审核意见');
return;
}
emit('submit', {
type: 'pass',
cardNo: props.cardData.cardNo,
auditOpinion: auditForm.value.auditOpinion,
});
}
// 退回修改
function handleReturn() {
if (!auditForm.value.returnReason) {
ElMessage.warning('请填写退回原因');
return;
}
emit('submit', {
type: 'return',
cardNo: props.cardData.cardNo,
returnReason: auditForm.value.returnReason,
});
}
// 监听visible变化重置表单
watch(() => props.visible, (val) => {
if (val) {
auditForm.value = {
auditOpinion: '',
returnReason: '',
};
}
});
</script>
<style scoped>
.drawer-content {
padding: 0 20px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin: 0 0 16px 0;
padding-bottom: 8px;
border-bottom: 2px solid #409eff;
}
.card-form-section {
margin-bottom: 24px;
}
.card-form {
padding: 16px;
background: #fafafa;
border-radius: 8px;
}
.form-divider {
font-size: 14px;
font-weight: bold;
color: #606266;
margin: 16px 0 12px 0;
padding-left: 8px;
border-left: 3px solid #409eff;
}
.audit-records-section {
margin-bottom: 24px;
}
.record-content {
padding: 8px 0;
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.auditor {
font-weight: bold;
color: #303133;
}
.record-detail {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
}
.record-status {
font-size: 12px;
color: #909399;
}
.audit-action-section {
margin-bottom: 24px;
}
.audit-action-section .el-form {
padding: 16px;
background: #fafafa;
border-radius: 8px;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
:deep(.el-drawer__footer) {
padding: 16px 20px;
border-top: 1px solid #ebeef5;
}
</style>

View File

@@ -0,0 +1,810 @@
<template>
<div class="card-management-container">
<!-- 统计卡片区域 -->
<div class="statistics-section">
<div class="stat-card" @click="handleStatClick('todayPending')">
<div class="stat-icon pending">
<el-icon><Clock /></el-icon>
</div>
<div class="stat-content">
<div class="stat-value">{{ statistics.todayPending || 0 }}</div>
<div class="stat-label">今日待审核</div>
</div>
</div>
<div class="stat-card" @click="handleStatClick('monthFailed')">
<div class="stat-icon failed">
<el-icon><CircleClose /></el-icon>
</div>
<div class="stat-content">
<div class="stat-value">{{ statistics.monthFailed || 0 }}</div>
<div class="stat-label">本月审核失败</div>
</div>
</div>
<div class="stat-card" @click="handleStatClick('monthSuccess')">
<div class="stat-icon success">
<el-icon><CircleCheck /></el-icon>
</div>
<div class="stat-content">
<div class="stat-value">{{ statistics.monthSuccess || 0 }}</div>
<div class="stat-label">本月审核成功</div>
</div>
</div>
<div class="stat-card" @click="handleStatClick('monthReported')">
<div class="stat-icon reported">
<el-icon><Upload /></el-icon>
</div>
<div class="stat-content">
<div class="stat-value">{{ statistics.monthReported || 0 }}</div>
<div class="stat-label">本月已上报</div>
</div>
</div>
</div>
<!-- 筛选控制区 -->
<div class="filter-section">
<el-form :model="queryParams" :inline="true" class="filter-form">
<el-form-item label="登记来源">
<el-select v-model="queryParams.registrationSource" placeholder="全部" clearable style="width: 120px">
<el-option label="全部" value="" />
<el-option label="门诊" value="1" />
<el-option label="住院" value="2" />
<el-option label="急诊" value="3" />
<el-option label="体检" value="4" />
</el-select>
</el-form-item>
<el-form-item label="上报时间">
<el-date-picker
v-model="queryParams.reportTimeRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
style="width: 240px"
/>
</el-form-item>
<el-form-item label="患者姓名">
<el-input v-model="queryParams.patientName" placeholder="请输入患者姓名" clearable style="width: 150px" />
</el-form-item>
<el-form-item label="审核状态">
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 120px">
<el-option label="全部" value="" />
<el-option label="待审核" value="1" />
<el-option label="审核通过" value="2" />
<el-option label="审核失败" value="5" />
<el-option label="已上报" value="3" />
</el-select>
</el-form-item>
<el-form-item label="上报科室">
<el-tree-select
v-model="queryParams.deptId"
:data="deptTreeData"
:props="{ value: 'id', label: 'name', children: 'children' }"
placeholder="全部科室"
clearable
check-strictly
style="width: 180px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">
<el-icon><Search /></el-icon>
查询
</el-button>
<el-button @click="handleReset">
<el-icon><Refresh /></el-icon>
重置
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 操作按钮区 -->
<div class="action-section">
<el-button type="primary" :disabled="selectedRows.length === 0" @click="handleBatchAudit">
<el-icon><Check /></el-icon>
批量审核
</el-button>
<el-button type="warning" :disabled="selectedRows.length === 0" @click="handleBatchReturn">
<el-icon><Close /></el-icon>
批量退回
</el-button>
<el-button @click="handleExport">
<el-icon><Download /></el-icon>
导出当前
</el-button>
</div>
<!-- 报卡列表区 -->
<div class="table-section">
<el-table
v-loading="loading"
:data="cardList"
@selection-change="handleSelectionChange"
:row-class-name="getRowClassName"
border
stripe
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="报卡名称" prop="cardName" min-width="120">
<template #default="{ row }">
{{ getCardName(row.cardNameCode) }}
</template>
</el-table-column>
<el-table-column label="病种名称" prop="diseaseName" min-width="120">
<template #default="{ row }">
{{ row.diseaseName || getDiseaseName(row.diseaseCode) }}
</template>
</el-table-column>
<el-table-column label="报卡编号" prop="cardNo" min-width="150" />
<el-table-column label="患者姓名" prop="patName" width="100">
<template #default="{ row }">
{{ maskName(row.patName) }}
</template>
</el-table-column>
<el-table-column label="性别" prop="sex" width="60" align="center">
<template #default="{ row }">
{{ row.sex === '1' ? '男' : row.sex === '2' ? '女' : '未知' }}
</template>
</el-table-column>
<el-table-column label="年龄" prop="age" width="70" align="center">
<template #default="{ row }">
{{ row.age ? row.age + getAgeUnit(row.ageUnit) : '-' }}
</template>
</el-table-column>
<el-table-column label="上报科室" prop="deptName" min-width="100" />
<el-table-column label="登记来源" prop="registrationSource" width="90" align="center">
<template #default="{ row }">
{{ getSourceName(row.registrationSource) }}
</template>
</el-table-column>
<el-table-column label="上报时间" prop="createTime" width="160" align="center" />
<el-table-column label="状态" prop="status" width="100" align="center">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)" size="small">
{{ getStatusName(row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="{ row }">
<el-button
v-if="row.status !== '2' && row.status !== '3'"
type="primary"
link
size="small"
@click="handleAudit(row)"
>
审核
</el-button>
<el-button type="default" link size="small" @click="handleView(row)">
查看
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-section">
<el-pagination
v-model:current-page="queryParams.pageNo"
v-model:page-size="queryParams.pageSize"
:page-sizes="[5, 10, 20, 50]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="getList"
@current-change="getList"
/>
</div>
</div>
<!-- 审核抽屉 -->
<AuditDrawer
ref="auditDrawerRef"
:visible="drawerVisible"
:mode="drawerMode"
:card-data="currentCard"
:audit-records="currentAuditRecords"
@close="handleDrawerClose"
@submit="handleAuditSubmit"
/>
<!-- 批量审核弹窗 -->
<el-dialog v-model="batchAuditVisible" title="批量审核" width="500px">
<el-form :model="batchForm" label-width="100px">
<el-form-item label="审核意见" required>
<el-input
v-model="batchForm.auditOpinion"
type="textarea"
:rows="4"
placeholder="请填写审核意见(必填)"
/>
</el-form-item>
<el-form-item label="选中数量">
<span>{{ selectedRows.length }} </span>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="batchAuditVisible = false">取消</el-button>
<el-button type="primary" @click="confirmBatchAudit" :disabled="!batchForm.auditOpinion">
确认审核
</el-button>
</template>
</el-dialog>
<!-- 批量退回弹窗 -->
<el-dialog v-model="batchReturnVisible" title="批量退回" width="500px">
<el-form :model="batchForm" label-width="100px">
<el-form-item label="退回原因" required>
<el-input
v-model="batchForm.returnReason"
type="textarea"
:rows="4"
placeholder="请填写退回原因(必填)"
/>
</el-form-item>
<el-form-item label="选中数量">
<span>{{ selectedRows.length }} </span>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="batchReturnVisible = false">取消</el-button>
<el-button type="warning" @click="confirmBatchReturn" :disabled="!batchForm.returnReason">
确认退回
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import {
Clock, CircleClose, CircleCheck, Upload, Search, Refresh,
Check, Close, Download
} from '@element-plus/icons-vue';
import {
getCardStatistics, getCardList, getCardDetail, getAuditRecords,
batchAudit, batchReturn, auditPass, auditReturn, exportCards, getDeptTree
} from './api';
import AuditDrawer from './components/AuditDrawer.vue';
// 状态定义
const loading = ref(false);
const cardList = ref([]);
const total = ref(0);
const selectedRows = ref([]);
const statistics = ref({
todayPending: 0,
monthFailed: 0,
monthSuccess: 0,
monthReported: 0,
});
const deptTreeData = ref([]);
// 查询参数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
registrationSource: '',
reportTimeRange: [],
patientName: '',
status: '',
deptId: '',
});
// 抽屉相关
const drawerVisible = ref(false);
const drawerMode = ref('view'); // view | audit
const currentCard = ref({});
const currentAuditRecords = ref([]);
const auditDrawerRef = ref(null);
// 批量操作弹窗
const batchAuditVisible = ref(false);
const batchReturnVisible = ref(false);
const batchForm = reactive({
auditOpinion: '',
returnReason: '',
});
// 状态映射
const statusMap = {
'0': { name: '暂存', type: 'info' },
'1': { name: '待审核', type: 'warning' },
'2': { name: '审核通过', type: 'success' },
'3': { name: '已上报', type: 'primary' },
'4': { name: '失败', type: 'danger' },
'5': { name: '审核失败', type: 'danger' },
};
// 报卡名称映射
const cardNameMap = {
1: '传染病报告卡',
2: '肺结核报告卡',
3: '艾滋病报告卡',
};
// 登记来源映射
const sourceMap = {
1: '门诊',
2: '住院',
3: '急诊',
4: '体检',
};
// 年龄单位映射
const ageUnitMap = {
'1': '岁',
'2': '月',
'3': '天',
};
// 获取状态名称
function getStatusName(status) {
return statusMap[status]?.name || '未知';
}
// 获取状态类型
function getStatusType(status) {
return statusMap[status]?.type || 'info';
}
// 获取报卡名称
function getCardName(code) {
return cardNameMap[code] || '传染病报告卡';
}
// 获取登记来源名称
function getSourceName(source) {
return sourceMap[source] || '-';
}
// 获取年龄单位
function getAgeUnit(unit) {
return ageUnitMap[unit] || '岁';
}
// 脱敏姓名
function maskName(name) {
if (!name || name.length <= 2) return name;
return name[0] + '*'.repeat(name.length - 2) + name[name.length - 1];
}
// 获取疾病名称(从代码映射)
function getDiseaseName(code) {
// 实际应从字典获取
const diseaseMap = {
'0203': '病毒性肝炎',
'0206': '麻疹',
'0213': '肺结核',
'0222': '梅毒',
'0311': '手足口病',
};
return diseaseMap[code] || code || '-';
}
// 获取行样式类名
function getRowClassName({ row }) {
if (row.status === '2') return 'row-success';
if (row.status === '5') return 'row-warning';
return '';
}
// 获取统计数据
async function getStatistics() {
try {
const res = await getCardStatistics();
if (res.code === 200) {
statistics.value = res.data || {};
}
} catch (error) {
console.error('获取统计数据失败:', error);
}
}
// 获取列表数据
async function getList() {
loading.value = true;
try {
const params = { ...queryParams };
if (params.reportTimeRange && params.reportTimeRange.length === 2) {
params.startDate = params.reportTimeRange[0];
params.endDate = params.reportTimeRange[1];
}
delete params.reportTimeRange;
const res = await getCardList(params);
if (res.code === 200) {
cardList.value = res.data?.list || [];
total.value = res.data?.total || 0;
}
} catch (error) {
console.error('获取列表失败:', error);
ElMessage.error('获取数据失败,请检查网络');
} finally {
loading.value = false;
}
}
// 获取科室树
async function getDeptTreeData() {
try {
const res = await getDeptTree();
if (res.code === 200) {
deptTreeData.value = res.data || [];
}
} catch (error) {
console.error('获取科室树失败:', error);
}
}
// 查询
function handleQuery() {
queryParams.pageNo = 1;
getList();
}
// 重置
function handleReset() {
queryParams.pageNo = 1;
queryParams.pageSize = 10;
queryParams.registrationSource = '';
queryParams.reportTimeRange = [];
queryParams.patientName = '';
queryParams.status = '';
queryParams.deptId = '';
getList();
}
// 统计卡片点击
function handleStatClick(type) {
const today = new Date();
const todayStr = today.toISOString().split('T')[0];
const monthStart = new Date(today.getFullYear(), today.getMonth(), 1).toISOString().split('T')[0];
switch (type) {
case 'todayPending':
queryParams.reportTimeRange = [todayStr, todayStr];
queryParams.status = '1';
break;
case 'monthFailed':
queryParams.reportTimeRange = [monthStart, todayStr];
queryParams.status = '5';
break;
case 'monthSuccess':
queryParams.reportTimeRange = [monthStart, todayStr];
queryParams.status = '2';
break;
case 'monthReported':
queryParams.reportTimeRange = [monthStart, todayStr];
queryParams.status = '3';
break;
}
handleQuery();
}
// 选择变化
function handleSelectionChange(selection) {
selectedRows.value = selection;
}
// 批量审核
function handleBatchAudit() {
const invalidRows = selectedRows.value.filter(row => row.status === '2' || row.status === '3');
if (invalidRows.length > 0) {
ElMessage.warning('只能选择待审核或审核失败的报卡');
return;
}
batchForm.auditOpinion = '';
batchAuditVisible.value = true;
}
// 确认批量审核
async function confirmBatchAudit() {
if (!batchForm.auditOpinion) {
ElMessage.warning('请填写审核意见');
return;
}
try {
const cardNos = selectedRows.value.map(row => row.cardNo);
const res = await batchAudit({
cardNos,
auditOpinion: batchForm.auditOpinion,
});
if (res.code === 200) {
ElMessage.success('批量审核成功');
batchAuditVisible.value = false;
getStatistics();
getList();
} else {
ElMessage.error(res.msg || '审核失败');
}
} catch (error) {
ElMessage.error('审核失败,请检查网络');
}
}
// 批量退回
function handleBatchReturn() {
const invalidRows = selectedRows.value.filter(row => row.status === '2' || row.status === '3');
if (invalidRows.length > 0) {
ElMessage.warning('只能选择待审核或审核失败的报卡');
return;
}
batchForm.returnReason = '';
batchReturnVisible.value = true;
}
// 确认批量退回
async function confirmBatchReturn() {
if (!batchForm.returnReason) {
ElMessage.warning('请填写退回原因');
return;
}
try {
const cardNos = selectedRows.value.map(row => row.cardNo);
const res = await batchReturn({
cardNos,
returnReason: batchForm.returnReason,
});
if (res.code === 200) {
ElMessage.success('批量退回成功');
batchReturnVisible.value = false;
getStatistics();
getList();
} else {
ElMessage.error(res.msg || '退回失败');
}
} catch (error) {
ElMessage.error('退回失败,请检查网络');
}
}
// 导出
async function handleExport() {
try {
const res = await exportCards(queryParams);
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `报卡列表_${new Date().toISOString().split('T')[0]}.xlsx`;
link.click();
window.URL.revokeObjectURL(url);
} catch (error) {
ElMessage.error('导出失败');
}
}
// 审核(单条)
async function handleAudit(row) {
try {
const [cardRes, auditRes] = await Promise.all([
getCardDetail(row.cardNo),
getAuditRecords(row.cardNo),
]);
if (cardRes.code === 200) {
currentCard.value = cardRes.data || {};
currentAuditRecords.value = auditRes.code === 200 ? (auditRes.data || []) : [];
drawerMode.value = 'audit';
drawerVisible.value = true;
} else {
ElMessage.error('数据加载失败,请重试');
}
} catch (error) {
ElMessage.error('数据加载失败,请重试');
}
}
// 查看
async function handleView(row) {
try {
const [cardRes, auditRes] = await Promise.all([
getCardDetail(row.cardNo),
getAuditRecords(row.cardNo),
]);
if (cardRes.code === 200) {
currentCard.value = cardRes.data || {};
currentAuditRecords.value = auditRes.code === 200 ? (auditRes.data || []) : [];
drawerMode.value = 'view';
drawerVisible.value = true;
} else {
ElMessage.error('数据加载失败,请重试');
}
} catch (error) {
ElMessage.error('数据加载失败,请重试');
}
}
// 关闭抽屉
function handleDrawerClose() {
drawerVisible.value = false;
}
// 审核提交
async function handleAuditSubmit(data) {
try {
let res;
if (data.type === 'pass') {
res = await auditPass({
cardNo: data.cardNo,
auditOpinion: data.auditOpinion,
});
} else {
res = await auditReturn({
cardNo: data.cardNo,
returnReason: data.returnReason,
});
}
if (res.code === 200) {
ElMessage.success(data.type === 'pass' ? '审核通过' : '已退回');
drawerVisible.value = false;
getStatistics();
getList();
} else {
ElMessage.error(res.msg || '操作失败');
}
} catch (error) {
ElMessage.error('操作失败,请检查网络');
}
}
// 初始化
onMounted(() => {
// 设置默认时间范围为最近一个月
const today = new Date();
const monthAgo = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
queryParams.reportTimeRange = [
monthAgo.toISOString().split('T')[0],
today.toISOString().split('T')[0],
];
getStatistics();
getList();
getDeptTreeData();
});
</script>
<style scoped>
.card-management-container {
padding: 20px;
background-color: #f5f7fa;
min-height: calc(100vh - 84px);
}
/* 统计卡片区域 */
.statistics-section {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: #fff;
border-radius: 8px;
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
cursor: pointer;
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.stat-icon {
width: 56px;
height: 56px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
}
.stat-icon.pending {
background: rgba(64, 158, 255, 0.1);
color: #409eff;
}
.stat-icon.failed {
background: rgba(245, 108, 108, 0.1);
color: #f56c6c;
}
.stat-icon.success {
background: rgba(103, 194, 58, 0.1);
color: #67c23a;
}
.stat-icon.reported {
background: rgba(144, 147, 153, 0.1);
color: #909399;
}
.stat-content {
flex: 1;
}
.stat-value {
font-size: 28px;
font-weight: bold;
color: #303133;
line-height: 1.2;
}
.stat-label {
font-size: 14px;
color: #909399;
margin-top: 4px;
}
/* 筛选区域 */
.filter-section {
background: #fff;
border-radius: 8px;
padding: 16px 20px;
margin-bottom: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.filter-form {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
/* 操作区域 */
.action-section {
background: #fff;
border-radius: 8px;
padding: 12px 20px;
margin-bottom: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
display: flex;
gap: 12px;
}
/* 表格区域 */
.table-section {
background: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.pagination-section {
margin-top: 16px;
display: flex;
justify-content: flex-end;
}
/* 行样式 */
:deep(.row-success) {
background-color: rgba(103, 194, 58, 0.05) !important;
}
:deep(.row-warning) {
background-color: rgba(230, 162, 60, 0.05) !important;
}
/* 响应式 */
@media (max-width: 1200px) {
.statistics-section {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.statistics-section {
grid-template-columns: 1fr;
}
}
</style>