完善B1 面板
This commit is contained in:
@@ -40,6 +40,8 @@ import type {
|
|||||||
VerificationCodePhoneResponse,
|
VerificationCodePhoneResponse,
|
||||||
InputUserOwnedMenus,
|
InputUserOwnedMenus,
|
||||||
UserOwnedMenusResponse,
|
UserOwnedMenusResponse,
|
||||||
|
InputB1ServiceBoard,
|
||||||
|
B1ServiceBoardResponse,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -332,3 +334,15 @@ export const getUserOwnedMenus = (
|
|||||||
).then(res => res.data);
|
).then(res => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B1服务看板
|
||||||
|
*/
|
||||||
|
export const getB1ServiceBoard = (
|
||||||
|
data: InputB1ServiceBoard = {}
|
||||||
|
): Promise<B1ServiceBoardResponse> => {
|
||||||
|
return request.post<B1ServiceBoardResponse>(
|
||||||
|
`${MEDICAL_EXAM_BASE_PATH}/b1-service-board`,
|
||||||
|
data
|
||||||
|
).then(res => res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -708,3 +708,39 @@ export interface OutputUserOwnedMenus {
|
|||||||
*/
|
*/
|
||||||
export type UserOwnedMenusResponse = CommonActionResult<OutputUserOwnedMenus>;
|
export type UserOwnedMenusResponse = CommonActionResult<OutputUserOwnedMenus>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B1服务点信息
|
||||||
|
*/
|
||||||
|
export interface B1ServiceInfo {
|
||||||
|
/** 科室名称 */
|
||||||
|
dept_name?: string | null;
|
||||||
|
/** 医生名称 */
|
||||||
|
doctor_name?: string | null;
|
||||||
|
/** 已检部位数 */
|
||||||
|
exam_part_count?: number | null;
|
||||||
|
/** 总时长(分钟) */
|
||||||
|
total_duration_minutes?: number | null;
|
||||||
|
/** 平均时长(分钟) */
|
||||||
|
average_duration_minutes?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B1服务看板入参
|
||||||
|
*/
|
||||||
|
export interface InputB1ServiceBoard {
|
||||||
|
// 空对象,无需参数
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B1服务看板出参
|
||||||
|
*/
|
||||||
|
export interface OutputB1ServiceBoard {
|
||||||
|
/** B1服务点信息列表 */
|
||||||
|
b1_service_info_list: B1ServiceInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B1服务看板响应
|
||||||
|
*/
|
||||||
|
export type B1ServiceBoardResponse = CommonActionResult<OutputB1ServiceBoard>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { getRevenueStatistics, getTodayExamStatistics, getUserOwnedMenus } from '../../api';
|
import { getRevenueStatistics, getTodayExamStatistics, getUserOwnedMenus, getB1ServiceBoard } from '../../api';
|
||||||
import { B1_ROWS, B1_SUMMARY, NORTH3_ROWS, NORTH3_SUMMARY } from '../../data/mockData';
|
import type { B1ServiceInfo } from '../../api/types';
|
||||||
|
import { NORTH3_ROWS, NORTH3_SUMMARY } from '../../data/mockData';
|
||||||
import { Card, CardContent, CardHeader, InfoCard } from '../ui';
|
import { Card, CardContent, CardHeader, InfoCard } from '../ui';
|
||||||
|
|
||||||
const APP_ID = 'b2b49e91d21446aeb14579930f732985';
|
const APP_ID = 'b2b49e91d21446aeb14579930f732985';
|
||||||
@@ -25,6 +26,8 @@ export const HomeSection = () => {
|
|||||||
{ label: '当日缺口', value: '¥ 0' },
|
{ label: '当日缺口', value: '¥ 0' },
|
||||||
]);
|
]);
|
||||||
const [showRevenueStats, setShowRevenueStats] = useState(false);
|
const [showRevenueStats, setShowRevenueStats] = useState(false);
|
||||||
|
const [b1ServiceList, setB1ServiceList] = useState<B1ServiceInfo[]>([]);
|
||||||
|
const [b1Loading, setB1Loading] = useState(false);
|
||||||
|
|
||||||
const currencyFormatter = useMemo(() => new Intl.NumberFormat('zh-CN', {
|
const currencyFormatter = useMemo(() => new Intl.NumberFormat('zh-CN', {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
@@ -98,6 +101,32 @@ export const HomeSection = () => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setB1Loading(true);
|
||||||
|
getB1ServiceBoard({})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.Status === 200 && res.Data) {
|
||||||
|
setB1ServiceList(res.Data.b1_service_info_list || []);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('获取B1服务看板失败', err);
|
||||||
|
setB1ServiceList([]);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setB1Loading(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 计算B1汇总信息
|
||||||
|
const b1Summary = useMemo(() => {
|
||||||
|
const totalClients = b1ServiceList.length;
|
||||||
|
// 由于接口没有返回"在检"和"待检"数据,这里暂时使用0
|
||||||
|
const waiting = 0;
|
||||||
|
const inExam = 0;
|
||||||
|
return { totalClients, waiting, inExam };
|
||||||
|
}, [b1ServiceList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='space-y-6'>
|
<div className='space-y-6'>
|
||||||
<Card>
|
<Card>
|
||||||
@@ -129,42 +158,44 @@ export const HomeSection = () => {
|
|||||||
<CardHeader>B1 服务看板</CardHeader>
|
<CardHeader>B1 服务看板</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className='grid grid-cols-3 gap-3 mb-3'>
|
<div className='grid grid-cols-3 gap-3 mb-3'>
|
||||||
<InfoCard label='客户总数' value={B1_SUMMARY.totalClients} />
|
<InfoCard label='客户总数' value={b1Summary.totalClients} />
|
||||||
<InfoCard label='待检人数' value={B1_SUMMARY.waiting} />
|
<InfoCard label='待检人数' value={b1Summary.waiting} />
|
||||||
<InfoCard label='已检人数' value={B1_SUMMARY.inExam} />
|
<InfoCard label='已检人数' value={b1Summary.inExam} />
|
||||||
</div>
|
</div>
|
||||||
<table className='w-full text-xs'>
|
{b1Loading ? (
|
||||||
<thead>
|
<div className='text-center text-gray-500 py-4'>加载中...</div>
|
||||||
<tr className='text-gray-500 border-b'>
|
) : b1ServiceList.length === 0 ? (
|
||||||
<th className='py-2 text-left'>科室</th>
|
<div className='text-center text-gray-500 py-4'>暂无数据</div>
|
||||||
<th className='py-2 text-left'>医生</th>
|
) : (
|
||||||
<th className='py-2 text-right'>已检人数</th>
|
<table className='w-full text-xs'>
|
||||||
<th className='py-2 text-right'>已检部位数</th>
|
<thead>
|
||||||
<th className='py-2 text-right'>总时长</th>
|
<tr className='text-gray-500 border-b'>
|
||||||
<th className='py-2 text-right'>平均时长</th>
|
<th className='py-2 text-left'>科室</th>
|
||||||
<th className='py-2 text-right'>在检</th>
|
<th className='py-2 text-left'>医生</th>
|
||||||
<th className='py-2 text-right'>待检</th>
|
<th className='py-2 text-right'>已检人数</th>
|
||||||
</tr>
|
<th className='py-2 text-right'>已检部位数</th>
|
||||||
</thead>
|
<th className='py-2 text-right'>总时长</th>
|
||||||
<tbody>
|
<th className='py-2 text-right'>平均时长</th>
|
||||||
{B1_ROWS.map(([dept, doctor, done, inExam, waiting, avg]) => {
|
<th className='py-2 text-right'>在检</th>
|
||||||
const parts = done * 3;
|
<th className='py-2 text-right'>待检</th>
|
||||||
const totalTime = done * avg;
|
</tr>
|
||||||
return (
|
</thead>
|
||||||
<tr key={dept} className='border-b last:border-b-0'>
|
<tbody>
|
||||||
<td className='py-2'>{dept}</td>
|
{b1ServiceList.map((item, index) => (
|
||||||
<td className='py-2'>{doctor}</td>
|
<tr key={`${item.dept_name}-${item.doctor_name}-${index}`} className='border-b last:border-b-0'>
|
||||||
<td className='py-2 text-right'>{done}</td>
|
<td className='py-2'>{item.dept_name || '-'}</td>
|
||||||
<td className='py-2 text-right'>{parts}</td>
|
<td className='py-2'>{item.doctor_name || '-'}</td>
|
||||||
<td className='py-2 text-right'>{totalTime}</td>
|
<td className='py-2 text-right'>-</td>
|
||||||
<td className='py-2 text-right'>{avg}</td>
|
<td className='py-2 text-right'>{item.exam_part_count ?? '-'}</td>
|
||||||
<td className='py-2 text-right'>{inExam}</td>
|
<td className='py-2 text-right'>{item.total_duration_minutes ?? '-'}</td>
|
||||||
<td className='py-2 text-right'>{waiting}</td>
|
<td className='py-2 text-right'>{item.average_duration_minutes ?? '-'}</td>
|
||||||
|
<td className='py-2 text-right'>-</td>
|
||||||
|
<td className='py-2 text-right'>-</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
))}
|
||||||
})}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user