Files
vueapp/pages/assessment/assessment.vue
T
2026-05-29 17:40:10 +08:00

564 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="assessment-page">
<view class="top-nav">
<button class="icon-button" aria-label="设置" @click="emit('open-settings')">
<view class="settings-icon"></view>
</button>
<button class="icon-button home-button" aria-label="首页" @click="emit('go-home')">
<view class="home-icon"></view>
</button>
<view class="nav-spacer"></view>
<button class="icon-button" aria-label="个人中心" @click="emit('open-profile')">
<view class="account-icon"></view>
</button>
</view>
<scroll-view class="assessment-content" scroll-y>
<view class="score-section">
<view class="score-gauge">
<view class="gauge-bg"></view>
<view class="gauge-fill"></view>
<view class="score-center">
<text class="score-value">88</text>
<text class="score-label">总分/100</text>
</view>
</view>
<view class="score-copy">
<text class="score-title">本次考核评价优良</text>
<text class="score-subtitle">临床思维严谨诊疗流程规范</text>
</view>
</view>
<view class="dimension-card">
<view class="section-title">
<view class="insights-icon"></view>
<text>临床能力维度评估</text>
</view>
<view class="radar-wrap">
<svg class="radar-svg" viewBox="0 0 200 200">
<polygon fill="none" points="100,20 176,76 147,166 53,166 24,76" stroke="#c2c6d4" stroke-width="0.5"></polygon>
<polygon fill="none" points="100,40 160,84 137,152 63,152 40,84" stroke="#c2c6d4" stroke-width="0.5"></polygon>
<polygon fill="none" points="100,60 144,92 127,138 73,138 56,92" stroke="#c2c6d4" stroke-width="0.5"></polygon>
<polygon fill="rgba(0, 71, 141, 0.2)" points="100,30 165,80 135,155 75,145 45,70" stroke="#00478d" stroke-width="2"></polygon>
<text class="radar-label" text-anchor="middle" x="100" y="15">病史采集</text>
<text class="radar-label" text-anchor="start" x="180" y="75">体格检查</text>
<text class="radar-label" text-anchor="start" x="150" y="180">临床思维</text>
<text class="radar-label" text-anchor="end" x="50" y="180">诊断准确性</text>
<text class="radar-label" text-anchor="end" x="20" y="75">治疗方案</text>
</svg>
</view>
<view class="mentor-review">
<view class="mentor-head">
<view class="mentor-avatar">
<image src="/static/config-doctor.png" mode="aspectFill"></image>
</view>
<view>
<text class="mentor-name">王主任点评</text>
<text class="mentor-role">资深临床导师</text>
</view>
</view>
<view class="mentor-bubble">
<view class="bubble-tail"></view>
<text>你在病史采集环节表现出色逻辑清晰但在鉴别诊断方面稍欠全面建议加强对心血管急症鉴别诊断的学习</text>
</view>
</view>
<view class="bar-list">
<view
v-for="item in dimensions"
:key="item.label"
class="bar-item"
>
<view class="bar-head">
<text>{{ item.label }}</text>
<text class="bar-score">{{ item.score }}/100</text>
</view>
<view class="bar-track">
<view class="bar-fill" :style="{ width: `${item.score}%` }"></view>
</view>
</view>
</view>
</view>
<view class="action-area">
<button class="primary-action" @click="showToast('病例详情暂未开放')">
<view class="description-icon"></view>
<text>查看病例详情</text>
</button>
<button class="secondary-action" @click="emit('go-home')">
<view class="map-icon"></view>
<text>返回路径</text>
</button>
</view>
</scroll-view>
<view class="toast" :class="{ visible: toastVisible }">{{ toastMessage }}</view>
</view>
</template>
<script setup lang="ts">
import { onUnmounted, ref } from 'vue'
const emit = defineEmits<{
(event: 'open-settings'): void
(event: 'open-profile'): void
(event: 'go-home'): void
}>()
const dimensions = [
{ label: '病史采集', score: 92 },
{ label: '体格检查', score: 85 },
{ label: '临床思维', score: 90 },
{ label: '诊断准确性', score: 88 },
{ label: '治疗方案', score: 82 }
]
const toastMessage = ref('')
const toastVisible = ref(false)
let toastTimer: ReturnType<typeof setTimeout> | null = null
function showToast(message: string) {
if (toastTimer) clearTimeout(toastTimer)
toastMessage.value = message
toastVisible.value = true
uni.showToast({
title: message,
icon: 'none'
})
toastTimer = setTimeout(() => {
toastVisible.value = false
}, 2200)
}
onUnmounted(() => {
if (toastTimer) clearTimeout(toastTimer)
})
</script>
<style scoped>
page {
min-height: 100%;
background: #f9f9ff;
}
.assessment-page {
width: 390px;
max-width: 100vw;
height: 884px;
min-height: 884px;
margin: 0 auto;
overflow: hidden;
background: #f9f9ff;
color: #191c21;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
-webkit-tap-highlight-color: transparent;
}
.assessment-page view,
.assessment-page text,
.assessment-page button,
.assessment-page scroll-view {
box-sizing: border-box;
}
.top-nav {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 50;
height: 56px;
padding: 0 20px;
border-bottom: 1px solid rgba(194, 198, 212, 0.3);
background: #ffffff;
box-shadow: 0 2px 8px rgba(25, 28, 33, 0.04);
display: flex;
align-items: center;
}
.nav-spacer {
flex: 1;
}
.icon-button {
width: 40px;
height: 40px;
min-height: 40px;
margin: 0;
padding: 0;
border: 0;
border-radius: 50%;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
}
.home-button {
margin-left: 4px;
}
.icon-button::after,
.primary-action::after,
.secondary-action::after {
border: 0;
}
.settings-icon,
.home-icon,
.account-icon,
.insights-icon,
.description-icon,
.map-icon {
background: #424752;
}
.settings-icon {
width: 22px;
height: 22px;
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M19.43%2012.98c.04-.32.07-.65.07-.98s-.02-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.37-.31-.6-.22l-2.49%201c-.52-.4-1.08-.73-1.69-.98L14.5%202.42C14.47%202.18%2014.25%202%2014%202h-4c-.25%200-.46.18-.5.42l-.38%202.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.08-.48%200-.6.22l-2%203.46c-.13.22-.07.49.12.64l2.11%201.65c-.04.32-.08.65-.08.98s.03.66.08.98l-2.11%201.65c-.19.15-.24.42-.12.64l2%203.46c.12.22.37.31.6.22l2.49-1c.52.4%201.08.73%201.69.98l.38%202.65c.04.24.25.42.5.42h4c.25%200%20.46-.18.5-.42l.38-2.65c.61-.25%201.17-.58%201.69-.98l2.49%201c.23.08.48%200%20.6-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12%2015.5A3.5%203.5%200%201%201%2012%208a3.5%203.5%200%200%201%200%207.5z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M19.43%2012.98c.04-.32.07-.65.07-.98s-.02-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.37-.31-.6-.22l-2.49%201c-.52-.4-1.08-.73-1.69-.98L14.5%202.42C14.47%202.18%2014.25%202%2014%202h-4c-.25%200-.46.18-.5.42l-.38%202.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.08-.48%200-.6.22l-2%203.46c-.13.22-.07.49.12.64l2.11%201.65c-.04.32-.08.65-.08.98s.03.66.08.98l-2.11%201.65c-.19.15-.24.42-.12.64l2%203.46c.12.22.37.31.6.22l2.49-1c.52.4%201.08.73%201.69.98l.38%202.65c.04.24.25.42.5.42h4c.25%200%20.46-.18.5-.42l.38-2.65c.61-.25%201.17-.58%201.69-.98l2.49%201c.23.08.48%200%20.6-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12%2015.5A3.5%203.5%200%201%201%2012%208a3.5%203.5%200%200%201%200%207.5z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.home-icon,
.account-icon {
width: 24px;
height: 24px;
}
.home-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M10%2020v-6h4v6h5v-8h3L12%203%202%2012h3v8h5z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M10%2020v-6h4v6h5v-8h3L12%203%202%2012h3v8h5z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.account-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202a10%2010%200%201%200%200%2020%2010%2010%200%200%200%200-20zm0%203a3.5%203.5%200%201%201%200%207%203.5%203.5%200%200%201%200-7zm0%2015a8%208%200%200%201-6.4-3.2c1.18-2.02%203.57-3.3%206.4-3.3s5.22%201.28%206.4%203.3A8%208%200%200%201%2012%2020z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202a10%2010%200%201%200%200%2020%2010%2010%200%200%200%200-20zm0%203a3.5%203.5%200%201%201%200%207%203.5%203.5%200%200%201%200-7zm0%2015a8%208%200%200%201-6.4-3.2c1.18-2.02%203.57-3.3%206.4-3.3s5.22%201.28%206.4%203.3A8%208%200%200%201%2012%2020z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.assessment-content {
height: 884px;
padding: 80px 20px 24px;
}
.score-section {
padding: 16px 0;
display: flex;
flex-direction: column;
align-items: center;
}
.score-gauge {
position: relative;
width: 128px;
height: 128px;
display: flex;
align-items: center;
justify-content: center;
}
.gauge-bg,
.gauge-fill {
position: absolute;
inset: 0;
border-radius: 50%;
}
.gauge-bg {
border: 8px solid #e1e2ea;
}
.gauge-fill {
background: conic-gradient(#00478d 0deg 317deg, transparent 317deg 360deg);
-webkit-mask: radial-gradient(circle, transparent 43px, #000 44px);
mask: radial-gradient(circle, transparent 43px, #000 44px);
transform: rotate(-90deg);
}
.score-center {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.score-value {
color: #00478d;
font-size: 32px;
line-height: 40px;
font-weight: 700;
}
.score-label {
color: #727783;
font-size: 12px;
line-height: 16px;
font-weight: 500;
}
.score-copy {
margin-top: 16px;
text-align: center;
display: flex;
flex-direction: column;
gap: 4px;
}
.score-title {
color: #191c21;
font-size: 24px;
line-height: 32px;
font-weight: 600;
}
.score-subtitle {
color: #424752;
font-size: 14px;
line-height: 20px;
}
.dimension-card {
padding: 16px;
border: 1px solid rgba(194, 198, 212, 0.3);
border-radius: 8px;
background: #ffffff;
box-shadow: 0 2px 8px rgba(25, 28, 33, 0.04);
}
.section-title {
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
color: #191c21;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.insights-icon {
width: 20px;
height: 20px;
background: #00478d;
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M3%2017h3v-7H3v7zm5%200h3V7H8v10zm5%200h3v-4h-3v4zm5%200h3V4h-3v13z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M3%2017h3v-7H3v7zm5%200h3V7H8v10zm5%200h3v-4h-3v4zm5%200h3V4h-3v13z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.radar-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
margin-bottom: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.radar-svg {
width: 100%;
height: 100%;
}
.radar-label {
fill: #424752;
font-size: 10px;
font-weight: 500;
}
.mentor-review {
margin-bottom: 24px;
padding: 16px;
border: 1px solid rgba(0, 71, 141, 0.1);
border-radius: 12px;
background: #f2f3fb;
}
.mentor-head {
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 12px;
}
.mentor-avatar {
width: 48px;
height: 48px;
border: 2px solid #ffffff;
border-radius: 50%;
overflow: hidden;
box-shadow: 0 2px 8px rgba(25, 28, 33, 0.08);
}
.mentor-avatar image {
width: 100%;
height: 100%;
}
.mentor-name {
display: block;
color: #00478d;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.mentor-role {
display: block;
color: #424752;
font-size: 10px;
line-height: 14px;
}
.mentor-bubble {
position: relative;
padding: 12px;
border: 1px solid rgba(194, 198, 212, 0.2);
border-radius: 8px;
border-top-left-radius: 0;
background: #ffffff;
box-shadow: 0 2px 8px rgba(25, 28, 33, 0.04);
color: #191c21;
font-size: 14px;
line-height: 20px;
}
.bubble-tail {
position: absolute;
left: -8px;
top: 0;
width: 0;
height: 0;
border-top: 8px solid #ffffff;
border-left: 8px solid transparent;
}
.bar-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.bar-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.bar-head {
display: flex;
justify-content: space-between;
color: #424752;
font-size: 12px;
line-height: 16px;
font-weight: 500;
}
.bar-score {
color: #00478d;
}
.bar-track {
width: 100%;
height: 6px;
border-radius: 999px;
background: #e1e2ea;
overflow: hidden;
}
.bar-fill {
height: 100%;
background: #00478d;
}
.action-area {
margin-top: 8px;
padding-bottom: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.primary-action,
.secondary-action {
width: 100%;
height: 56px;
min-height: 56px;
margin: 0;
border-radius: 8px;
font-size: 16px;
line-height: 24px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.primary-action {
border: 0;
background: #00478d;
box-shadow: 0 4px 12px rgba(0, 71, 141, 0.22);
color: #ffffff;
}
.secondary-action {
border: 2px solid rgba(0, 71, 141, 0.2);
background: #ffffff;
color: #00478d;
}
.description-icon,
.map-icon {
width: 20px;
height: 20px;
}
.primary-action .description-icon {
background: #ffffff;
}
.secondary-action .map-icon {
background: #00478d;
}
.description-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8l-6-6zm-1%207V3.5L18.5%209H13zm-5%204h8v2H8v-2zm0%204h8v2H8v-2z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8l-6-6zm-1%207V3.5L18.5%209H13zm-5%204h8v2H8v-2zm0%204h8v2H8v-2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.map-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='m20.5%203-.16.03L15%205.1%209%203%203.36%204.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9%2018.9l6%202.1%205.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15%2019l-6-2.11V5l6%202.11V19z'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='m20.5%203-.16.03L15%205.1%209%203%203.36%204.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9%2018.9l6%202.1%205.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15%2019l-6-2.11V5l6%202.11V19z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.toast {
position: fixed;
left: 50%;
bottom: 96px;
z-index: 100;
max-width: 320px;
padding: 12px 24px;
border-radius: 999px;
background: #2e3037;
color: #eff0f8;
font-size: 14px;
line-height: 20px;
font-weight: 600;
text-align: center;
pointer-events: none;
opacity: 0;
transform: translate(-50%, 16px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
.toast.visible {
opacity: 1;
transform: translate(-50%, 0);
}
</style>