添加接口

- 体检客户列表
- 体检进度详情
- 客户详情
This commit is contained in:
xianyi
2025-12-10 17:28:15 +08:00
parent f4d5c085ee
commit 0efc4c186e
5 changed files with 428 additions and 71 deletions

View File

@@ -1,47 +1,97 @@
import { useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useOutletContext } from 'react-router-dom';
import type { ExamClient, ExamModalTab } from '../data/mockData';
import { EXAM_CLIENTS, EXAM_TAGS } from '../data/mockData';
import { EXAM_TAGS } from '../data/mockData';
import { ExamSection } from '../components/exam/ExamSection';
import { ExamModal } from '../components/exam/ExamModal';
import type { MainLayoutContext } from '../layouts/MainLayout';
import { getPhysicalExamCustomerList } from '../api';
export const ExamPage = () => {
const { search } = useOutletContext<MainLayoutContext>();
const [examSelectedId, setExamSelectedId] = useState<string>('A001');
const [clients, setClients] = useState<ExamClient[]>([]);
const [examSelectedId, setExamSelectedId] = useState<string>('');
const [examPanelTab, setExamPanelTab] = useState<ExamModalTab>('detail');
const [examModalOpen, setExamModalOpen] = useState(false);
const [examFilterTag, setExamFilterTag] = useState<(typeof EXAM_TAGS)[number]>('全部');
const filteredClients = useMemo(() => {
return EXAM_CLIENTS.filter((c) => (c.name + c.packageName + c.id).toLowerCase().includes(search.trim().toLowerCase())).filter(
(c) => {
switch (examFilterTag) {
case '上午':
return c.timeSlot === '午';
case '下午':
return c.timeSlot === '下午';
case '高客':
return c.vipType === '客';
case '普客':
return c.vipType === '普客';
case '已登记':
return c.signStatus === '登记';
case '未登记':
return c.signStatus !== '已登记';
case '散客':
return c.customerType === '客';
case '团客':
return c.customerType === '团客';
default:
return true;
}
},
);
}, [search, examFilterTag]);
// 将筛选标签映射为接口 filter_type
const filterType = useMemo(() => {
switch (examFilterTag) {
case '上午':
return 2;
case '午':
return 3;
case '高客':
return 4;
case '客':
return 5;
case '已登记':
return 6;
case '登记':
return 7;
case '散客':
return 8;
case '客':
return 9;
default:
return 1; // 全部
}
}, [examFilterTag]);
const selectedExamClient: ExamClient = EXAM_CLIENTS.find((c) => c.id === examSelectedId) || EXAM_CLIENTS[0];
// 从接口拉取体检客户列表
useEffect(() => {
const payload = {
customer_name: search.trim() || undefined,
phone: undefined,
id_no: undefined,
filter_type: filterType,
};
getPhysicalExamCustomerList(payload)
.then((res) => {
const list = res.Data || [];
const mapped: ExamClient[] = list.map((item) => {
// 简单映射为现有 UI 使用的字段
const statusName = item.physical_exam_status_name || '';
const signStatus = item.is_register === 1 ? '已登记' : '未登记';
const customerType = item.customer_type === 1 ? '团客' : '散客';
const vipType = item.is_vip === 1 ? '高客' : '普客';
return {
id: String(item.physical_exam_id ?? ''),
name: item.customer_name || '未知客户',
gender: '男', // 后端未提供,默认填充
age: 0,
level: item.member_level || (item.is_vip === 1 ? 'VIP' : '普通'),
packageName: item.package_name || '未提供套餐',
status: statusName || '未开始',
elapsed: '',
checkedItems: [],
pendingItems: [],
timeSlot: '上午',
vipType,
signStatus,
customerType,
guidePrinted: item.is_print === 1,
addonCount: item.add_item_count ?? 0,
};
});
setClients(mapped);
if (mapped.length && !examSelectedId) {
setExamSelectedId(mapped[0].id);
} else if (mapped.length === 0) {
setExamSelectedId('');
}
})
.catch((err) => {
console.error('获取体检客户列表失败', err);
});
}, [search, filterType, examSelectedId]);
const selectedExamClient: ExamClient | undefined = useMemo(
() => clients.find((c) => c.id === examSelectedId) || clients[0],
[clients, examSelectedId],
);
const handleOpenModal = (id: string, tab: ExamModalTab) => {
setExamSelectedId(id);
@@ -51,13 +101,15 @@ export const ExamPage = () => {
return (
<>
<ExamSection
filteredClients={filteredClients}
selectedExamClient={selectedExamClient}
examFilterTag={examFilterTag}
onFilterChange={setExamFilterTag}
onOpenModal={handleOpenModal}
/>
{selectedExamClient && (
<ExamSection
filteredClients={clients}
selectedExamClient={selectedExamClient}
examFilterTag={examFilterTag}
onFilterChange={setExamFilterTag}
onOpenModal={handleOpenModal}
/>
)}
{examModalOpen && (
<ExamModal