完善北3面板
This commit is contained in:
@@ -42,6 +42,8 @@ import type {
|
|||||||
UserOwnedMenusResponse,
|
UserOwnedMenusResponse,
|
||||||
InputB1ServiceBoard,
|
InputB1ServiceBoard,
|
||||||
B1ServiceBoardResponse,
|
B1ServiceBoardResponse,
|
||||||
|
InputNorth3ServiceBoard,
|
||||||
|
North3ServiceBoardResponse,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,3 +348,15 @@ export const getB1ServiceBoard = (
|
|||||||
).then(res => res.data);
|
).then(res => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北3服务看板
|
||||||
|
*/
|
||||||
|
export const getNorth3ServiceBoard = (
|
||||||
|
data: InputNorth3ServiceBoard = {}
|
||||||
|
): Promise<North3ServiceBoardResponse> => {
|
||||||
|
return request.post<North3ServiceBoardResponse>(
|
||||||
|
`${MEDICAL_EXAM_BASE_PATH}/north3-service-board`,
|
||||||
|
data
|
||||||
|
).then(res => res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -744,3 +744,43 @@ export interface OutputB1ServiceBoard {
|
|||||||
*/
|
*/
|
||||||
export type B1ServiceBoardResponse = CommonActionResult<OutputB1ServiceBoard>;
|
export type B1ServiceBoardResponse = CommonActionResult<OutputB1ServiceBoard>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北3服务点信息
|
||||||
|
*/
|
||||||
|
export interface North3ServiceInfo {
|
||||||
|
/** 家医名称 */
|
||||||
|
family_doctor_name?: string | null;
|
||||||
|
/** 面诊率 */
|
||||||
|
face_to_face_rate: number;
|
||||||
|
/** 分配客户数 */
|
||||||
|
assigned_customer_count: number;
|
||||||
|
/** 面诊数 */
|
||||||
|
face_to_face_count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北3服务看板入参
|
||||||
|
*/
|
||||||
|
export interface InputNorth3ServiceBoard {
|
||||||
|
// 空对象,无需参数
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北3服务看板出参
|
||||||
|
*/
|
||||||
|
export interface OutputNorth3ServiceBoard {
|
||||||
|
/** 今日家医数 */
|
||||||
|
today_family_doctor_count: number;
|
||||||
|
/** 分配客户数 */
|
||||||
|
assigned_customer_count: number;
|
||||||
|
/** 面诊数 */
|
||||||
|
face_to_face_count: number;
|
||||||
|
/** 北3服务点信息列表 */
|
||||||
|
north3_service_list: North3ServiceInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北3服务看板响应
|
||||||
|
*/
|
||||||
|
export type North3ServiceBoardResponse = CommonActionResult<OutputNorth3ServiceBoard>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { getRevenueStatistics, getTodayExamStatistics, getUserOwnedMenus, getB1ServiceBoard } from '../../api';
|
import { getRevenueStatistics, getTodayExamStatistics, getUserOwnedMenus, getB1ServiceBoard, getNorth3ServiceBoard } from '../../api';
|
||||||
import type { B1ServiceInfo } from '../../api/types';
|
import type { B1ServiceInfo, OutputNorth3ServiceBoard } 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';
|
||||||
@@ -28,6 +27,8 @@ export const HomeSection = () => {
|
|||||||
const [showRevenueStats, setShowRevenueStats] = useState(false);
|
const [showRevenueStats, setShowRevenueStats] = useState(false);
|
||||||
const [b1ServiceList, setB1ServiceList] = useState<B1ServiceInfo[]>([]);
|
const [b1ServiceList, setB1ServiceList] = useState<B1ServiceInfo[]>([]);
|
||||||
const [b1Loading, setB1Loading] = useState(false);
|
const [b1Loading, setB1Loading] = useState(false);
|
||||||
|
const [north3Data, setNorth3Data] = useState<OutputNorth3ServiceBoard | null>(null);
|
||||||
|
const [north3Loading, setNorth3Loading] = useState(false);
|
||||||
|
|
||||||
const currencyFormatter = useMemo(() => new Intl.NumberFormat('zh-CN', {
|
const currencyFormatter = useMemo(() => new Intl.NumberFormat('zh-CN', {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
@@ -127,6 +128,23 @@ export const HomeSection = () => {
|
|||||||
return { totalClients, waiting, inExam };
|
return { totalClients, waiting, inExam };
|
||||||
}, [b1ServiceList]);
|
}, [b1ServiceList]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNorth3Loading(true);
|
||||||
|
getNorth3ServiceBoard({})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.Status === 200 && res.Data) {
|
||||||
|
setNorth3Data(res.Data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('获取北3服务看板失败', err);
|
||||||
|
setNorth3Data(null);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setNorth3Loading(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='space-y-6'>
|
<div className='space-y-6'>
|
||||||
<Card>
|
<Card>
|
||||||
@@ -203,30 +221,43 @@ export const HomeSection = () => {
|
|||||||
<CardHeader>北3服务看板</CardHeader>
|
<CardHeader>北3服务看板</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={NORTH3_SUMMARY.totalDoctor} />
|
<InfoCard label='今日家医数' value={north3Data?.today_family_doctor_count ?? 0} />
|
||||||
<InfoCard label='分配客户数' value={NORTH3_SUMMARY.totalAssigned} />
|
<InfoCard label='分配客户数' value={north3Data?.assigned_customer_count ?? 0} />
|
||||||
<InfoCard label='面诊数' value={NORTH3_SUMMARY.consult} />
|
<InfoCard label='面诊数' value={north3Data?.face_to_face_count ?? 0} />
|
||||||
</div>
|
</div>
|
||||||
<table className='w-full text-xs'>
|
{north3Loading ? (
|
||||||
<thead>
|
<div className='text-center text-gray-500 py-4'>加载中...</div>
|
||||||
<tr className='text-gray-500 border-b'>
|
) : !north3Data || north3Data.north3_service_list.length === 0 ? (
|
||||||
<th className='py-2 text-left'>家医</th>
|
<div className='text-center text-gray-500 py-4'>暂无数据</div>
|
||||||
<th className='py-2 text-right'>分配客户数</th>
|
) : (
|
||||||
<th className='py-2 text-right'>面诊数</th>
|
<table className='w-full text-xs'>
|
||||||
<th className='py-2 text-right'>面诊率</th>
|
<thead>
|
||||||
</tr>
|
<tr className='text-gray-500 border-b'>
|
||||||
</thead>
|
<th className='py-2 text-left'>家医</th>
|
||||||
<tbody>
|
<th className='py-2 text-right'>分配客户数</th>
|
||||||
{NORTH3_ROWS.map(([name, total, consult]) => (
|
<th className='py-2 text-right'>面诊数</th>
|
||||||
<tr key={name} className='border-b last:border-b-0'>
|
<th className='py-2 text-right'>面诊率</th>
|
||||||
<td className='py-2'>{name}</td>
|
|
||||||
<td className='py-2 text-right'>{total}</td>
|
|
||||||
<td className='py-2 text-right'>{consult}</td>
|
|
||||||
<td className='py-2 text-right'>{((Number(consult) / Number(total)) * 100).toFixed(2)}%</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{north3Data.north3_service_list.map((item, index) => (
|
||||||
|
<tr key={`${item.family_doctor_name}-${index}`} className='border-b last:border-b-0'>
|
||||||
|
<td className='py-2'>{item.family_doctor_name || '-'}</td>
|
||||||
|
<td className='py-2 text-right'>{item.assigned_customer_count ?? '-'}</td>
|
||||||
|
<td className='py-2 text-right'>{item.face_to_face_count ?? '-'}</td>
|
||||||
|
<td className='py-2 text-right'>
|
||||||
|
{item.face_to_face_rate !== undefined
|
||||||
|
? `${(item.face_to_face_rate * 100).toFixed(2)}%`
|
||||||
|
: item.assigned_customer_count && item.assigned_customer_count > 0
|
||||||
|
? `${((item.face_to_face_count ?? 0) / item.assigned_customer_count * 100).toFixed(2)}%`
|
||||||
|
: '-'
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user