feat: 联调对话功能
This commit is contained in:
+61
-36
@@ -1,13 +1,8 @@
|
||||
<template>
|
||||
<HomePage
|
||||
v-if="showHomePage"
|
||||
@open-settings="returnToSettings"
|
||||
@open-profile="openProfile"
|
||||
/>
|
||||
<view v-else class="config-page">
|
||||
<view class="config-page">
|
||||
<view class="phone-frame">
|
||||
<view class="hero-section">
|
||||
<image class="hospital-image" src="/static/config-hospital.png" mode="aspectFill"></image>
|
||||
<image class="hospital-image" :src="hospitalBannerUrl" mode="aspectFill" @error="handleBannerError"></image>
|
||||
<view class="hero-overlay"></view>
|
||||
</view>
|
||||
|
||||
@@ -99,8 +94,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import HomePage from '../home/home.vue'
|
||||
import { createProfileOpener } from '../../api/navigation'
|
||||
import { fetchInstitutionInfo, fetchMyDepartments, type DepartmentRecord } from '../../api/auth'
|
||||
import {
|
||||
MOCK_CONFIG_OPTIONS,
|
||||
fetchConfigOptions,
|
||||
@@ -114,12 +109,7 @@ type PickerType = '' | 'department' | 'title' | 'experience'
|
||||
type OptionGroup = keyof ConfigOptions
|
||||
type SaveState = 'idle' | 'saved'
|
||||
|
||||
type LoginUser = {
|
||||
id?: string | number
|
||||
phone?: string
|
||||
institutionId?: string
|
||||
institution?: string | null
|
||||
}
|
||||
const DEFAULT_HOSPITAL_BANNER = '/static/config-hospital.png'
|
||||
|
||||
const form = reactive({
|
||||
department: 'im',
|
||||
@@ -137,7 +127,7 @@ const saving = ref(false)
|
||||
const saveState = ref<SaveState>('idle')
|
||||
const toastMessage = ref('')
|
||||
const toastVisible = ref(false)
|
||||
const showHomePage = ref(false)
|
||||
const hospitalBannerUrl = ref('')
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'open-profile'): void
|
||||
@@ -189,6 +179,39 @@ function loadConfigOptions() {
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeDepartment(item: DepartmentRecord): ConfigOption {
|
||||
return {
|
||||
value: String(item.id),
|
||||
label: item.name,
|
||||
desc: item.category
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDepartments() {
|
||||
try {
|
||||
const departments = await fetchMyDepartments()
|
||||
if (departments.length === 0) return
|
||||
|
||||
const departmentOptions = departments.map(normalizeDepartment)
|
||||
options.value = {
|
||||
...options.value,
|
||||
departments: departmentOptions
|
||||
}
|
||||
form.department = departmentOptions[0].value
|
||||
} catch {
|
||||
// Keep mock departments when the user-specific list cannot be loaded.
|
||||
}
|
||||
}
|
||||
|
||||
async function loadInstitutionInfo() {
|
||||
try {
|
||||
const institution = await fetchInstitutionInfo()
|
||||
hospitalBannerUrl.value = institution.banner_url || DEFAULT_HOSPITAL_BANNER
|
||||
} catch {
|
||||
hospitalBannerUrl.value = DEFAULT_HOSPITAL_BANNER
|
||||
}
|
||||
}
|
||||
|
||||
function findOption(group: OptionGroup, value: string) {
|
||||
const groupOptions = options.value[group] || []
|
||||
return groupOptions.find(item => item.value === value) || groupOptions[0] || { label: '请选择', value: '' }
|
||||
@@ -231,17 +254,16 @@ function chooseOption(option: ConfigOption) {
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
const user = (uni.getStorageSync('clinical-thinking-user') || {}) as LoginUser
|
||||
const departmentId = Number(form.department)
|
||||
if (!Number.isInteger(departmentId) || departmentId <= 0) {
|
||||
showToast('请先选择有效执业科室')
|
||||
return
|
||||
}
|
||||
|
||||
const payload: ClinicalConfigPayload = {
|
||||
userId: user.id ? String(user.id) : 'mock-user-guest',
|
||||
phone: user.phone || '',
|
||||
institutionId: user.institutionId || user.institution || '',
|
||||
department: form.department,
|
||||
title: form.title,
|
||||
experience: form.experience,
|
||||
departmentName: selectedDepartment.value.label,
|
||||
titleName: selectedTitle.value.label,
|
||||
experienceName: selectedExperience.value.label
|
||||
department: departmentId,
|
||||
title_name: selectedTitle.value.label,
|
||||
practice_years: selectedExperience.value.label
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
@@ -253,33 +275,36 @@ function handleSubmit() {
|
||||
showToast('配置已保存')
|
||||
|
||||
setTimeout(() => {
|
||||
showHomePage.value = true
|
||||
uni.reLaunch({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
}, 500)
|
||||
}).catch(() => {
|
||||
}).catch(error => {
|
||||
saving.value = false
|
||||
showToast('保存失败,请稍后重试')
|
||||
showToast(error instanceof Error ? error.message : '保存失败,请稍后重试')
|
||||
})
|
||||
}
|
||||
|
||||
function returnToSettings() {
|
||||
showHomePage.value = false
|
||||
saveState.value = 'idle'
|
||||
function handleBannerError() {
|
||||
if (hospitalBannerUrl.value !== DEFAULT_HOSPITAL_BANNER) {
|
||||
hospitalBannerUrl.value = DEFAULT_HOSPITAL_BANNER
|
||||
}
|
||||
}
|
||||
|
||||
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(loadConfigOptions)
|
||||
onMounted(() => {
|
||||
loadConfigOptions()
|
||||
void loadDepartments()
|
||||
void loadInstitutionInfo()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (typingTimer) clearTimeout(typingTimer)
|
||||
|
||||
Reference in New Issue
Block a user