ykt-wxapp/pages/message/components/medical-case-progress.vue

198 lines
4.3 KiB
Vue
Raw Normal View History

2026-01-29 18:03:40 +08:00
<template>
<uni-popup ref="popup" type="center" :mask-click="false">
<view class="progress-modal">
<view class="close-btn" @click="close">
<text class="close-icon"></text>
</view>
<view class="progress-content">
<view class="progress-title">{{ progressTitle }}</view>
<view class="progress-bar-wrapper">
<view class="progress-bar">
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
</view>
<text class="progress-text">{{ progress }}%</text>
</view>
<view v-if="detectedInfo.length > 0" class="detected-info">
<text class="detected-title">检测到以下{{ caseTypeName }}信息</text>
<view class="info-list">
<view v-for="(item, index) in detectedInfo" :key="index" class="info-item">
<text class="check-icon"></text>
<text class="info-text">{{ item }}</text>
</view>
</view>
</view>
<view v-if="isGenerating" class="generating-text">
正在生成结构化{{ caseTypeName }}...
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref, computed } from 'vue';
const popup = ref(null);
const progress = ref(0);
const detectedInfo = ref([]);
const isGenerating = ref(false);
const caseType = ref('');
const CASE_TYPE_NAMES = {
outpatient: '门诊病历',
inpatient: '住院病历',
physicalExam: '体检记录',
preConsultation: '预问诊记录'
};
const caseTypeName = computed(() => CASE_TYPE_NAMES[caseType.value] || '病历');
const progressTitle = computed(() => {
if (progress.value < 100) {
return `正在智能整理${caseTypeName.value}...`;
}
return `${caseTypeName.value}生成完成`;
});
const open = (type) => {
caseType.value = type;
progress.value = 0;
detectedInfo.value = [];
isGenerating.value = false;
popup.value?.open();
};
const close = () => {
popup.value?.close();
};
const updateProgress = (value) => {
progress.value = value;
};
const addDetectedInfo = (info) => {
detectedInfo.value.push(info);
};
const setGenerating = (value) => {
isGenerating.value = value;
};
defineExpose({
open,
close,
updateProgress,
addDetectedInfo,
setGenerating
});
</script>
<style scoped lang="scss">
.progress-modal {
width: 600rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 48rpx 40rpx;
position: relative;
.close-btn {
position: absolute;
top: 20rpx;
right: 20rpx;
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
.close-icon {
font-size: 40rpx;
color: #999999;
}
}
.progress-content {
.progress-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 32rpx;
text-align: center;
}
.progress-bar-wrapper {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 32rpx;
.progress-bar {
flex: 1;
height: 16rpx;
background-color: #e5e5e5;
border-radius: 8rpx;
overflow: hidden;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #1890ff 0%, #40a9ff 100%);
transition: width 0.3s ease;
}
}
.progress-text {
font-size: 28rpx;
color: #1890ff;
font-weight: 600;
min-width: 80rpx;
text-align: right;
}
}
.detected-info {
margin-bottom: 24rpx;
.detected-title {
font-size: 28rpx;
color: #666666;
display: block;
margin-bottom: 16rpx;
}
.info-list {
.info-item {
display: flex;
align-items: flex-start;
gap: 12rpx;
margin-bottom: 12rpx;
.check-icon {
font-size: 28rpx;
color: #52c41a;
font-weight: bold;
}
.info-text {
flex: 1;
font-size: 26rpx;
color: #333333;
line-height: 1.5;
}
}
}
}
.generating-text {
font-size: 28rpx;
color: #1890ff;
text-align: center;
padding: 16rpx 0;
}
}
}
</style>