Files
hms/apps/web/src/pages/health/components/ChatBubble.tsx
iven 0c21f13e72
Some checks failed
CI / security-audit (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
feat(web): 健康管理模块 10 页面完整实现
Task 12 - 患者管理:
- PatientList: 搜索+状态筛选+CRUD+行点击跳转详情
- PatientTagManage: 患者标签管理+批量打标
- PatientDetail: 3Tab详情页(基本信息/健康数据/随访记录)+编辑

Task 13 - 医护预约:
- DoctorList: 科室筛选+CRUD+在线状态Badge
- AppointmentList: 状态筛选+日期筛选+创建预约+状态流转
- DoctorSchedule: 医生选择+列表/日历视图+排班CRUD

Task 14 - 随访咨询:
- FollowUpTaskList: 任务CRUD+填写记录+分配医护
- FollowUpRecordList: 只读台账+日期范围筛选+导出
- ConsultationList: 会话列表+创建+关闭+行点击跳转
- ConsultationDetail: 聊天界面+消息分页+发送+图片预览

修正: consultations.ts Session类型补充 updated_at/version
2026-04-25 00:57:48 +08:00

75 lines
2.0 KiB
TypeScript

import { Avatar, Typography } from 'antd';
import { UserOutlined } from '@ant-design/icons';
interface Props {
senderRole: 'patient' | 'doctor' | 'system';
senderName?: string;
content: string;
contentType?: string;
createdAt: string;
}
const ROLE_CONFIG = {
patient: { align: 'flex-start' as const, bg: '#f0f0f0', color: '#000' },
doctor: { align: 'flex-end' as const, bg: '#1890ff', color: '#fff' },
system: { align: 'center' as const, bg: '#fafafa', color: '#999' },
};
export function ChatBubble({
senderRole,
senderName,
content,
createdAt,
}: Props) {
const cfg = ROLE_CONFIG[senderRole] ?? ROLE_CONFIG.system;
if (senderRole === 'system') {
return (
<div style={{ textAlign: 'center', padding: '8px 0' }}>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
{content}
</Typography.Text>
</div>
);
}
return (
<div style={{ display: 'flex', justifyContent: cfg.align, marginBottom: 12 }}>
{senderRole === 'patient' && (
<Avatar icon={<UserOutlined />} style={{ marginRight: 8, flexShrink: 0 }} />
)}
<div style={{ maxWidth: '70%' }}>
{senderName && (
<Typography.Text
type="secondary"
style={{ fontSize: 12, display: 'block', marginBottom: 2 }}
>
{senderName}
</Typography.Text>
)}
<div
style={{
background: cfg.bg,
color: cfg.color,
padding: '8px 12px',
borderRadius: 8,
wordBreak: 'break-word',
}}
>
<Typography.Paragraph
style={{ margin: 0, color: 'inherit' }}
>
{content}
</Typography.Paragraph>
</div>
<Typography.Text type="secondary" style={{ fontSize: 11 }}>
{createdAt}
</Typography.Text>
</div>
{senderRole === 'doctor' && (
<Avatar icon={<UserOutlined />} style={{ marginLeft: 8, flexShrink: 0 }} />
)}
</div>
);
}