Commit f1c4920f authored by yuguo's avatar yuguo

fix

parent 4ae56601
......@@ -14,7 +14,11 @@
"Bash(npx tailwindcss:*)",
"Bash(npx next:*)",
"Bash(PGPASSWORD=T5sSfTZ6XYTD9bfC psql:*)",
"Bash(npm install:*)"
"Bash(npm install:*)",
"Bash(kill:*)",
"Bash(go run:*)",
"Bash(npm run:*)",
"Bash(lsof:*)"
]
}
}
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
"internet-hospital/internal/model"
)
......@@ -46,7 +47,9 @@ func (s *Service) CreatePatient(ctx context.Context, req *CreatePatientRequest)
return fmt.Errorf("密码加密失败: %w", err)
}
userID := uuid.New().String()
user := &model.User{
ID: userID,
Phone: req.Phone,
Password: string(hashedPassword),
RealName: req.RealName,
......@@ -56,7 +59,22 @@ func (s *Service) CreatePatient(ctx context.Context, req *CreatePatientRequest)
Age: req.Age,
}
return s.db.Create(user).Error
tx := s.db.Begin()
if err := tx.Create(user).Error; err != nil {
tx.Rollback()
return err
}
profile := &model.PatientProfile{
ID: uuid.New().String(),
UserID: userID,
}
if err := tx.Create(profile).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
// UpdatePatient 更新患者信息
......
......@@ -7,7 +7,7 @@ import {
HomeOutlined, UserOutlined, MedicineBoxOutlined, FileTextOutlined,
HeartOutlined, SettingOutlined, LogoutOutlined, BellOutlined,
RobotOutlined, VideoCameraOutlined, PayCircleOutlined,
ShoppingCartOutlined, FolderOpenOutlined,
ShoppingCartOutlined, FolderOpenOutlined, SearchOutlined,
} from '@ant-design/icons';
import { useUserStore } from '@/store/userStore';
......@@ -16,17 +16,39 @@ const { Text } = Typography;
const menuItems = [
{ key: '/patient/home', icon: <HomeOutlined />, label: '首页' },
{ key: '/patient/doctors', icon: <MedicineBoxOutlined />, label: '医生列表' },
{ key: '/patient/pre-consult', icon: <RobotOutlined />, label: 'AI预问诊' },
{ key: '/patient/consult', icon: <VideoCameraOutlined />, label: '问诊' },
{ key: '/patient/prescription', icon: <FileTextOutlined />, label: '处方' },
{ key: '/patient/payment', icon: <PayCircleOutlined />, label: '支付' },
{ key: '/patient/pharmacy/order', icon: <ShoppingCartOutlined />, label: '药品配送' },
{ key: '/patient/chronic', icon: <HeartOutlined />, label: '慢病管理' },
{ key: '/patient/health-records', icon: <FolderOpenOutlined />, label: '健康档案' },
{
key: 'consult-services', icon: <VideoCameraOutlined />, label: '问诊服务',
children: [
{ key: '/patient/doctors', icon: <SearchOutlined />, label: '找医生' },
{ key: '/patient/pre-consult', icon: <RobotOutlined />, label: 'AI预问诊' },
{ key: '/patient/consult', icon: <VideoCameraOutlined />, label: '我的问诊' },
],
},
{
key: 'rx-pharmacy', icon: <MedicineBoxOutlined />, label: '处方购药',
children: [
{ key: '/patient/prescription', icon: <FileTextOutlined />, label: '电子处方' },
{ key: '/patient/pharmacy/order', icon: <ShoppingCartOutlined />, label: '药品配送' },
{ key: '/patient/payment', icon: <PayCircleOutlined />, label: '支付管理' },
],
},
{
key: 'health-mgmt', icon: <HeartOutlined />, label: '健康管理',
children: [
{ key: '/patient/chronic', icon: <HeartOutlined />, label: '慢病管理' },
{ key: '/patient/health-records', icon: <FolderOpenOutlined />, label: '健康档案' },
],
},
{ key: '/patient/profile', icon: <UserOutlined />, label: '个人中心' },
];
// 所有可路由的 key 列表(用于选中匹配)
const allRouteKeys = [
'/patient/home', '/patient/doctors', '/patient/pre-consult', '/patient/consult',
'/patient/prescription', '/patient/pharmacy/order', '/patient/payment',
'/patient/chronic', '/patient/health-records', '/patient/profile',
];
export default function PatientLayout({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
......@@ -52,8 +74,8 @@ export default function PatientLayout({ children }: { children: React.ReactNode
};
const getSelectedKeys = () => {
const match = menuItems.find(item => currentPath.startsWith(item.key));
return match ? [match.key] : [];
const match = allRouteKeys.find(k => currentPath.startsWith(k));
return match ? [match] : [];
};
return (
......
......@@ -2,7 +2,7 @@
import React from 'react';
import { useRouter } from 'next/navigation';
import { Card, Row, Col, Input, Button, Typography, Space, Statistic } from 'antd';
import { Card, Row, Col, Input, Button, Typography, Tag } from 'antd';
import {
SearchOutlined,
VideoCameraOutlined,
......@@ -14,144 +14,158 @@ import {
TeamOutlined,
SafetyCertificateOutlined,
ClockCircleOutlined,
RightOutlined,
ShoppingCartOutlined,
FolderOpenOutlined,
} from '@ant-design/icons';
const { Title, Text, Paragraph } = Typography;
const { Text } = Typography;
const PatientHomePage: React.FC = () => {
const router = useRouter();
const services = [
{ icon: <VideoCameraOutlined />, title: '视频问诊', desc: '面对面视频交流', path: '/patient/doctors?type=video', color: '#1890ff', bg: '#e6f7ff' },
{ icon: <MessageOutlined />, title: '图文问诊', desc: '随时在线咨询', path: '/patient/doctors?type=text', color: '#52c41a', bg: '#f6ffed' },
{ icon: <RobotOutlined />, title: 'AI智能问诊', desc: 'AI辅助症状分析', path: '/patient/pre-consult', color: '#722ed1', bg: '#f9f0ff' },
{ icon: <MedicineBoxOutlined />, title: '找医生', desc: '按科室找专家', path: '/patient/doctors', color: '#fa8c16', bg: '#fff7e6' },
{ icon: <FileTextOutlined />, title: '电子处方', desc: '查看历史处方', path: '/patient/prescription', color: '#13c2c2', bg: '#e6fffb' },
{ icon: <HeartOutlined />, title: '慢病管理', desc: '慢性病续方', path: '/patient/chronic', color: '#eb2f96', bg: '#fff0f6' },
];
const quickLinks = [
{ icon: <VideoCameraOutlined />, title: '我的问诊', path: '/patient/consult', color: '#1890ff' },
{ icon: <ShoppingCartOutlined />, title: '药品配送', path: '/patient/pharmacy/order', color: '#fa8c16' },
{ icon: <FolderOpenOutlined />, title: '健康档案', path: '/patient/health-records', color: '#52c41a' },
];
const services = [
{
icon: <VideoCameraOutlined style={{ fontSize: 36, color: '#1890ff' }} />,
title: '视频问诊',
desc: '与医生面对面视频交流',
path: '/patient/doctors?type=video',
color: '#e6f7ff',
},
{
icon: <MessageOutlined style={{ fontSize: 36, color: '#52c41a' }} />,
title: '图文问诊',
desc: '随时随地在线咨询',
path: '/patient/doctors?type=text',
color: '#f6ffed',
},
{
icon: <RobotOutlined style={{ fontSize: 36, color: '#722ed1' }} />,
title: 'AI 智能问诊',
desc: 'AI 辅助症状分析',
path: '/patient/pre-consult',
color: '#f9f0ff',
},
{
icon: <MedicineBoxOutlined style={{ fontSize: 36, color: '#fa8c16' }} />,
title: '找医生',
desc: '按科室找专家',
path: '/patient/doctors',
color: '#fff7e6',
},
{
icon: <FileTextOutlined style={{ fontSize: 36, color: '#13c2c2' }} />,
title: '电子处方',
desc: '查看历史处方',
path: '/patient/prescription',
color: '#e6fffb',
},
{
icon: <HeartOutlined style={{ fontSize: 36, color: '#eb2f96' }} />,
title: '慢病管理',
desc: '慢性病续方服务',
path: '/patient/chronic',
color: '#fff0f6',
},
];
const departments = [
'内科', '外科', '妇科', '儿科', '皮肤科', '眼科',
'耳鼻喉科', '口腔科', '骨科', '神经内科', '心血管内科', '消化内科',
];
const departments = [
'内科', '外科', '妇科', '儿科', '皮肤科', '眼科', '耳鼻喉科', '口腔科',
'骨科', '神经内科', '心血管内科', '消化内科',
];
const PatientHomePage: React.FC = () => {
const router = useRouter();
return (
<div className="max-w-[1200px] mx-auto space-y-3">
{/* 顶部 Banner */}
<div className="rounded-xl overflow-hidden"
style={{ background: 'linear-gradient(135deg, #001529 0%, #003a8c 40%, #0050b3 70%, #1890ff 100%)' }}>
<div className="text-center px-6 py-8 relative">
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white/5 rounded-full blur-2xl" />
<div className="absolute -bottom-10 -left-10 w-48 h-48 bg-blue-400/8 rounded-full blur-2xl" />
<div style={{ maxWidth: 1200, margin: '0 auto' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
{/* 顶部 Banner */}
<div style={{
borderRadius: 12, overflow: 'hidden', position: 'relative',
background: 'linear-gradient(135deg, #001529 0%, #003a8c 40%, #0050b3 70%, #1890ff 100%)',
}}>
{/* 装饰 */}
<div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }}>
<div style={{ position: 'absolute', top: -40, right: -40, width: 160, height: 160, background: 'rgba(255,255,255,0.05)', borderRadius: '50%', filter: 'blur(40px)' }} />
<div style={{ position: 'absolute', bottom: -40, left: -40, width: 192, height: 192, background: 'rgba(96,165,250,0.08)', borderRadius: '50%', filter: 'blur(40px)' }} />
</div>
<div className="relative z-10">
<h2 className="text-xl font-bold text-white mb-1">互联网医院 · 在线问诊平台</h2>
<p className="text-blue-200/80 text-sm mb-5">专业医生在线服务,足不出户享受优质医疗</p>
<div className="max-w-[440px] mx-auto">
<div style={{ position: 'relative', zIndex: 1, textAlign: 'center', padding: '32px 24px' }}>
<h2 style={{ fontSize: 20, fontWeight: 700, color: '#fff', margin: '0 0 4px' }}>互联网医院 · 在线问诊平台</h2>
<p style={{ fontSize: 13, color: 'rgba(191,219,254,0.8)', margin: '0 0 20px' }}>专业医生在线服务,足不出户享受优质医疗</p>
<div style={{ maxWidth: 440, margin: '0 auto' }}>
<Input.Search
placeholder="搜索医生、科室、疾病"
enterButton={<><SearchOutlined /> 搜索</>}
onSearch={(value) => router.push(`/patient/doctors?keyword=${value}`)}
className="shadow-lg shadow-black/10"
size="large"
/>
</div>
<div className="flex justify-center gap-12 mt-5">
<div className="text-center">
<div className="text-white text-xl font-bold"><TeamOutlined className="mr-1" />1,280</div>
<div className="text-blue-200/60 text-xs">注册医生</div>
</div>
<div className="text-center">
<div className="text-white text-xl font-bold"><SafetyCertificateOutlined className="mr-1" />56,800</div>
<div className="text-blue-200/60 text-xs">服务患者</div>
</div>
<div className="text-center">
<div className="text-white text-xl font-bold"><ClockCircleOutlined className="mr-1" />3分钟</div>
<div className="text-blue-200/60 text-xs">平均响应</div>
</div>
<div style={{ display: 'flex', justifyContent: 'center', gap: 48, marginTop: 20 }}>
{[
{ icon: <TeamOutlined />, value: '1,280', label: '注册医生' },
{ icon: <SafetyCertificateOutlined />, value: '56,800', label: '服务患者' },
{ icon: <ClockCircleOutlined />, value: '3分钟', label: '平均响应' },
].map((stat) => (
<div key={stat.label} style={{ textAlign: 'center' }}>
<div style={{ fontSize: 20, fontWeight: 700, color: '#fff' }}>
<span style={{ marginRight: 4 }}>{stat.icon}</span>{stat.value}
</div>
<div style={{ fontSize: 11, color: 'rgba(191,219,254,0.6)' }}>{stat.label}</div>
</div>
))}
</div>
</div>
</div>
</div>
{/* 服务入口 */}
<Card title={<span className="text-sm font-semibold">医疗服务</span>} size="small">
<Row gutter={[8, 8]}>
{services.map((service, index) => (
<Col xs={12} sm={8} md={4} key={index}>
<div
className="text-center rounded-lg p-3 cursor-pointer transition-all hover:scale-105 hover:shadow-md"
style={{ background: service.color }}
onClick={() => router.push(service.path)}
>
{service.icon}
<div className="mt-2">
<Text strong className="text-[13px]!">{service.title}</Text>
{/* 医疗服务入口 */}
<Card title={<span style={{ fontSize: 14, fontWeight: 600 }}>医疗服务</span>} size="small">
<Row gutter={[8, 8]}>
{services.map((service, index) => (
<Col xs={12} sm={8} md={4} key={index}>
<div
style={{
textAlign: 'center', borderRadius: 8, padding: 12,
cursor: 'pointer', transition: 'all 0.2s', background: service.bg,
}}
onClick={() => router.push(service.path)}
onMouseEnter={(e) => { e.currentTarget.style.transform = 'scale(1.03)'; e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.08)'; }}
onMouseLeave={(e) => { e.currentTarget.style.transform = 'scale(1)'; e.currentTarget.style.boxShadow = 'none'; }}
>
<div style={{ fontSize: 32, color: service.color, marginBottom: 8 }}>{service.icon}</div>
<div style={{ fontSize: 13, fontWeight: 600, color: '#1d2129' }}>{service.title}</div>
<div style={{ fontSize: 11, color: '#8c8c8c' }}>{service.desc}</div>
</div>
<Text type="secondary" className="text-[11px]!">{service.desc}</Text>
</Col>
))}
</Row>
</Card>
<Row gutter={[8, 8]}>
{/* 快捷入口 */}
<Col xs={24} sm={12}>
<Card title={<span style={{ fontSize: 14, fontWeight: 600 }}>快捷入口</span>} size="small" style={{ height: '100%' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
{quickLinks.map((link) => (
<div
key={link.title}
style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '10px 12px', borderRadius: 8, cursor: 'pointer',
border: '1px solid #e6f0fa', transition: 'all 0.2s',
}}
onClick={() => router.push(link.path)}
onMouseEnter={(e) => { e.currentTarget.style.background = '#f0f5ff'; e.currentTarget.style.borderColor = '#bbd4f0'; }}
onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.borderColor = '#e6f0fa'; }}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<div style={{
width: 32, height: 32, borderRadius: 8, display: 'flex',
alignItems: 'center', justifyContent: 'center', fontSize: 16,
color: link.color, background: `${link.color}15`,
}}>
{link.icon}
</div>
<span style={{ fontSize: 13, fontWeight: 500, color: '#1d2129' }}>{link.title}</span>
</div>
<RightOutlined style={{ fontSize: 12, color: '#bfbfbf' }} />
</div>
))}
</div>
</Col>
))}
</Row>
</Card>
</Card>
</Col>
{/* 科室导航 */}
<Card title={<span className="text-sm font-semibold">科室导航</span>} size="small">
<div className="flex flex-wrap gap-2">
{departments.map((dept) => (
<Button
key={dept}
size="small"
className="rounded-full!"
onClick={() => router.push(`/patient/doctors?department=${dept}`)}
>
{dept}
</Button>
))}
<Button type="link" size="small" onClick={() => router.push('/patient/doctors')}>
全部科室 &gt;
</Button>
</div>
</Card>
{/* 科室导航 */}
<Col xs={24} sm={12}>
<Card title={<span style={{ fontSize: 14, fontWeight: 600 }}>科室导航</span>} size="small" style={{ height: '100%' }}>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
{departments.map((dept) => (
<Tag
key={dept}
style={{ cursor: 'pointer', borderRadius: 16, padding: '2px 12px', fontSize: 12 }}
onClick={() => router.push(`/patient/doctors?department=${dept}`)}
>
{dept}
</Tag>
))}
<Button type="link" size="small" style={{ fontSize: 12, padding: 0 }}
onClick={() => router.push('/patient/doctors')}>
全部科室 &gt;
</Button>
</div>
</Card>
</Col>
</Row>
</div>
</div>
);
};
export default PatientHomePage;
......@@ -8,28 +8,47 @@ import {
SafetyCertificateOutlined,
EditOutlined,
IdcardOutlined,
VideoCameraOutlined,
FileTextOutlined,
FolderOpenOutlined,
HeartOutlined,
ShoppingCartOutlined,
RobotOutlined,
RightOutlined,
} from '@ant-design/icons';
import { useRouter } from 'next/navigation';
import { useUserStore } from '../../../store/userStore';
const { Title, Text } = Typography;
const { Text } = Typography;
const PatientProfilePage: React.FC = () => {
const { user } = useUserStore();
const router = useRouter();
const serviceLinks = [
{ icon: <VideoCameraOutlined />, title: '就诊记录', path: '/patient/consult', color: '#1890ff' },
{ icon: <FileTextOutlined />, title: '电子处方', path: '/patient/prescription', color: '#13c2c2' },
{ icon: <FolderOpenOutlined />, title: '健康档案', path: '/patient/health-records', color: '#52c41a' },
{ icon: <HeartOutlined />, title: '慢病管理', path: '/patient/chronic', color: '#eb2f96' },
{ icon: <ShoppingCartOutlined />, title: '药品配送', path: '/patient/pharmacy/order', color: '#fa8c16' },
{ icon: <RobotOutlined />, title: 'AI预问诊', path: '/patient/pre-consult', color: '#722ed1' },
];
return (
<div className="max-w-[1200px] mx-auto space-y-2">
<div style={{ maxWidth: 1200, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 8 }}>
{/* 个人信息卡片 */}
<Card size="small">
<Row gutter={12} align="middle">
<Col>
<Avatar size={56} src={user?.avatar} icon={<UserOutlined />} />
</Col>
<Col flex="auto">
<h4 className="text-sm font-bold m-0 mb-0.5">{user?.real_name || '未设置姓名'}</h4>
<span className="text-xs text-gray-400"><PhoneOutlined className="mr-1" />{user?.phone || '未绑定手机'}</span>
<div className="mt-1">
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
<Avatar size={56} src={user?.avatar} icon={<UserOutlined />}
style={{ backgroundColor: '#1890ff', flexShrink: 0 }} />
<div style={{ flex: 1 }}>
<h4 style={{ fontSize: 15, fontWeight: 700, margin: '0 0 4px', color: '#1d2129' }}>
{user?.real_name || '未设置姓名'}
</h4>
<div style={{ fontSize: 12, color: '#8c8c8c', marginBottom: 6 }}>
<PhoneOutlined style={{ marginRight: 4 }} />{user?.phone || '未绑定手机'}
</div>
<div style={{ display: 'flex', gap: 4 }}>
{user?.is_verified ? (
<Tag icon={<SafetyCertificateOutlined />} color="success">已实名</Tag>
) : (
......@@ -37,52 +56,91 @@ const PatientProfilePage: React.FC = () => {
)}
<Tag color="blue">患者</Tag>
</div>
</Col>
<Col>
<Button size="small" type="primary" icon={<EditOutlined />}>编辑资料</Button>
</Col>
</Row>
</div>
<Button size="small" type="primary" icon={<EditOutlined />}>编辑资料</Button>
</div>
</Card>
{/* 基本信息 */}
<Card title={<span className="text-xs font-semibold">基本信息</span>} size="small">
<Descriptions column={2} size="small">
<Descriptions.Item label="用户ID">{user?.id || '-'}</Descriptions.Item>
<Descriptions.Item label="手机">{user?.phone || '-'}</Descriptions.Item>
<Descriptions.Item label="真实姓名">{user?.real_name || '-'}</Descriptions.Item>
<Descriptions.Item label="注册时间">{user?.created_at || '-'}</Descriptions.Item>
</Descriptions>
</Card>
<Row gutter={[8, 8]}>
{/* 基本信息 */}
<Col xs={24} sm={12}>
<Card title={<span style={{ fontSize: 13, fontWeight: 600 }}>基本信息</span>} size="small" style={{ height: '100%' }}>
<Descriptions column={1} size="small">
<Descriptions.Item label="用户ID">
<Text copyable style={{ fontSize: 12 }}>{user?.id || '-'}</Text>
</Descriptions.Item>
<Descriptions.Item label="手机号">{user?.phone || '-'}</Descriptions.Item>
<Descriptions.Item label="真实姓名">{user?.real_name || '-'}</Descriptions.Item>
<Descriptions.Item label="注册时间">
{user?.created_at ? new Date(user.created_at).toLocaleDateString('zh-CN') : '-'}
</Descriptions.Item>
</Descriptions>
</Card>
</Col>
{/* 实名认证 */}
<Card title={<span className="text-xs font-semibold">实名认证</span>} size="small">
{user?.is_verified ? (
<div className="text-center py-4">
<div className="w-10 h-10 rounded-full bg-green-50 flex items-center justify-center mx-auto mb-2">
<SafetyCertificateOutlined className="text-xl text-green-500" />
</div>
<Text strong className="text-xs!">已完成实名认证</Text>
</div>
) : (
<div className="text-center py-4">
<div className="w-10 h-10 rounded-full bg-yellow-50 flex items-center justify-center mx-auto mb-2">
<IdcardOutlined className="text-xl text-yellow-500" />
</div>
<div className="text-xs text-gray-500 mb-2">完成实名认证后可享受完整的线上问诊服务</div>
<Button type="primary" size="small">去认证</Button>
</div>
)}
</Card>
{/* 实名认证 */}
<Col xs={24} sm={12}>
<Card title={<span style={{ fontSize: 13, fontWeight: 600 }}>实名认证</span>} size="small" style={{ height: '100%' }}>
{user?.is_verified ? (
<div style={{ textAlign: 'center', padding: '16px 0' }}>
<div style={{
width: 48, height: 48, borderRadius: '50%', backgroundColor: '#f6ffed',
display: 'flex', alignItems: 'center', justifyContent: 'center',
margin: '0 auto 8px', fontSize: 24, color: '#52c41a',
}}>
<SafetyCertificateOutlined />
</div>
<div style={{ fontSize: 13, fontWeight: 600, color: '#1d2129' }}>已完成实名认证</div>
<div style={{ fontSize: 11, color: '#8c8c8c', marginTop: 4 }}>可使用全部在线问诊服务</div>
</div>
) : (
<div style={{ textAlign: 'center', padding: '16px 0' }}>
<div style={{
width: 48, height: 48, borderRadius: '50%', backgroundColor: '#fffbe6',
display: 'flex', alignItems: 'center', justifyContent: 'center',
margin: '0 auto 8px', fontSize: 24, color: '#faad14',
}}>
<IdcardOutlined />
</div>
<div style={{ fontSize: 12, color: '#8c8c8c', marginBottom: 8 }}>
完成实名认证后可享受完整的线上问诊服务
</div>
<Button type="primary" size="small">去认证</Button>
</div>
)}
</Card>
</Col>
</Row>
{/* 快捷操作 */}
<Card title={<span className="text-xs font-semibold">更多服务</span>} size="small">
{/* 更多服务 */}
<Card title={<span style={{ fontSize: 13, fontWeight: 600 }}>更多服务</span>} size="small">
<Row gutter={[8, 8]}>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/consult')}>就诊记录</Button></Col>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/prescription')}>电子处方</Button></Col>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/health-records')}>健康档案</Button></Col>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/chronic')}>慢病管理</Button></Col>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/pharmacy/order')}>药品配送</Button></Col>
<Col span={8}><Button block size="small" onClick={() => router.push('/patient/pre-consult')}>AI预问诊</Button></Col>
{serviceLinks.map((link) => (
<Col xs={12} sm={8} md={4} key={link.title}>
<div
style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '10px 12px', borderRadius: 8, cursor: 'pointer',
border: '1px solid #e6f0fa', transition: 'all 0.2s',
}}
onClick={() => router.push(link.path)}
onMouseEnter={(e) => { e.currentTarget.style.background = '#f0f5ff'; e.currentTarget.style.borderColor = '#bbd4f0'; }}
onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.borderColor = '#e6f0fa'; }}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div style={{
width: 28, height: 28, borderRadius: 6, display: 'flex',
alignItems: 'center', justifyContent: 'center',
color: link.color, background: `${link.color}15`, fontSize: 14,
}}>
{link.icon}
</div>
<span style={{ fontSize: 12, fontWeight: 500, color: '#1d2129' }}>{link.title}</span>
</div>
<RightOutlined style={{ fontSize: 10, color: '#bfbfbf' }} />
</div>
</Col>
))}
</Row>
</Card>
</div>
......@@ -90,4 +148,3 @@ const PatientProfilePage: React.FC = () => {
};
export default PatientProfilePage;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment