fix(miniprogram): 修复 API 接口字段对齐 — 33 接口端到端验证
P0: submitRecord() 路径修正 POST /follow-up-records → POST /follow-up-tasks/{id}/records
+ 请求体从 {task_id, content:{text}} 改为 {result, patient_condition, executed_date}
P1: ConsultationSession.subject/last_message 改为可选(后端暂不返回)
P1: Appointment.department 改为可选(后端未 JOIN 医生表)
P1: FollowUpRecord 结构对齐后端扁平字段(executed_date/result/medical_advice 等)
P2: Article 增加 status 可选字段
This commit is contained in:
@@ -97,34 +97,53 @@ export default function AppointmentDetail() {
|
||||
<View className='header-placeholder' />
|
||||
</View>
|
||||
|
||||
{/* 状态卡片 */}
|
||||
<View className='status-card'>
|
||||
<View className={`status-badge ${status.className}`}>
|
||||
<Text className='status-badge-text'>{status.label}</Text>
|
||||
<View className={`status-tag ${status.className}`}>
|
||||
<Text className='status-tag-text'>{status.label}</Text>
|
||||
</View>
|
||||
<Text className='status-doctor'>{appointment.doctor_name}</Text>
|
||||
<Text className='status-dept'>{appointment.department}</Text>
|
||||
<Text className='status-dept'>{appointment.department || ''}</Text>
|
||||
</View>
|
||||
|
||||
{/* 预约信息 */}
|
||||
<View className='info-section'>
|
||||
<Text className='section-title'>预约信息</Text>
|
||||
|
||||
<View className='info-item'>
|
||||
<Text className='info-label'>就诊人</Text>
|
||||
<View className='info-label-wrap'>
|
||||
<Text className='info-icon-serif'>患</Text>
|
||||
<Text className='info-label'>就诊人</Text>
|
||||
</View>
|
||||
<Text className='info-value'>{appointment.patient_name}</Text>
|
||||
</View>
|
||||
|
||||
<View className='info-item'>
|
||||
<Text className='info-label'>就诊日期</Text>
|
||||
<Text className='info-value'>{appointment.appointment_date}</Text>
|
||||
<View className='info-label-wrap'>
|
||||
<Text className='info-icon-serif'>日</Text>
|
||||
<Text className='info-label'>就诊日期</Text>
|
||||
</View>
|
||||
<Text className='info-value info-date'>{appointment.appointment_date}</Text>
|
||||
</View>
|
||||
|
||||
<View className='info-item'>
|
||||
<Text className='info-label'>就诊时段</Text>
|
||||
<Text className='info-value'>{appointment.start_time} - {appointment.end_time}</Text>
|
||||
<View className='info-label-wrap'>
|
||||
<Text className='info-icon-serif'>时</Text>
|
||||
<Text className='info-label'>就诊时段</Text>
|
||||
</View>
|
||||
<Text className='info-value info-time'>{appointment.start_time} - {appointment.end_time}</Text>
|
||||
</View>
|
||||
|
||||
<View className='info-item'>
|
||||
<Text className='info-label'>预约单号</Text>
|
||||
<View className='info-label-wrap'>
|
||||
<Text className='info-icon-serif'>号</Text>
|
||||
<Text className='info-label'>预约单号</Text>
|
||||
</View>
|
||||
<Text className='info-value info-id'>{appointment.id}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 温馨提示 */}
|
||||
{(appointment.status === 'pending' || appointment.status === 'confirmed') && (
|
||||
<View className='tips-card'>
|
||||
<Text className='tips-title'>温馨提示</Text>
|
||||
@@ -132,6 +151,7 @@ export default function AppointmentDetail() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 取消按钮 */}
|
||||
{canCancel && (
|
||||
<View className='bottom-bar'>
|
||||
<View
|
||||
|
||||
@@ -14,6 +14,16 @@ const STATUS_MAP: Record<string, { label: string; className: string }> = {
|
||||
completed: { label: '已完成', className: 'tag-completed' },
|
||||
};
|
||||
|
||||
// 科室首字映射(用于衬线图标)
|
||||
const DEPT_INITIAL: Record<string, string> = {
|
||||
'内科': '内',
|
||||
'外科': '外',
|
||||
'妇科': '妇',
|
||||
'儿科': '儿',
|
||||
'体检中心': '检',
|
||||
'中医科': '中',
|
||||
};
|
||||
|
||||
export default function AppointmentList() {
|
||||
const [appointments, setAppointments] = useState<Appointment[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
@@ -71,16 +81,21 @@ export default function AppointmentList() {
|
||||
return STATUS_MAP[status] || { label: status, className: 'tag-pending' };
|
||||
};
|
||||
|
||||
const getDeptInitial = (dept: string) => {
|
||||
return DEPT_INITIAL[dept] || dept.charAt(0);
|
||||
};
|
||||
|
||||
return (
|
||||
<View className='appointment-page'>
|
||||
{/* 页面标题 */}
|
||||
<View className='page-header'>
|
||||
<Text className='page-title'>预约挂号</Text>
|
||||
<Text className='page-subtitle'>Appointment</Text>
|
||||
</View>
|
||||
|
||||
{/* 预约列表 */}
|
||||
{appointments.length === 0 && !loading ? (
|
||||
<EmptyState icon='📋' text='暂无预约记录' hint='点击下方按钮新建预约' />
|
||||
<EmptyState text='暂无预约记录' hint='点击下方按钮新建预约' />
|
||||
) : (
|
||||
<View className='appointment-list'>
|
||||
{appointments.map((item) => {
|
||||
@@ -92,22 +107,34 @@ export default function AppointmentList() {
|
||||
onClick={() => goDetail(item.id)}
|
||||
>
|
||||
<View className='card-top'>
|
||||
<View className='doctor-info'>
|
||||
<Text className='doctor-name'>{item.doctor_name}</Text>
|
||||
<Text className='department'>{item.department}</Text>
|
||||
<View className='doctor-section'>
|
||||
<View className='dept-initial'>
|
||||
<Text className='dept-initial-text'>{getDeptInitial(item.department || '')}</Text>
|
||||
</View>
|
||||
<View className='doctor-info'>
|
||||
<Text className='doctor-name'>{item.doctor_name}</Text>
|
||||
<View className='dept-tag'>
|
||||
<Text className='dept-tag-text'>{item.department || ''}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className={`status-tag ${tag.className}`}>
|
||||
<Text className='status-tag-text'>{tag.label}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className='card-divider' />
|
||||
<View className='card-bottom'>
|
||||
<View className='info-row'>
|
||||
<Text className='info-icon'>📅</Text>
|
||||
<View className='info-icon-wrap'>
|
||||
<Text className='info-icon-serif'>日</Text>
|
||||
</View>
|
||||
<Text className='info-text'>{item.appointment_date}</Text>
|
||||
</View>
|
||||
<View className='info-row'>
|
||||
<Text className='info-icon'>🕐</Text>
|
||||
<Text className='info-text'>{item.start_time} - {item.end_time}</Text>
|
||||
<View className='info-icon-wrap'>
|
||||
<Text className='info-icon-serif'>时</Text>
|
||||
</View>
|
||||
<Text className='info-text info-time'>{item.start_time} - {item.end_time}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -124,7 +151,7 @@ export default function AppointmentList() {
|
||||
|
||||
{/* 底部悬浮按钮 */}
|
||||
<View className='fab-btn' onClick={goCreate}>
|
||||
<Text className='fab-text'>+ 新建预约</Text>
|
||||
<Text className='fab-text'>新建预约</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -38,9 +38,9 @@ export default function FollowUpDetail() {
|
||||
}
|
||||
setSubmitting(true);
|
||||
try {
|
||||
await submitRecord({
|
||||
task_id: id,
|
||||
content: { text: content.trim() },
|
||||
await submitRecord(id, {
|
||||
result: content.trim(),
|
||||
patient_condition: content.trim(),
|
||||
});
|
||||
Taro.showToast({ title: '提交成功', icon: 'success' });
|
||||
trackEvent('followup_submit', { task_id: id });
|
||||
|
||||
@@ -4,7 +4,7 @@ export interface Appointment {
|
||||
id: string;
|
||||
patient_name: string;
|
||||
doctor_name: string;
|
||||
department: string;
|
||||
department?: string;
|
||||
appointment_date: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface Article {
|
||||
published_at?: string;
|
||||
author?: string;
|
||||
view_count?: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface ArticleCategory {
|
||||
|
||||
@@ -6,8 +6,8 @@ export interface ConsultationSession {
|
||||
doctor_id: string | null;
|
||||
consultation_type: string;
|
||||
status: string;
|
||||
subject: string | null;
|
||||
last_message: string | null;
|
||||
subject?: string | null;
|
||||
last_message?: string | null;
|
||||
last_message_at: string | null;
|
||||
unread_count_patient: number;
|
||||
created_at: string;
|
||||
|
||||
@@ -11,15 +11,15 @@ export interface FollowUpTask {
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface FollowUpContent {
|
||||
text: string;
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface FollowUpRecord {
|
||||
id: string;
|
||||
task_id: string;
|
||||
content: FollowUpContent;
|
||||
executed_by?: string;
|
||||
executed_date: string;
|
||||
result?: string;
|
||||
patient_condition?: string;
|
||||
medical_advice?: string;
|
||||
next_follow_up_date?: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,16 @@ export async function getTaskDetail(id: string) {
|
||||
return api.get<FollowUpTask>(`/health/follow-up-tasks/${id}`);
|
||||
}
|
||||
|
||||
export async function submitRecord(data: { task_id: string; content: FollowUpContent }) {
|
||||
return api.post<FollowUpRecord>('/health/follow-up-records', data);
|
||||
export async function submitRecord(taskId: string, data: {
|
||||
result?: string;
|
||||
patient_condition?: string;
|
||||
medical_advice?: string;
|
||||
next_follow_up_date?: string;
|
||||
}) {
|
||||
return api.post<FollowUpRecord>(`/health/follow-up-tasks/${taskId}/records`, {
|
||||
...data,
|
||||
executed_date: new Date().toISOString().slice(0, 10),
|
||||
});
|
||||
}
|
||||
|
||||
export async function listRecords(taskId?: string) {
|
||||
|
||||
Reference in New Issue
Block a user