进度条
This commit is contained in:
parent
d52158bb11
commit
d6b6c40d74
@ -26,7 +26,7 @@
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || progressVisible"
|
||||
@click="handleBatchReview"
|
||||
>
|
||||
<Icon icon="ep:check" class="mr-5px" /> 批量审核
|
||||
@ -61,6 +61,34 @@
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 批量处理进度对话框 -->
|
||||
<el-dialog
|
||||
v-model="progressVisible"
|
||||
title="批量审核进度"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
>
|
||||
<div class="progress-container">
|
||||
<div class="progress-info">
|
||||
<div class="progress-stats">
|
||||
<span>进度:{{ processedCount }} / {{ totalCount }}</span>
|
||||
<span class="estimated-time">预计剩余:{{ formatTime(estimatedTimeRemaining) }}</span>
|
||||
</div>
|
||||
<el-progress
|
||||
:percentage="progressPercentage"
|
||||
:stroke-width="8"
|
||||
:format="progressFormat"
|
||||
class="progress-bar"
|
||||
/>
|
||||
<div class="current-processing">
|
||||
<span v-if="currentProcessing">当前处理:{{ currentProcessing }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -71,7 +99,6 @@ import Pagination from '@/components/Pagination/index.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { InspectOrgApi } from '@/api/inspect/inspectorg/index'
|
||||
import { getUserProfile } from '@/api/system/user/profile'
|
||||
import { ElLoading } from 'element-plus'
|
||||
import { PacsDataApi } from '@/api/inspect/inspectpacsdata'
|
||||
import { PatientitemsApi } from '@/api/inspect/inspectpatientitems'
|
||||
import { DoctorApi } from '@/api/inspect/inspectdoctor'
|
||||
@ -89,6 +116,49 @@ const queryParams = reactive({
|
||||
})
|
||||
const selectedRows = ref<PatientVO[]>([])
|
||||
|
||||
// 进度相关状态
|
||||
const progressVisible = ref(false)
|
||||
const progressPercentage = ref(0)
|
||||
const currentProcessing = ref('')
|
||||
const processedCount = ref(0)
|
||||
const totalCount = ref(0)
|
||||
const estimatedTimeRemaining = ref(0)
|
||||
const startTime = ref(0)
|
||||
|
||||
// 进度相关函数
|
||||
const updateProgress = (current: number, total: number, currentItem: string) => {
|
||||
processedCount.value = current
|
||||
totalCount.value = total
|
||||
progressPercentage.value = Math.round((current / total) * 100)
|
||||
currentProcessing.value = currentItem
|
||||
|
||||
// 计算预计剩余时间
|
||||
if (current > 0) {
|
||||
const elapsed = Date.now() - startTime.value
|
||||
const avgTimePerItem = elapsed / current
|
||||
const remaining = total - current
|
||||
estimatedTimeRemaining.value = Math.round((remaining * avgTimePerItem) / 1000) // 转换为秒
|
||||
}
|
||||
}
|
||||
|
||||
const progressFormat = (percentage: number) => {
|
||||
return `${percentage}%`
|
||||
}
|
||||
|
||||
const formatTime = (seconds: number) => {
|
||||
if (seconds < 60) {
|
||||
return `${seconds}秒`
|
||||
} else if (seconds < 3600) {
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const remainingSeconds = seconds % 60
|
||||
return `${minutes}分${remainingSeconds}秒`
|
||||
} else {
|
||||
const hours = Math.floor(seconds / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
return `${hours}小时${minutes}分钟`
|
||||
}
|
||||
}
|
||||
|
||||
const handleDateChange = (val: [string, string] | null) => {
|
||||
if (val) {
|
||||
// 设置开始时间为当天的 00:00:00
|
||||
@ -144,11 +214,17 @@ const handleBatchReview = async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '批量同步中...',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
})
|
||||
// 初始化进度相关变量
|
||||
progressVisible.value = true
|
||||
progressPercentage.value = 0
|
||||
currentProcessing.value = '准备开始处理...'
|
||||
processedCount.value = 0
|
||||
totalCount.value = selectedRows.value.length
|
||||
estimatedTimeRemaining.value = 0
|
||||
startTime.value = Date.now()
|
||||
|
||||
// 初始显示进度
|
||||
updateProgress(0, selectedRows.value.length, '准备开始处理...')
|
||||
|
||||
let successCount = 0
|
||||
let failCount = 0
|
||||
@ -157,16 +233,20 @@ const handleBatchReview = async () => {
|
||||
const userProfile = await getUserProfile()
|
||||
if (!userProfile || !userProfile.nickname) {
|
||||
ElMessage.error('获取用户信息失败,请重新登录')
|
||||
loading.close()
|
||||
progressVisible.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const currentTimestamp = Date.now()
|
||||
|
||||
// 逐条处理选中的体检编号
|
||||
for (const row of selectedRows.value) {
|
||||
for (let index = 0; index < selectedRows.value.length; index++) {
|
||||
const row = selectedRows.value[index]
|
||||
const medicalSn = row.medicalSn
|
||||
const cardId = row.cardId
|
||||
|
||||
// 更新进度
|
||||
updateProgress(index, selectedRows.value.length, `${row.pname} (${medicalSn})`)
|
||||
console.log('正在处理体检编号:', medicalSn)
|
||||
|
||||
try {
|
||||
@ -515,8 +595,6 @@ const handleBatchReview = async () => {
|
||||
const pacsRes = await PacsDataApi.getPacsDataDetail(medicalSn)
|
||||
const pacsDuration = Date.now() - pacsStartTime
|
||||
console.log(`${medicalSn} 获取PACS数据完成,耗时: ${pacsDuration}ms`)
|
||||
console.log('PACS数据明细:', pacsRes);
|
||||
console.log('typeGroups:', pacsRes);
|
||||
if (pacsRes && pacsRes.length > 0) {
|
||||
const typeGroups: Record<string, any[]> = {}
|
||||
pacsRes.forEach((item) => {
|
||||
@ -526,14 +604,7 @@ const handleBatchReview = async () => {
|
||||
}
|
||||
typeGroups[type].push(item)
|
||||
})
|
||||
|
||||
console.log('typeGroups:', typeGroups);
|
||||
if (typeGroups['us']) {
|
||||
typeGroups['us'].forEach(item => {
|
||||
console.log('us item:', item.data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 类型映射关系
|
||||
const typeToTabMapping = {
|
||||
cbc: 'blood',
|
||||
@ -792,9 +863,19 @@ const handleBatchReview = async () => {
|
||||
console.error(`处理体检编号 ${medicalSn} 失败:`, error)
|
||||
failCount++
|
||||
}
|
||||
|
||||
// 处理完成后更新进度
|
||||
updateProgress(index + 1, selectedRows.value.length,
|
||||
index + 1 === selectedRows.value.length ? '全部处理完成' : `已完成 ${index + 1} 项`)
|
||||
}
|
||||
|
||||
loading.close()
|
||||
// 最终更新进度为100%
|
||||
updateProgress(selectedRows.value.length, selectedRows.value.length, '处理完成')
|
||||
|
||||
// 延迟关闭进度对话框,让用户看到完成状态
|
||||
setTimeout(() => {
|
||||
progressVisible.value = false
|
||||
}, 1500)
|
||||
|
||||
if (failCount === 0) {
|
||||
ElMessage.success(`批量同步完成,共处理 ${successCount} 项`)
|
||||
@ -809,6 +890,7 @@ const handleBatchReview = async () => {
|
||||
} catch (error) {
|
||||
console.error('批量同步失败:', error)
|
||||
ElMessage.error('批量同步失败,请重试')
|
||||
progressVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -870,4 +952,47 @@ const handleSelectionChange = (rows: PatientVO[]) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.progress-container {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.progress-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.progress-stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.estimated-time {
|
||||
color: #409eff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.current-processing {
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
min-height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.current-processing span {
|
||||
background: #f5f7fa;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
</style>
|
||||
|
@ -73,58 +73,60 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-content">
|
||||
<div v-if="loading" class="loading-container">
|
||||
<el-skeleton :rows="5" animated />
|
||||
</div>
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="patient in filteredPatients"
|
||||
:key="patient.id"
|
||||
class="patient-item"
|
||||
@click="handlePatientSelect(patient)"
|
||||
:class="{ active: selectedPatient?.id === patient.id }"
|
||||
>
|
||||
<div class="patient-info">
|
||||
<div class="info-row">
|
||||
<span class="name">{{ patient.pname }}</span>
|
||||
<span class="medical-sn">{{ truncateMedicalSn(patient.medicalSn) }}</span>
|
||||
<el-tag
|
||||
size="small"
|
||||
:type="getStatusInfo(patient).color"
|
||||
class="status-tag"
|
||||
>
|
||||
{{ getStatusInfo(patient).text }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
v-if="getStatusInfo(patient).showButton"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click.stop="resetPatientStatus(patient)"
|
||||
class="reset-status-btn"
|
||||
>
|
||||
撤回
|
||||
</el-button>
|
||||
<div class="patient-items-wrapper">
|
||||
<div v-if="loading" class="loading-container">
|
||||
<el-skeleton :rows="5" animated />
|
||||
</div>
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="patient in filteredPatients"
|
||||
:key="patient.id"
|
||||
class="patient-item"
|
||||
@click="handlePatientSelect(patient)"
|
||||
:class="{ active: selectedPatient?.id === patient.id }"
|
||||
>
|
||||
<div class="patient-info">
|
||||
<div class="info-row">
|
||||
<span class="name">{{ patient.pname }}</span>
|
||||
<span class="medical-sn">{{ truncateMedicalSn(patient.medicalSn) }}</span>
|
||||
<el-tag
|
||||
size="small"
|
||||
:type="getStatusInfo(patient).color"
|
||||
class="status-tag"
|
||||
>
|
||||
{{ getStatusInfo(patient).text }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
v-if="getStatusInfo(patient).showButton"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click.stop="resetPatientStatus(patient)"
|
||||
class="reset-status-btn"
|
||||
>
|
||||
撤回
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 将分页组件移到list-content外部底部 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="pageNo"
|
||||
:page-size="pageSize"
|
||||
small
|
||||
:total="total"
|
||||
:pager-count="3"
|
||||
layout="total, prev, pager, next"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #total>
|
||||
<span>共 {{ total }} 条</span>
|
||||
</template>
|
||||
</el-pagination>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 将分页组件移到list-content外部,固定在底部 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="pageNo"
|
||||
:page-size="pageSize"
|
||||
small
|
||||
:total="total"
|
||||
:pager-count="3"
|
||||
layout="total, prev, pager, next"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #total>
|
||||
<span>共 {{ total }} 条</span>
|
||||
</template>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧内容区域 -->
|
||||
<div class="right-content">
|
||||
@ -2997,8 +2999,8 @@ const examhosInfo = ref({
|
||||
<style scoped>
|
||||
.medical-report {
|
||||
display: flex;
|
||||
height: calc(100vh - 120px); /* 使用视口高度减去头部和其他元素的高度 */
|
||||
min-height: 600px;
|
||||
height: calc(100vh - 160px); /* 使用视口高度减去头部和其他元素的高度 */
|
||||
min-height: 580px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
@ -3381,17 +3383,20 @@ const examhosInfo = ref({
|
||||
}
|
||||
|
||||
/* 美化滚动条 */
|
||||
.table-body::-webkit-scrollbar {
|
||||
.table-body::-webkit-scrollbar,
|
||||
.patient-items-wrapper::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.table-body::-webkit-scrollbar-thumb {
|
||||
.table-body::-webkit-scrollbar-thumb,
|
||||
.patient-items-wrapper::-webkit-scrollbar-thumb {
|
||||
background: #c0c4cc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.table-body::-webkit-scrollbar-track {
|
||||
.table-body::-webkit-scrollbar-track,
|
||||
.patient-items-wrapper::-webkit-scrollbar-track {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
@ -3553,12 +3558,18 @@ const examhosInfo = ref({
|
||||
|
||||
.list-content {
|
||||
flex: 1; /* 让列表内容区域占据剩余空间 */
|
||||
overflow-y: auto;
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.patient-items-wrapper {
|
||||
flex: 1;
|
||||
overflow-y: auto; /* 只有患者列表可以滚动 */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 添加空状态样式 */
|
||||
.empty-content {
|
||||
flex: 1;
|
||||
@ -3604,6 +3615,9 @@ const examhosInfo = ref({
|
||||
.pagination-container {
|
||||
padding: 10px 15px;
|
||||
text-align: right;
|
||||
border-top: 1px solid #e6e6e6; /* 添加顶部边框 */
|
||||
background: #fff; /* 确保背景是白色 */
|
||||
flex-shrink: 0; /* 防止被压缩 */
|
||||
}
|
||||
|
||||
/* 自定义分页组件样式 */
|
||||
|
Loading…
Reference in New Issue
Block a user