完成选择三甲还是普通问诊页面,点击后记录对应的类型,跳转到选择科室路由
步骤:
代码:
1)路由和组件
router/index.ts
{
path: '/consult/fast',
component: () => import('@/views/consult/ConsultFast.vue'),
meta: { title: '极速问诊' }
}
2)点击入口记录极速问诊级别
Consult/ConsultFast.vue
<script setup lang="ts">
import { useConsultStore } from '@/stores'
const store = useConsultStore()
</script>
实现:配置科室选择路由
代码:
router/index.ts
{
path: '/consult/dep',
component: () => import('@/views/consult/ConsultDep.vue'),
meta: { title: '选择科室' }
}
实现:科室切换以及跳转到病情描述
步骤:
编写科室需要的类型:父子科室
准备API函数
实现一级科室切换
实现二级科室切换
跳转时记录科室到问诊记录
代码:
1)编写科室需要的类型 types/consult.d.ts
// 科室
export type SubDep = {
id: string
name: string
}
// 一级科室
export type TopDep = SubDep & {
child: SubDep[]
}
2)准备API函数 api/consult.ts
import type {
DoctorPage,
FollowType,
KnowledgePage,
KnowledgeParams,
PageParams,
+ TopDep
} from '@/types/consult'
+ export const getAllDep = () => request.get('/dep/all')
3)实现一级科室切换 Consult/ConsultDep.vue
import { getAllDep } from '@/api/consult'
import type { TopDep } from '@/types/consult'
import { onMounted, ref } from 'vue'
// 获取所有科室
const allDep = ref<TopDep[]>([])
onMounted(async () => {
const res = await getAllDep()
allDep.value = res.data
})
<van-sidebar v-model="active">
<van-sidebar-item :title="top.name" v-for="top in allDep" :key="top.id" />
van-sidebar>
4)实现二级科室切换
{{ item.name }}
注意❓:使用可选链操作符,解决组件初始化没有数据 child 可能拿不到
5)跳转时记录科室到问诊记录
import { useConsultStore } from '@/stores'
const store = useConsultStore()
{{ sub.name }}
实现:路由配置,了解组件以及页面的基础布局(医生提示,描述,症状时间,是否已问诊)
1)路由
{
path: '/consult/illness',
component: () => import('@/views/consult/ConsultIllness.vue'),
meta: { title: '病情描述' }
},
2)准备病情描述类型和表单数据
consult.d.ts
// 病情描述全部必填
export type ConsultIllness = Pick<
PartialConsult,
'illnessDesc' | 'illnessTime' | 'consultFlag' | 'pictures'
>
Consult/ConsultIllness.vue
import type { ConsultIllness } from '@/types/consult'
import { ref } from 'vue'
// 表单变量
const form = ref<ConsultIllness>({
illnessDesc: '',
illnessTime: undefined,
consultFlag: undefined,
pictures: []
})
本次患病多久了?
此次病情是否去医院问诊过?
实现:使用 van-upload 组件,进行样式和功能配置
步骤:
代码:
1)配置文字和图标
2)配置最多数量和最大体积
3)支持双向数据绑定,支持选择图片后触发函数,支持点击删除事件函数
// 有赞提供的类型
import type { UploaderAfterRead, UploaderFileListItem } from 'vant/lib/uploader/types'
import type { Image } from '@/types/consult'
const fileList = ref<Image[]>([])
const onAfterRead: UploaderAfterRead = (item) => {
// TODO 上传图片:调用后台api上传接口
}
const onDeleteImg = (item: UploaderFileListItem) => {
// TODO 删除图片
}
小结:
实现:上传图片与删除图片功能
步骤:
代码:
1)定义 api 函数 api/consult.ts
import type {
DoctorPage,
FollowType,
+ Image,
KnowledgePage,
KnowledgeParams,
PageParams,
TopDep
} from '@/types/consult'
// 上传病情描述图片
export const uploadImage = (file: File) => {
const fd = new FormData()
fd.append('file', file)
return request.post<Image>('/upload', fd)
}
2)实现上传 Consult/ConsultIllness.vue
import { uploadImage } from '@/api/consult'
// 这个item并不是我们传的值,就是vant自带的那个参数'file'
const onAfterRead: UploaderAfterRead = (item) => {
if (Array.isArray(item)) return
if (!item.file) return
// 开始上传
item.status = 'uploading'
item.message = '上传中...'
uploadImage(item.file)
.then((res) => {
item.status = 'done'
item.message = undefined
// 给 item 加上 url 是为了删除可以根据 url 进行删除
item.url = res.data.url
// 存储上传成功图片url
form.value.pictures?.push(res.data)
})
.catch(() => {
item.status = 'failed'
item.message = '上传失败'
})
}
3)实现删除
const onDeleteImg = (item: UploaderFileListItem) => {
// 删除已经上传图片 -->> 根据我们上传是记录的url来删除
form.value.pictures = form.value.pictures?.filter((pic) => pic.url !== item.url)
}
小结:
实现:按钮点亮,提交校验,保存数据,跳转选择患者
1)添加vant按钮,实现按钮点亮交互
<van-button :class={disabled} @click="next" type="primary" block round>下一步van-button>
import { computed, ref } from 'vue'
// ... 省略 ...
const disabled = computed(
() =>
!form.value.illnessDesc ||
form.value.illnessTime === undefined ||
form.value.consultFlag === undefined
)
2)提交校验 保存数据,跳转选择患者
import { useRouter } from 'vue-router'
import { Toast } from 'vant'
import { useConsultStore } from '@/stores'
const store = useConsultStore()
const router = useRouter()
const next = () => {
if (!form.value.illnessDesc) return Toast('请输入病情描述')
if (form.value.illnessTime === undefined) return Toast('请选择症状持续时间')
if (form.value.consultFlag === undefined) return Toast('请选择是否已经问诊')
// 存储病情描述
store.setIllness(form.value)
// 跳转档案管理:选择患者,需要根据 isChange 实现选择功能
router.push('/user/patient?isChange=1')
}
说明❓:后续需要根据?isChange=1
参数实现患者选择功能
实现:进入页面时候提示用户是否回显之前填写的病情描述信息
1)进入页面,如果有记录数据,弹出确认框
import { ..., onMounted } from 'vue'
// 回显数据
onMounted(() => {
if (store.consult.illnessDesc) {
Dialog.confirm({
title: '温馨提示',
message: '是否恢复您之前填写的病情信息呢?',
confirmButtonColor: 'var(--cp-primary)',
closeOnPopstate: false // 是否在页面回退时自动关闭,注意默认值为true
}).then(() => {
// 确认
})
}
})
2)回显数据
从 store 拿出记录的数据
// ...
.then(() => {
// 确认
const { illnessDesc, illnessTime, consultFlag, pictures } = store.consult
form.value = { illnessDesc, illnessTime, consultFlag, pictures }
// 图片回显预览
fileList.value = pictures || []
})
说明❓:回退页面时,确认框会自动关闭,需要设置closeOnPopstate: false
实现:在家庭档案基础上实现选择患者功能
步骤:
界面兼容,根据地址栏是否有isChange
标识
点击选中效果
默认选中效果
记录患者ID跳转到待支付页面
代码:
User/PatientInfo.vue
import { useRoute } from 'vue-router'
// 是否是选择患者
const route = useRoute()
// 用于判断是否能够选中患者 --极速问诊流程中能够选中 --家庭档案中不能选中
const isChange = computed(() => route.query.isChange === '1')
-
请选择患者信息
以便医生给出更准确的治疗,信息仅医生可见
-
下一步
// 存储点击选中患者ID作为标识
const patientId = ref<string>()
const selectedPatient = (item: Patient) => {
if (isChange.value) {
patientId.value = item.id
}
}
- 默认选中效果
const loadList = async () => {
const res = await getPatientList()
list.value = res.data
+ // 设置默认选中的ID,当你是选择患者的时候,且有患者信息的时候
+ if (isChange.value && list.value.length) {
+ const defPatient = list.value.find((item) => item.defaultFlag === 1)
+ if (defPatient) patientId.value = defPatient.id
+ else patientId.value = list.value[0].id
+ }
}
- 记录患者ID跳转到待支付页面
const store = useConsultStore()
const router = useRouter()
const next = async () => {
if (!patientId.value) return Toast('请选问诊择患者')
store.setPatient(patientId.value)
router.push('/consult/pay')
}