<template>
|
<div class="batch-process">
|
<!-- 页面标题 -->
|
<div class="page-header">
|
<div class="header-content">
|
<h2 class="page-title">异常批量处理</h2>
|
<p class="page-description">批量处理选中的异常反馈</p>
|
<div class="header-actions">
|
<el-button
|
type="primary"
|
icon="el-icon-check"
|
@click="handleBatchSubmit"
|
:loading="batchProcessing"
|
>
|
批量提交处理
|
</el-button>
|
<el-button
|
type="warning"
|
icon="el-icon-back"
|
@click="handleGoBack"
|
>
|
返回异常列表
|
</el-button>
|
</div>
|
</div>
|
</div>
|
|
<!-- 异常列表 -->
|
<div class="list-section">
|
<el-card shadow="never">
|
<div class="filter-section">
|
<el-form
|
:model="filterParams"
|
:inline="true"
|
size="medium"
|
class="filter-form"
|
>
|
<el-form-item label="负责科室">
|
<el-select
|
v-model="filterParams.deptId"
|
placeholder="请选择科室"
|
clearable
|
style="width: 200px"
|
>
|
<el-option
|
v-for="dept in deptList"
|
:key="dept.id"
|
:label="dept.name"
|
:value="dept.id"
|
/>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="处理状态">
|
<el-select
|
v-model="filterParams.status"
|
placeholder="请选择状态"
|
clearable
|
style="width: 200px"
|
>
|
<el-option label="待处理" :value="0" />
|
<el-option label="处理中" :value="1" />
|
<el-option label="已处理" :value="2" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button
|
type="primary"
|
icon="el-icon-search"
|
@click="handleFilter"
|
>
|
筛选
|
</el-button>
|
<el-button
|
icon="el-icon-refresh"
|
@click="handleResetFilter"
|
>
|
重置
|
</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
|
<el-table
|
v-loading="loading"
|
:data="exceptionList"
|
:border="true"
|
style="width: 100%"
|
@selection-change="handleSelectionChange"
|
class="exception-table"
|
>
|
<el-table-column
|
type="selection"
|
width="55"
|
align="center"
|
/>
|
|
<el-table-column
|
label="序号"
|
type="index"
|
width="60"
|
align="center"
|
/>
|
|
<el-table-column
|
label="负责科室"
|
prop="responsibilityDept"
|
width="120"
|
align="center"
|
>
|
<template slot-scope="{ row }">
|
<el-tag type="primary">{{ row.responsibilityDept }}</el-tag>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="不满意详情"
|
prop="unsatisfactoryDetail"
|
min-width="200"
|
align="center"
|
>
|
<template slot-scope="{ row }">
|
<div class="detail-content">
|
{{ row.unsatisfactoryDetail }}
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="患者信息"
|
width="300"
|
align="center"
|
>
|
<template slot-scope="{ row }">
|
<div class="patient-info">
|
<div class="patient-item">
|
<span class="label">姓名:</span>
|
<span class="value">{{ row.patientName }}</span>
|
</div>
|
<div class="patient-item">
|
<span class="label">性别:</span>
|
<span class="value">{{ row.gender === 1 ? '男' : '女' }}</span>
|
</div>
|
<div class="patient-item">
|
<span class="label">年龄:</span>
|
<span class="value">{{ row.age }}岁</span>
|
</div>
|
<div class="patient-item">
|
<span class="label">电话:</span>
|
<span class="value">{{ row.phone }}</span>
|
</div>
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="出院信息"
|
width="250"
|
align="center"
|
>
|
<template slot-scope="{ row }">
|
<div class="discharge-info">
|
<div class="info-item">
|
<span class="label">科室:</span>
|
<span class="value">{{ row.dischargeDept }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">病区:</span>
|
<span class="value">{{ row.dischargeWard }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">填写时间:</span>
|
<span class="value time">{{ row.fillTime }}</span>
|
</div>
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="处理状态"
|
prop="processStatus"
|
width="100"
|
align="center"
|
>
|
<template slot-scope="{ row }">
|
<el-tag
|
:type="getStatusTagType(row.processStatus)"
|
effect="dark"
|
>
|
{{ getStatusText(row.processStatus) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="操作"
|
width="180"
|
align="center"
|
fixed="right"
|
>
|
<template slot-scope="{ row }">
|
<el-button
|
type="primary"
|
size="small"
|
icon="el-icon-view"
|
@click="handleViewDetail(row)"
|
>
|
查看详情
|
</el-button>
|
<el-button
|
type="warning"
|
size="small"
|
icon="el-icon-edit"
|
@click="handleProcess(row)"
|
:disabled="row.processStatus === 2"
|
>
|
处理
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 分页 -->
|
<div class="pagination-section">
|
<el-pagination
|
background
|
layout="total, sizes, prev, pager, next, jumper"
|
:current-page="filterParams.pageNum"
|
:page-size="filterParams.pageSize"
|
:page-sizes="[10, 20, 30, 50]"
|
:total="total"
|
@size-change="handleSizeChange"
|
@current-change="handlePageChange"
|
/>
|
</div>
|
</el-card>
|
</div>
|
|
<!-- 处理对话框 -->
|
<el-dialog
|
title="处理异常反馈"
|
:visible.sync="processDialogVisible"
|
width="600px"
|
center
|
>
|
<el-form
|
:model="processForm"
|
:rules="processRules"
|
ref="processForm"
|
label-width="100px"
|
size="medium"
|
>
|
<el-form-item label="处理状态" prop="status">
|
<el-select
|
v-model="processForm.status"
|
placeholder="请选择处理状态"
|
style="width: 100%"
|
>
|
<el-option label="处理中" :value="1" />
|
<el-option label="已处理" :value="2" />
|
<el-option label="已驳回" :value="3" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="报备科室" prop="reportDepts">
|
<el-select
|
v-model="processForm.reportDepts"
|
placeholder="请选择报备科室"
|
multiple
|
filterable
|
collapse-tags
|
style="width: 100%"
|
>
|
<el-option
|
v-for="dept in deptList"
|
:key="dept.id"
|
:label="dept.name"
|
:value="dept.id"
|
/>
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="处理备注" prop="remark">
|
<el-input
|
v-model="processForm.remark"
|
type="textarea"
|
:rows="4"
|
placeholder="请输入处理备注(最多500字)"
|
maxlength="500"
|
show-word-limit
|
/>
|
</el-form-item>
|
|
<el-form-item label="附件上传">
|
<el-upload
|
class="upload-demo"
|
action="#"
|
:on-preview="handlePreview"
|
:on-remove="handleRemove"
|
:before-remove="beforeRemove"
|
:limit="3"
|
:on-exceed="handleExceed"
|
:file-list="fileList"
|
>
|
<el-button size="small" type="primary">点击上传</el-button>
|
<div slot="tip" class="el-upload__tip">支持上传图片、文档等附件,单个文件不超过10MB</div>
|
</el-upload>
|
</el-form-item>
|
</el-form>
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="processDialogVisible = false">取消</el-button>
|
<el-button
|
type="primary"
|
@click="submitProcess"
|
:loading="processing"
|
>
|
提交处理
|
</el-button>
|
</span>
|
</el-dialog>
|
|
<!-- 批量处理对话框 -->
|
<el-dialog
|
title="批量处理异常反馈"
|
:visible.sync="batchDialogVisible"
|
width="600px"
|
center
|
>
|
<el-form
|
:model="batchProcessForm"
|
:rules="processRules"
|
ref="batchProcessForm"
|
label-width="100px"
|
size="medium"
|
>
|
<el-form-item label="处理状态" prop="status">
|
<el-select
|
v-model="batchProcessForm.status"
|
placeholder="请选择处理状态"
|
style="width: 100%"
|
>
|
<el-option label="处理中" :value="1" />
|
<el-option label="已处理" :value="2" />
|
<el-option label="已驳回" :value="3" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="报备科室" prop="reportDepts">
|
<el-select
|
v-model="batchProcessForm.reportDepts"
|
placeholder="请选择报备科室"
|
multiple
|
filterable
|
collapse-tags
|
style="width: 100%"
|
>
|
<el-option
|
v-for="dept in deptList"
|
:key="dept.id"
|
:label="dept.name"
|
:value="dept.id"
|
/>
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="处理备注" prop="remark">
|
<el-input
|
v-model="batchProcessForm.remark"
|
type="textarea"
|
:rows="4"
|
placeholder="请输入处理备注(最多500字)"
|
maxlength="500"
|
show-word-limit
|
/>
|
</el-form-item>
|
</el-form>
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="batchDialogVisible = false">取消</el-button>
|
<el-button
|
type="primary"
|
@click="submitBatchProcess"
|
:loading="batchProcessing"
|
>
|
批量提交
|
</el-button>
|
</span>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: 'BatchProcess',
|
data() {
|
return {
|
// 当前处理的异常ID
|
currentExceptionId: null,
|
|
// 批量选中的异常ID
|
selectedExceptionIds: [],
|
|
// 过滤参数
|
filterParams: {
|
deptId: '',
|
status: '',
|
pageNum: 1,
|
pageSize: 10
|
},
|
|
// 加载状态
|
loading: false,
|
processing: false,
|
batchProcessing: false,
|
|
// 科室列表
|
deptList: [
|
{ id: 1, name: '心血管内科' },
|
{ id: 2, name: '神经内科' },
|
{ id: 3, name: '普外科' },
|
{ id: 4, name: '骨科' },
|
{ id: 5, name: '妇产科' },
|
{ id: 6, name: '儿科' },
|
{ id: 7, name: '急诊科' },
|
{ id: 8, name: '呼吸内科' },
|
{ id: 9, name: '消化内科' },
|
{ id: 10, name: '内分泌科' }
|
],
|
|
// 异常列表数据
|
exceptionList: [],
|
total: 0,
|
|
// 处理对话框
|
processDialogVisible: false,
|
processForm: {
|
status: '',
|
reportDepts: [],
|
remark: ''
|
},
|
processRules: {
|
status: [
|
{ required: true, message: '请选择处理状态', trigger: 'change' }
|
],
|
remark: [
|
{ required: true, message: '请输入处理备注', trigger: 'blur' },
|
{ min: 5, max: 500, message: '备注长度在 5 到 500 个字符', trigger: 'blur' }
|
]
|
},
|
fileList: [],
|
|
// 批量处理对话框
|
batchDialogVisible: false,
|
batchProcessForm: {
|
status: '',
|
reportDepts: [],
|
remark: ''
|
}
|
};
|
},
|
|
mounted() {
|
this.loadExceptionList();
|
},
|
|
methods: {
|
// 加载异常列表
|
async loadExceptionList() {
|
this.loading = true;
|
try {
|
// Mock 数据
|
await new Promise(resolve => {
|
setTimeout(() => {
|
this.exceptionList = [
|
{
|
id: 1,
|
responsibilityDept: '心血管内科',
|
unsatisfactoryDetail: '医生查房时间太短,沟通不够充分,对病情解释不够详细',
|
patientName: '张先生',
|
gender: 1,
|
age: 45,
|
phone: '138****1234',
|
dischargeDept: '心血管内科',
|
dischargeWard: '内科一病区',
|
fillTime: '2024-01-15 10:30:25',
|
processStatus: 0,
|
questionnaireId: 1001
|
},
|
{
|
id: 2,
|
responsibilityDept: '神经内科',
|
unsatisfactoryDetail: '护士打针技术不佳,扎了三次才成功,且态度不够耐心',
|
patientName: '李女士',
|
gender: 0,
|
age: 38,
|
phone: '139****5678',
|
dischargeDept: '神经内科',
|
dischargeWard: '内科二病区',
|
fillTime: '2024-01-14 16:20:10',
|
processStatus: 0,
|
questionnaireId: 1002
|
},
|
{
|
id: 3,
|
responsibilityDept: '普外科',
|
unsatisfactoryDetail: '术后换药不及时,伤口疼痛时没有及时处理',
|
patientName: '王先生',
|
gender: 1,
|
age: 52,
|
phone: '137****9012',
|
dischargeDept: '普外科',
|
dischargeWard: '外科一病区',
|
fillTime: '2024-01-13 09:15:45',
|
processStatus: 1,
|
questionnaireId: 1003
|
},
|
{
|
id: 4,
|
responsibilityDept: '骨科',
|
unsatisfactoryDetail: '康复指导不够专业,对恢复过程描述不清楚',
|
patientName: '刘女士',
|
gender: 0,
|
age: 65,
|
phone: '136****3456',
|
dischargeDept: '骨科',
|
dischargeWard: '外科二病区',
|
fillTime: '2024-01-12 14:40:30',
|
processStatus: 0,
|
questionnaireId: 1004
|
},
|
{
|
id: 5,
|
responsibilityDept: '妇产科',
|
unsatisfactoryDetail: '产前检查排队时间过长,等待期间没有休息座位',
|
patientName: '陈女士',
|
gender: 0,
|
age: 28,
|
phone: '135****7890',
|
dischargeDept: '妇产科',
|
dischargeWard: '妇产科病区',
|
fillTime: '2024-01-11 11:25:15',
|
processStatus: 2,
|
questionnaireId: 1005
|
},
|
{
|
id: 6,
|
responsibilityDept: '儿科',
|
unsatisfactoryDetail: '儿童用药剂量交代不清晰,用药注意事项没有说明',
|
patientName: '赵宝宝',
|
gender: 1,
|
age: 5,
|
phone: '134****1234',
|
dischargeDept: '儿科',
|
dischargeWard: '儿科病区',
|
fillTime: '2024-01-10 15:50:20',
|
processStatus: 0,
|
questionnaireId: 1006
|
},
|
{
|
id: 7,
|
responsibilityDept: '急诊科',
|
unsatisfactoryDetail: '急诊等待时间过长,病情没有得到及时评估',
|
patientName: '孙先生',
|
gender: 1,
|
age: 40,
|
phone: '133****5678',
|
dischargeDept: '急诊科',
|
dischargeWard: '急诊病区',
|
fillTime: '2024-01-09 10:15:40',
|
processStatus: 0,
|
questionnaireId: 1007
|
},
|
{
|
id: 8,
|
responsibilityDept: '呼吸内科',
|
unsatisfactoryDetail: '医生开药较多,费用较高,没有说明必要性',
|
patientName: '周女士',
|
gender: 0,
|
age: 55,
|
phone: '132****9012',
|
dischargeDept: '呼吸内科',
|
dischargeWard: '内科一病区',
|
fillTime: '2024-01-08 13:30:55',
|
processStatus: 1,
|
questionnaireId: 1008
|
}
|
];
|
this.total = this.exceptionList.length;
|
resolve();
|
}, 500);
|
});
|
} finally {
|
this.loading = false;
|
}
|
},
|
|
// 获取状态标签类型
|
getStatusTagType(status) {
|
switch (status) {
|
case 0: return 'warning'; // 待处理
|
case 1: return 'primary'; // 处理中
|
case 2: return 'success'; // 已处理
|
default: return 'info';
|
}
|
},
|
|
// 获取状态文本
|
getStatusText(status) {
|
switch (status) {
|
case 0: return '待处理';
|
case 1: return '处理中';
|
case 2: return '已处理';
|
default: return '未知';
|
}
|
},
|
|
// 处理筛选
|
handleFilter() {
|
this.filterParams.pageNum = 1;
|
this.loadExceptionList();
|
},
|
|
// 重置筛选
|
handleResetFilter() {
|
this.filterParams = {
|
deptId: '',
|
status: '',
|
pageNum: 1,
|
pageSize: 10
|
};
|
this.loadExceptionList();
|
},
|
|
// 处理选择变化
|
handleSelectionChange(selection) {
|
this.selectedExceptionIds = selection.map(item => item.id);
|
},
|
|
// 处理批量提交
|
handleBatchSubmit() {
|
if (this.selectedExceptionIds.length === 0) {
|
this.$message.warning('请先选择要处理的异常反馈');
|
return;
|
}
|
this.batchDialogVisible = true;
|
},
|
|
// 返回异常列表
|
handleGoBack() {
|
this.$router.push('/satisfaction/exception/list');
|
},
|
|
// 查看详情
|
handleViewDetail(row) {
|
this.$router.push({
|
path: '/satisfaction/exception/detail',
|
query: {
|
id: row.questionnaireId
|
}
|
});
|
},
|
|
// 处理单个异常
|
handleProcess(row) {
|
this.currentExceptionId = row.id;
|
this.processForm = {
|
status: row.processStatus === 0 ? 1 : row.processStatus,
|
reportDepts: [],
|
remark: ''
|
};
|
this.processDialogVisible = true;
|
},
|
|
// 提交处理
|
async submitProcess() {
|
this.$refs.processForm.validate(async (valid) => {
|
if (valid) {
|
this.processing = true;
|
try {
|
// Mock API调用
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
this.$message.success('处理提交成功');
|
this.processDialogVisible = false;
|
this.loadExceptionList();
|
} finally {
|
this.processing = false;
|
}
|
}
|
});
|
},
|
|
// 提交批量处理
|
async submitBatchProcess() {
|
this.$refs.batchProcessForm.validate(async (valid) => {
|
if (valid) {
|
this.batchProcessing = true;
|
try {
|
// Mock API调用
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
this.$message.success(`已批量处理 ${this.selectedExceptionIds.length} 条异常反馈`);
|
this.batchDialogVisible = false;
|
this.selectedExceptionIds = [];
|
this.loadExceptionList();
|
} finally {
|
this.batchProcessing = false;
|
}
|
}
|
});
|
},
|
|
// 分页大小变化
|
handleSizeChange(size) {
|
this.filterParams.pageSize = size;
|
this.filterParams.pageNum = 1;
|
this.loadExceptionList();
|
},
|
|
// 页码变化
|
handlePageChange(page) {
|
this.filterParams.pageNum = page;
|
this.loadExceptionList();
|
},
|
|
// 文件上传相关方法
|
handlePreview(file) {
|
console.log('预览文件:', file);
|
},
|
|
handleRemove(file, fileList) {
|
console.log('移除文件:', file, fileList);
|
},
|
|
beforeRemove(file) {
|
return this.$confirm(`确定移除 ${file.name}?`);
|
},
|
|
handleExceed(files, fileList) {
|
this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.batch-process {
|
padding: 20px;
|
background-color: #f5f7fa;
|
min-height: 100vh;
|
|
.page-header {
|
margin-bottom: 20px;
|
padding: 20px;
|
background: linear-gradient(135deg, #5788FE 0%, #66b1ff 100%);
|
border-radius: 8px;
|
color: white;
|
|
.header-content {
|
.page-title {
|
margin: 0 0 8px 0;
|
font-size: 20px;
|
font-weight: 600;
|
}
|
|
.page-description {
|
margin: 0 0 20px 0;
|
opacity: 0.9;
|
font-size: 14px;
|
}
|
|
.header-actions {
|
display: flex;
|
gap: 10px;
|
}
|
}
|
}
|
|
.list-section {
|
.filter-section {
|
margin-bottom: 20px;
|
|
.filter-form {
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
|
::v-deep .el-form-item {
|
margin-bottom: 0;
|
margin-right: 20px;
|
|
&:last-child {
|
margin-right: 0;
|
}
|
}
|
}
|
}
|
|
.exception-table {
|
::v-deep .el-table__header-wrapper {
|
th {
|
background-color: #f8f9fa;
|
font-weight: 600;
|
color: #333;
|
}
|
}
|
|
.detail-content {
|
font-size: 13px;
|
color: #606266;
|
line-height: 1.5;
|
text-align: left;
|
}
|
|
.patient-info {
|
.patient-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 5px;
|
padding: 2px 0;
|
|
.label {
|
font-size: 12px;
|
color: #606266;
|
min-width: 40px;
|
}
|
|
.value {
|
font-size: 13px;
|
color: #333;
|
font-weight: 500;
|
text-align: right;
|
flex: 1;
|
}
|
}
|
}
|
|
.discharge-info {
|
.info-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 5px;
|
padding: 2px 0;
|
|
.label {
|
font-size: 12px;
|
color: #606266;
|
min-width: 50px;
|
}
|
|
.value {
|
font-size: 13px;
|
color: #333;
|
font-weight: 500;
|
text-align: right;
|
flex: 1;
|
|
&.time {
|
font-size: 12px;
|
color: #909399;
|
}
|
}
|
}
|
}
|
}
|
|
.pagination-section {
|
display: flex;
|
justify-content: center;
|
padding: 20px 0 0 0;
|
}
|
}
|
}
|
|
@media (max-width: 768px) {
|
.batch-process {
|
padding: 10px;
|
|
.page-header {
|
.header-actions {
|
flex-direction: column;
|
align-items: stretch;
|
}
|
}
|
|
.list-section {
|
.filter-section {
|
.filter-form {
|
::v-deep .el-form-item {
|
width: 100%;
|
margin-right: 0;
|
margin-bottom: 10px;
|
}
|
}
|
}
|
}
|
}
|
}
|
</style>
|