fix(health): 全链路流通性验证修复
- 创建 stub migration 解决缺失文件报错 - PatientList/PatientDetail: DatePicker dayjs 对象序列化为 YYYY-MM-DD - AppointmentList: 预约类型与后端验证对齐(outpatient/recheck/health_checkup/consultation/dialysis) - AppointmentList: 医生字段改为必填(后端 CAS 排班要求), destroyOnClose→destroyOnHidden - Home.tsx: 补充审计日志 action 翻译(created/login_failed 等) 全链路验证通过: 医生CRUD→排班→预约创建+状态流转→随访生命周期→咨询会话+消息→患者详情+健康数据
This commit is contained in:
@@ -72,8 +72,8 @@ function StatValue({ value, loading }: { value: number; loading: boolean }) {
|
||||
}
|
||||
|
||||
const ACTION_LABELS: Record<string, string> = {
|
||||
create: '创建', update: '更新', delete: '删除',
|
||||
login: '登录', user_login: '登录', 'user.login': '登录',
|
||||
create: '创建', created: '创建', update: '更新', updated: '更新', delete: '删除', deleted: '删除',
|
||||
login: '登录', login_failed: '登录失败', user_login: '登录', 'user.login': '登录',
|
||||
'user.create': '创建', 'user.update': '更新', 'user.delete': '删除',
|
||||
'role.create': '创建', 'role.update': '更新', 'role.delete': '删除',
|
||||
'patient.create': '创建', 'patient.update': '更新',
|
||||
|
||||
@@ -28,16 +28,18 @@ import { DoctorSelect } from './components/DoctorSelect';
|
||||
/** 预约类型选项 */
|
||||
const APPOINTMENT_TYPE_OPTIONS = [
|
||||
{ value: 'outpatient', label: '门诊' },
|
||||
{ value: 'physical_checkup', label: '体检' },
|
||||
{ value: 'follow_up', label: '随访' },
|
||||
{ value: 'recheck', label: '复诊' },
|
||||
{ value: 'health_checkup', label: '体检' },
|
||||
{ value: 'consultation', label: '咨询' },
|
||||
{ value: 'dialysis', label: '透析' },
|
||||
];
|
||||
|
||||
const APPOINTMENT_TYPE_MAP: Record<string, string> = {
|
||||
outpatient: '门诊',
|
||||
physical_checkup: '体检',
|
||||
follow_up: '随访',
|
||||
recheck: '复诊',
|
||||
health_checkup: '体检',
|
||||
consultation: '咨询',
|
||||
dialysis: '透析',
|
||||
};
|
||||
|
||||
/** 状态筛选选项 */
|
||||
@@ -138,6 +140,10 @@ export default function AppointmentList() {
|
||||
message.warning('请选择患者');
|
||||
return;
|
||||
}
|
||||
if (!selectedDoctorId) {
|
||||
message.warning('请选择医护');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const req: CreateAppointmentReq = {
|
||||
patient_id: selectedPatientId,
|
||||
@@ -312,7 +318,7 @@ export default function AppointmentList() {
|
||||
setSelectedDoctorId(undefined);
|
||||
}}
|
||||
onOk={() => form.submit()}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
width={560}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
@@ -323,11 +329,11 @@ export default function AppointmentList() {
|
||||
placeholder="搜索选择患者"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="医护">
|
||||
<Form.Item label="医护" required>
|
||||
<DoctorSelect
|
||||
value={selectedDoctorId}
|
||||
onChange={(val) => setSelectedDoctorId(val)}
|
||||
placeholder="搜索选择医护(可选)"
|
||||
placeholder="搜索选择医护"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Row gutter={16}>
|
||||
|
||||
@@ -64,7 +64,7 @@ export default function PatientDetail() {
|
||||
const handleEdit = async (values: {
|
||||
name?: string;
|
||||
gender?: string;
|
||||
birth_date?: string;
|
||||
birth_date?: unknown;
|
||||
blood_type?: string;
|
||||
id_number?: string;
|
||||
allergy_history?: string;
|
||||
@@ -74,9 +74,15 @@ export default function PatientDetail() {
|
||||
notes?: string;
|
||||
}) => {
|
||||
if (!patient) return;
|
||||
const formatted = {
|
||||
...values,
|
||||
birth_date: values.birth_date && typeof values.birth_date === 'object' && 'format' in (values.birth_date as object)
|
||||
? (values.birth_date as { format: (f: string) => string }).format('YYYY-MM-DD')
|
||||
: (values.birth_date as string | undefined),
|
||||
};
|
||||
try {
|
||||
const req: UpdatePatientReq & { version: number } = {
|
||||
...values,
|
||||
...formatted,
|
||||
version: patient.version,
|
||||
};
|
||||
await patientApi.update(patient.id, req);
|
||||
|
||||
@@ -77,22 +77,28 @@ export default function PatientList() {
|
||||
const handleCreateOrEdit = async (values: {
|
||||
name: string;
|
||||
gender?: string;
|
||||
birth_date?: string;
|
||||
birth_date?: unknown;
|
||||
blood_type?: string;
|
||||
id_number?: string;
|
||||
allergy_history?: string;
|
||||
notes?: string;
|
||||
}) => {
|
||||
const formatted = {
|
||||
...values,
|
||||
birth_date: values.birth_date && typeof values.birth_date === 'object' && 'format' in (values.birth_date as object)
|
||||
? (values.birth_date as { format: (f: string) => string }).format('YYYY-MM-DD')
|
||||
: (values.birth_date as string | undefined),
|
||||
};
|
||||
try {
|
||||
if (editingPatient) {
|
||||
const req: UpdatePatientReq & { version: number } = {
|
||||
...values,
|
||||
...formatted,
|
||||
version: (editingPatient as PatientListItem & { version?: number }).version ?? 0,
|
||||
};
|
||||
await patientApi.update(editingPatient.id, req);
|
||||
message.success('患者信息更新成功');
|
||||
} else {
|
||||
const req: CreatePatientReq = values;
|
||||
const req: CreatePatientReq = formatted;
|
||||
await patientApi.create(req);
|
||||
message.success('患者创建成功');
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ mod m20260424_000046_health_constraints_fix;
|
||||
mod m20260424_000047_health_index_fix;
|
||||
mod m20260425_000048_add_patient_id_number_hash;
|
||||
mod m20260425_000049_widen_patient_id_number;
|
||||
mod m20260425_00050_add_doctor_name_column;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
@@ -105,6 +106,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260424_000047_health_index_fix::Migration),
|
||||
Box::new(m20260425_000048_add_patient_id_number_hash::Migration),
|
||||
Box::new(m20260425_000049_widen_patient_id_number::Migration),
|
||||
Box::new(m20260425_00050_add_doctor_name_column::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// 已在主库手动执行,此处为空壳保持迁移历史一致性
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user