feat(doctor): 新增医生聊天与订单确认功能

- 在医生聊天页面增加患者与医师列表渲染逻辑
- 新增订单确认页面,支持处方信息预览与发送
- 更新开方页面跳转逻辑,将数据通过本地存储传递至确认页-优化聊天页面初始化逻辑,区分医生与普通用户角色-修复 CMS 文章详情内容判断逻辑,避免空内容解析异常
- 新增关于我们页面,支持富文本内容展示- 调整医生相关模型字段,如添加头像、替换手机号字段为 phone
- 补充页面配置文件,完善导航栏标题与样式设置
- 新增医生订单确认页样式文件及详细交互布局
- 提供订单确认页使用说明文档,涵盖功能概述与技术实现细节
This commit is contained in:
2025-10-28 17:24:23 +08:00
parent 18940c8fd6
commit 25eb1366c5
17 changed files with 1540 additions and 242 deletions

158
src/chat/doctor/index.tsx Normal file
View File

@@ -0,0 +1,158 @@
import {useState, useEffect} from 'react'
import {View, Text} from '@tarojs/components'
import Taro, {useDidShow} from '@tarojs/taro'
import {useRouter} from '@tarojs/taro'
import {
Loading,
InfiniteLoading,
Empty,
Space,
Input,
Avatar,
Tag,
Divider,
Button
} from '@nutui/nutui-react-taro'
import { Voice, FaceMild, AddCircle } from '@nutui/icons-react-taro'
import {getClinicDoctorUser} from "@/api/clinic/clinicDoctorUser";
import {ClinicDoctorUser} from "@/api/clinic/clinicDoctorUser/model";
import {ClinicPatientUser} from "@/api/clinic/clinicPatientUser/model";
import navTo from "@/utils/common";
import {pageShopChatMessage} from "@/api/shop/shopChatMessage";
import {ShopChatMessage} from "@/api/shop/shopChatMessage/model";
import Line from "@/components/Gap";
const CustomerIndex = () => {
const {params} = useRouter();
const [doctor, setDoctor] = useState<ClinicDoctorUser>()
const [list, setList] = useState<ShopChatMessage[]>([])
const [isDoctor, setIsDoctor] = useState<boolean>(false)
const [doctors, setDoctors] = useState<ClinicDoctorUser[]>([])
const [patientUsers, setPatientUsers] = useState<ClinicPatientUser[]>([])
const [loading, setLoading] = useState<boolean>(false)
const [searchValue, setSearchValue] = useState<string>('')
const [displaySearchValue, setDisplaySearchValue] = useState<string>('')
const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true)
// 获取列表数据
const fetchData = async () => {
setLoading(true);
if (Taro.getStorageSync('Doctor')) {
setIsDoctor(true)
}
const doctorUser = await getClinicDoctorUser(Number(params.id))
if (doctorUser) {
setDoctor(doctorUser)
Taro.setNavigationBarTitle({title: `${doctorUser.realName}`});
}
const messages = await pageShopChatMessage({})
}
// 初始化数据
useEffect(() => {
fetchData().then()
}, []);
// 监听页面显示,当从其他页面返回时刷新数据
useDidShow(() => {
// 刷新当前tab的数据和统计信息
fetchData().then();
});
// 渲染医师项
const renderDoctorItem = (item: ClinicDoctorUser) => (
<View key={item.userId} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
<View className="flex items-center">
<View className="flex-1 flex justify-between items-center">
<View className="flex justify-between">
<Avatar src={item.avatar} size={'large'}/>
<View className={'flex flex-col mx-3'}>
<Text className="font-semibold text-gray-800 mr-2">
{item.realName}
</Text>
<View>
<Tag background="#f3f3f3" color="#999999"></Tag>
</View>
<View className={'my-1'}>
<Text className={'text-gray-400 text-xs'}> 1 </Text>
<Divider direction="vertical"/>
<Text className={'text-gray-400 text-xs'}> 3 </Text>
</View>
</View>
</View>
<Button type="warning"></Button>
</View>
</View>
</View>
);
// 渲染患者项
const renderPatientUserItem = (item: ClinicPatientUser) => (
<View key={item.userId} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
<View className="flex items-center">
<View className="flex-1 flex justify-between items-center">
<View className="flex justify-between">
<Avatar src={item.avatar} size={'large'}/>
<View className={'flex flex-col mx-3'}>
<Text className="font-semibold text-gray-800 mr-2">
{item.realName}
</Text>
<View>
{
<Text
className={'text-gray-400 text-xs'}>{item.sex}</Text>
}
{
item.age && (
<>
<Divider direction="vertical"/>
<Text className={'text-gray-400 text-xs'}>{item.age}</Text>
</>
)
}
{
item.weight && (
<>
<Divider direction="vertical"/>
<Text className={'text-gray-400 text-xs'}>{item.weight}</Text>
</>
)
}
</View>
<View>
<Text className={'text-gray-400 text-xs'}>{item.allergyHistory}</Text>
</View>
</View>
</View>
<Button type="warning" onClick={() => navTo(`/doctor/orders/add?id=${item.userId}`)}></Button>
</View>
</View>
</View>
);
return (
<View className="min-h-screen bg-gray-50 w-full">
<View className={'p-4'}>
{list?.map(renderPatientUserItem)}
</View>
<View className={'fixed bottom-0 w-full bg-orange-50 pt-2 pb-8'}>
<View className={'flex flex-1 items-center justify-between'}>
<Voice className={'mx-2'} />
<Input className={'w-full'} style={{
borderRadius: '6px',
paddingLeft: '12px',
paddingRight: '12px'
}} />
<FaceMild size={26} className={'ml-2'} />
<AddCircle size={26} className={'mx-2'} />
</View>
</View>
</View>
);
};
export default CustomerIndex;