123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import React, { useState, useEffect } from 'react';
- import styled from 'styled-components';
- import { apiGet } from '../../utils/request';
- import { useDefaultDate, getSelectedMonthRange } from '../../App';
- import useGlobalRefresh from '../../hooks/useGlobalRefresh';
- // 组件容器样式 - 确保完全填充Grid单元格
- const ChartWrapper = styled.div`
- width: 100%;
- height: 100%;
- position: relative;
- overflow: hidden;
- border: 1px solid #2980B9;
- box-sizing: border-box;
- display: flex;
- flex-direction: column;
- `;
- // 组件标题 - 使用与其他模块相同的样式
- const PanelHeader = styled.div`
- position: relative;
- width: 95%;
- height: 1.6vw;
- min-height: 1.6vw;
- max-height: 1.6vw;
- padding-left: 5.5%;
- text-align: left;
- line-height: 1.6vw;
- font-size: 0.8vw;
- color: #E6F2FF;
- font-family: 'DingTalk JinBuTi', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
- background: url('/component_header_bg.png') no-repeat;
- background-size: 100% 100%;
- flex-shrink: 0;
- `;
- // 表格容器 - 占据剩余空间,确保与其他模块一致
- const TableContainer = styled.div`
- width: 100%;
- flex: 1;
- overflow: hidden;
- `;
- // 表格样式
- const Table = styled.table`
- width: 100%;
- height: 100%;
- border-collapse: collapse;
- font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif !important;
- `;
- // 表头样式
- const TableHeader = styled.thead`
- tr {
- background:#051833;
- }
-
- th {
- padding: 0.3vw 1.2vw;
- font-size: 0.7vw;
- font-weight: normal;
- color: #CCE6FF;
- white-space: nowrap;
- font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif !important;
-
- &:first-child {
- width: 35%;
- text-align: left;
- padding-left: 3.2vw; /* 增加左边距,与药品名称文字对齐 */
- }
-
- &:nth-child(2) {
- width: 20%;
- text-align: left;
- }
-
- &:nth-child(3) {
- width: 45%;
- text-align: left;
- }
- }
- `;
- // 表体样式
- const TableBody = styled.tbody`
- tr {
- &:nth-child(odd) {
- background: #162840;
- }
-
- &:nth-child(even) {
- background: #051833;
- }
-
- &:hover {
- background: rgba(6, 30, 93, 0.6);
- }
- }
-
- td {
- padding: 0.2vw 1.2vw;
- font-size: 0.65vw;
- color: #FFFFFF;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif !important;
-
- &:first-child {
- text-align: left;
- color: #FFFFFF;
- }
-
- &:nth-child(2) {
- text-align: left;
- }
-
- &:nth-child(3) {
- text-align: left;
- }
- }
- `;
- // 排名号码样式
- const RankNumber = styled.span<{ rank: string }>`
- display: inline-block;
- min-width: 1.5vw;
- text-align: center;
- font-size: 0.7vw;
- font-weight: bold;
- margin-right: 0.5vw;
- font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif !important;
- color: ${props => {
- const rankNum = parseInt(props.rank);
- if (rankNum <= 3) return '#FF4D6A'; // 前三名红色
- return '#CCE6FF'; // 剩余浅蓝色
- }};
- `;
- // 数据类型定义
- interface MedicineData {
- rank: string;
- drugName: string;
- drugSpec: string;
- firmName: string;
- amount: number;
- }
- const ConsumedMedicineTop8Chart: React.FC = () => {
- const [data, setData] = useState<MedicineData[]>([]);
- const [loading, setLoading] = useState<boolean>(true);
- const { defaultDateTime, selectedMonth } = useDefaultDate();
- // 获取数据
- const fetchData = async () => {
- try {
- setLoading(true);
-
- // 使用选中月份获取时间范围,支持月份选择功能
- const { startTime, endTime } = getSelectedMonthRange(defaultDateTime, selectedMonth);
-
- const response = await apiGet('/stageStats/drugsConsumptionTop', {
- params: {
- startTime,
- endTime
- }
- });
-
- if (response.data && response.data.data && Array.isArray(response.data.data)) {
- // 最多只取前8条数据
- const limitedData = response.data.data.slice(0, 8);
- setData(limitedData);
- } else {
- console.warn('消耗药品Top8 - 接口返回格式不符合预期:', response.data);
- // 设置为空数组,不使用模拟数据
- setData([]);
- }
- } catch (error) {
- console.error('获取消耗药品Top8数据失败:', error);
- // 设置为空数组,不使用模拟数据
- setData([]);
- } finally {
- setLoading(false);
- }
- };
- // 组件挂载时和依赖变化时获取数据
- useEffect(() => {
- fetchData();
- }, [defaultDateTime, selectedMonth]);
- // 使用刷新Hook,配置对应的模块代码
- useGlobalRefresh(fetchData, '41');
- return (
- <ChartWrapper>
- <PanelHeader>消耗药品Top8</PanelHeader>
- <TableContainer>
- {loading ? (
- <div style={{
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- height: '100%',
- color: '#CCE6FF',
- fontSize: '0.8vw'
- }}>
- 数据加载中...
- </div>
- ) : data.length === 0 ? (
- <div style={{
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- height: '100%',
- color: '#CCE6FF',
- fontSize: '0.8vw'
- }}>
- 暂无数据
- </div>
- ) : (
- <Table>
- <TableHeader>
- <tr>
- <th>药品名称</th>
- <th>药品规格</th>
- <th>厂商</th>
- </tr>
- </TableHeader>
- <TableBody>
- {data.map((item, index) => (
- <tr key={index}>
- <td>
- <RankNumber rank={item.rank}>
- {String(item.rank).padStart(2, '0')}
- </RankNumber>
- {item.drugName}
- </td>
- <td>{item.drugSpec}</td>
- <td>{item.firmName}</td>
- </tr>
- ))}
- </TableBody>
- </Table>
- )}
- </TableContainer>
- </ChartWrapper>
- );
- };
- export default ConsumedMedicineTop8Chart;
|