feat: 联调对话功能
This commit is contained in:
@@ -1,17 +1,11 @@
|
||||
<template>
|
||||
<TreatmentPage
|
||||
v-if="showTreatmentPage"
|
||||
:case-item="caseItem"
|
||||
@open-settings="emit('open-settings')"
|
||||
@open-profile="openProfile"
|
||||
@go-home="emit('go-home')"
|
||||
/>
|
||||
<view v-else class="diagnosis-page">
|
||||
<view class="diagnosis-page">
|
||||
<view class="diagnosis-shell">
|
||||
<view class="top-nav">
|
||||
<button class="icon-button" aria-label="设置" @click="emit('open-settings')">
|
||||
<button class="icon-button" aria-label="设置" @click="openSettings">
|
||||
<view class="settings-icon"></view>
|
||||
</button>
|
||||
<button class="icon-button home-button" aria-label="首页" @click="emit('go-home')">
|
||||
<button class="icon-button home-button" aria-label="首页" @click="goHome">
|
||||
<view class="home-icon"></view>
|
||||
</button>
|
||||
<view class="nav-spacer"></view>
|
||||
@@ -132,13 +126,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import type { ClinicalCase } from '../../api/cases'
|
||||
import { readStoredClinicalCase, type ClinicalCase } from '../../api/cases'
|
||||
import { fetchDiagnosisContext, submitDiagnosis, type DiagnosisDraft } from '../../api/diagnosis'
|
||||
import { createProfileOpener } from '../../api/navigation'
|
||||
import TreatmentPage from '../treatment/treatment.vue'
|
||||
import { createHomeNavigator, createProfileOpener, createSettingsOpener } from '../../api/navigation'
|
||||
import { readActiveSessionId } from '../../api/session'
|
||||
|
||||
const props = defineProps<{
|
||||
caseItem: ClinicalCase | null
|
||||
caseItem?: ClinicalCase | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -148,6 +142,8 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const openProfile = createProfileOpener(emit)
|
||||
const openSettings = createSettingsOpener(emit)
|
||||
const goHome = createHomeNavigator(emit)
|
||||
|
||||
type SubmitState = 'idle' | 'submitted'
|
||||
|
||||
@@ -162,15 +158,19 @@ const submitting = ref(false)
|
||||
const submitState = ref<SubmitState>('idle')
|
||||
const toastMessage = ref('')
|
||||
const toastVisible = ref(false)
|
||||
const showTreatmentPage = ref(false)
|
||||
const storedCase = ref<ClinicalCase | null>(null)
|
||||
|
||||
let toastTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const patientName = computed(() => '陈先生')
|
||||
const patientGender = computed(() => '男')
|
||||
const patientAge = computed(() => 60)
|
||||
const patientDepartment = computed(() => '心血管内科')
|
||||
const complaintShort = computed(() => '胸痛')
|
||||
const activeCase = computed(() => props.caseItem || storedCase.value)
|
||||
const patientName = computed(() => activeCase.value?.patientName || '陈先生')
|
||||
const patientGender = computed(() => activeCase.value?.gender || '男')
|
||||
const patientAge = computed(() => activeCase.value?.age || 60)
|
||||
const patientDepartment = computed(() => activeCase.value?.department || '心血管内科')
|
||||
const complaintShort = computed(() => {
|
||||
const title = activeCase.value?.title || '持续胸痛3小时'
|
||||
return title.includes('胸痛') ? '胸痛' : title.slice(0, 6)
|
||||
})
|
||||
|
||||
const buttonText = computed(() => {
|
||||
if (submitting.value) return '提交中...'
|
||||
@@ -179,7 +179,7 @@ const buttonText = computed(() => {
|
||||
})
|
||||
|
||||
function loadDiagnosisContext() {
|
||||
fetchDiagnosisContext(props.caseItem).then(result => {
|
||||
fetchDiagnosisContext(activeCase.value).then(result => {
|
||||
mentorAdvice.value = result.mentorAdvice
|
||||
form.primaryDiagnosis = ''
|
||||
form.differentialDiagnosis = ['', '']
|
||||
@@ -187,36 +187,54 @@ function loadDiagnosisContext() {
|
||||
})
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
async function handleNext() {
|
||||
if (submitting.value) return
|
||||
if (!form.primaryDiagnosis.trim()) {
|
||||
showToast('请输入主要诊断')
|
||||
return
|
||||
}
|
||||
if (!form.evidence.trim()) {
|
||||
showToast('请输入诊断依据')
|
||||
return
|
||||
}
|
||||
|
||||
submitting.value = true
|
||||
submitDiagnosis(props.caseItem?.id || 'mock-case', {
|
||||
primaryDiagnosis: form.primaryDiagnosis,
|
||||
differentialDiagnosis: form.differentialDiagnosis.filter(item => item.trim()),
|
||||
evidence: form.evidence
|
||||
}).then(result => {
|
||||
try {
|
||||
const sessionId = readActiveSessionId()
|
||||
const result = await submitDiagnosis(sessionId, {
|
||||
primaryDiagnosis: form.primaryDiagnosis,
|
||||
differentialDiagnosis: form.differentialDiagnosis.filter(item => item.trim()),
|
||||
evidence: form.evidence
|
||||
})
|
||||
uni.setStorageSync('clinical-thinking-diagnosis', result)
|
||||
showTreatmentPage.value = true
|
||||
}).finally(() => {
|
||||
submitState.value = 'submitted'
|
||||
uni.redirectTo({
|
||||
url: '/pages/treatment/treatment',
|
||||
fail() {
|
||||
submitState.value = 'idle'
|
||||
showToast('进入治疗计划失败,请重试')
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
showToast(error instanceof Error ? error.message : '诊断提交失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
onMounted(loadDiagnosisContext)
|
||||
onMounted(() => {
|
||||
storedCase.value = readStoredClinicalCase()
|
||||
loadDiagnosisContext()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (toastTimer) clearTimeout(toastTimer)
|
||||
@@ -312,6 +330,7 @@ page {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.settings-icon,
|
||||
.home-icon,
|
||||
.account-icon,
|
||||
.check-icon,
|
||||
@@ -331,6 +350,13 @@ page {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
-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;
|
||||
@@ -378,6 +404,9 @@ page {
|
||||
|
||||
.stepper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex: 0 0 auto;
|
||||
min-height: 56px;
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user