feat: 新增教学模式
This commit is contained in:
+79
-3
@@ -6,6 +6,13 @@
|
||||
@open-profile="emit('open-profile')"
|
||||
@go-home="emit('go-home')"
|
||||
/>
|
||||
<TeachingPage
|
||||
v-else-if="showTeachingPage"
|
||||
:case-item="selectedCase"
|
||||
@open-settings="emit('open-settings')"
|
||||
@open-profile="emit('open-profile')"
|
||||
@go-home="emit('go-home')"
|
||||
/>
|
||||
<view v-else class="cases-page">
|
||||
<view class="case-shell">
|
||||
<view class="case-header">
|
||||
@@ -40,6 +47,7 @@
|
||||
v-for="item in filteredCases"
|
||||
:key="item.id"
|
||||
class="case-card"
|
||||
:class="`mode-${item.mode}`"
|
||||
@click="selectCase(item)"
|
||||
>
|
||||
<view class="case-main">
|
||||
@@ -55,6 +63,10 @@
|
||||
</view>
|
||||
<view class="case-footer">
|
||||
<text class="case-no">病例编号: {{ item.caseNo }}</text>
|
||||
<view class="mode-badge" :class="`mode-badge-${item.mode}`">
|
||||
<view class="mode-icon" :class="`mode-icon-${item.mode}`"></view>
|
||||
<text>{{ getModeLabel(item.mode) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -71,8 +83,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { fetchCaseList, type ClinicalCase } from '../../api/cases'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { fetchCaseList, type CaseMode, type ClinicalCase } from '../../api/cases'
|
||||
import ScenarioPage from '../scenario/scenario.vue'
|
||||
import TeachingPage from '../teaching/teaching.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'open-settings'): void
|
||||
@@ -86,14 +100,17 @@ const toastMessage = ref('')
|
||||
const toastVisible = ref(false)
|
||||
const selectedCase = ref<ClinicalCase | null>(null)
|
||||
const showScenarioPage = ref(false)
|
||||
const showTeachingPage = ref(false)
|
||||
const modeFilter = ref<CaseMode | ''>('')
|
||||
|
||||
let toastTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const filteredCases = computed(() => {
|
||||
const value = keyword.value.trim().toLowerCase()
|
||||
if (!value) return cases.value
|
||||
const source = modeFilter.value ? cases.value.filter(item => item.mode === modeFilter.value) : cases.value
|
||||
if (!value) return source
|
||||
|
||||
return cases.value.filter(item => {
|
||||
return source.filter(item => {
|
||||
return [
|
||||
item.title,
|
||||
item.patientName,
|
||||
@@ -106,6 +123,10 @@ const filteredCases = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
function getModeLabel(mode: CaseMode) {
|
||||
return mode === 'teaching' ? '教学模式' : '训练模式'
|
||||
}
|
||||
|
||||
function loadCases() {
|
||||
fetchCaseList().then(result => {
|
||||
cases.value = result
|
||||
@@ -114,7 +135,12 @@ function loadCases() {
|
||||
|
||||
function selectCase(item: ClinicalCase) {
|
||||
uni.setStorageSync('clinical-thinking-selected-case', item)
|
||||
uni.setStorageSync('clinical-thinking-case-mode', item.mode)
|
||||
selectedCase.value = item
|
||||
if (item.mode === 'teaching') {
|
||||
showTeachingPage.value = true
|
||||
return
|
||||
}
|
||||
showScenarioPage.value = true
|
||||
}
|
||||
|
||||
@@ -131,6 +157,13 @@ function showToast(message: string) {
|
||||
}, 2200)
|
||||
}
|
||||
|
||||
onLoad(query => {
|
||||
const mode = query?.mode
|
||||
if (mode === 'teaching' || mode === 'training') {
|
||||
modeFilter.value = mode
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(loadCases)
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -296,6 +329,10 @@ page {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.case-card.mode-teaching {
|
||||
border-color: rgba(0, 71, 141, 0.22);
|
||||
}
|
||||
|
||||
.case-card:active {
|
||||
transform: scale(0.99);
|
||||
}
|
||||
@@ -411,6 +448,45 @@ page {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mode-badge {
|
||||
flex: 0 0 auto;
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.mode-badge-training {
|
||||
background: #ecedf6;
|
||||
color: #424752;
|
||||
}
|
||||
|
||||
.mode-badge-teaching {
|
||||
background: #d6e3ff;
|
||||
color: #00478d;
|
||||
}
|
||||
|
||||
.mode-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.mode-icon-training {
|
||||
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M9%2016.2l-3.5-3.5L4%2014.2%209%2019%2020%208l-1.5-1.5L9%2016.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='M9%2016.2l-3.5-3.5L4%2014.2%209%2019%2020%208l-1.5-1.5L9%2016.2z'/%3E%3C/svg%3E") center / contain no-repeat;
|
||||
}
|
||||
|
||||
.mode-icon-teaching {
|
||||
-webkit-mask: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%203L1%209l11%206%209-4.91V17h2V9L12%203zm0%202.28L18.85%209%2012%2012.72%205.15%209%2012%205.28zM5%2013.18v3.2C6.63%2018.24%209.26%2019%2012%2019s5.37-.76%207-2.62v-3.2l-7%203.82-7-3.82z'/%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%203L1%209l11%206%209-4.91V17h2V9L12%203zm0%202.28L18.85%209%2012%2012.72%205.15%209%2012%205.28zM5%2013.18v3.2C6.63%2018.24%209.26%2019%2012%2019s5.37-.76%207-2.62v-3.2l-7%203.82-7-3.82z'/%3E%3C/svg%3E") center / contain no-repeat;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 40px 0;
|
||||
text-align: center;
|
||||
|
||||
Reference in New Issue
Block a user