ThumbnailList.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import React, { useEffect } from 'react';
  2. import { Row, Col, Image, Card, Typography, Tag, Empty, Badge } from 'antd';
  3. import { FormattedMessage } from 'react-intl';
  4. import { useDispatch, useSelector } from 'react-redux';
  5. import store, { AppDispatch, RootState } from '@/states/store';
  6. import { dview } from '@/domain/dview';
  7. import { clearThumbnails, updateThumbnailsFromHistorySelection } from '@/states/patient/worklist/slices/thumbnailListSlice';
  8. import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
  9. const { Text, Title } = Typography;
  10. interface ThumbnailListProps {
  11. className?: string;
  12. }
  13. const ThumbnailList: React.FC<ThumbnailListProps> = ({ className }) => {
  14. const dispatch = useDispatch<AppDispatch>();
  15. const thumbnails = useSelector(
  16. (state: RootState) => state.thumbnailList.thumbnails
  17. );
  18. const currentKey = useSelector(
  19. (state: RootState) => state.BusinessFlow.currentKey
  20. );
  21. const loading = useSelector(
  22. (state: RootState) => state.thumbnailList.loading
  23. );
  24. const error = useSelector((state: RootState) => state.thumbnailList.error);
  25. const workSelectedIds = useSelector((state: RootState) => state.workSelection.selectedIds);
  26. const workHistorySelectedIds = useSelector((state: RootState) => state.historySelection.selectedIds);
  27. useEffect(() => {
  28. // 组件挂载时清空
  29. // 基于currentKey,查找history或者worklist中的选中项,
  30. if (currentKey === 'worklist') {
  31. const selectedId = store.getState().workSelection.selectedIds;
  32. if (selectedId.length > 0) { dispatch(updateThumbnailsFromHistorySelection(selectedId)); }
  33. }
  34. if (currentKey === 'historylist') {
  35. const selectedId = store.getState().historySelection.selectedIds;
  36. if (selectedId.length > 0) { dispatch(updateThumbnailsFromHistorySelection(selectedId)); }
  37. }
  38. // 组件卸载时清空
  39. return () => {
  40. dispatch(clearThumbnails());
  41. };
  42. }, [dispatch,workHistorySelectedIds,workSelectedIds]);
  43. if (error) {
  44. return (
  45. <div className={`p-4 ${className}`}>
  46. <Text type="danger">{error}</Text>
  47. </div>
  48. );
  49. }
  50. if (loading) {
  51. return (
  52. <div className={`p-4 ${className}`}>
  53. <Text>
  54. <FormattedMessage id="loading" defaultMessage="Loading..." />
  55. </Text>
  56. </div>
  57. );
  58. }
  59. if (thumbnails.length === 0) {
  60. return (
  61. <div className={`p-4 ${className}`}>
  62. <Empty
  63. description={
  64. <FormattedMessage
  65. id="thumbnailList.noImages"
  66. defaultMessage="No images to display"
  67. />
  68. }
  69. />
  70. </div>
  71. );
  72. }
  73. return (
  74. <div className={`p-1 overflow-auto ${className}`}>
  75. {/* <Title level={5} className="mb-3">
  76. <FormattedMessage
  77. id="thumbnailList.title"
  78. defaultMessage="Image Thumbnails"
  79. />
  80. </Title> */}
  81. <Row >
  82. {thumbnails.map((thumbnail: dview) => (
  83. <Col xs={24} sm={12} md={8} lg={3} xl={2} key={thumbnail.view_id}>
  84. <Card
  85. size="small"
  86. hoverable
  87. cover={
  88. <div className="relative">
  89. <Image
  90. src={thumbnail.thumbnail_file}
  91. alt={thumbnail.view_description || thumbnail.view_id}
  92. style={{
  93. width: '100%',
  94. height: '60px',
  95. objectFit: 'cover',
  96. }}
  97. fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3Ik1RUG8M+Q4cMRcNHuS2BAYiBD/PIOCSFfYQ6QHBI7XhAGLpA5v4RFmEQGBFCCMxkYHJw9DQpIKjNZ/lN6JHV9937d8/o2+32uj9/t6j7n3F8nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  98. preview={{
  99. mask: (
  100. <div className="text-white text-center">
  101. <FormattedMessage
  102. id="preview"
  103. defaultMessage="Preview"
  104. />
  105. </div>
  106. ),
  107. }}
  108. />
  109. {/* 左上角:判断状态badge */}
  110. {/* {thumbnail.expose_status === 'Exposed' && thumbnail.judged_status && (
  111. <div className="absolute top-1 left-1">
  112. <Badge
  113. count={
  114. thumbnail.judged_status === 'Accept' ? (
  115. <CheckOutlined style={{ color: '#fff' }} />
  116. ) : thumbnail.judged_status === 'Reject' ? (
  117. <CloseOutlined style={{ color: '#fff' }} />
  118. ) : 'Un'
  119. }
  120. style={{
  121. backgroundColor: thumbnail.judged_status === 'Accept' ? '#52c41a' : '#ff4d4f',
  122. }}
  123. />
  124. </div>
  125. )} */}
  126. {/* 右上角:曝光状态tag */}
  127. {/* <div className="absolute top-1 right-1">
  128. <Tag
  129. color={
  130. thumbnail.expose_status === 'Exposed'
  131. ? 'green'
  132. : 'orange'
  133. }
  134. >
  135. {thumbnail.expose_status}
  136. </Tag>
  137. </div> */}
  138. </div>
  139. }
  140. >
  141. <Card.Meta
  142. title={
  143. <Text
  144. ellipsis={{ tooltip: true }}
  145. style={{ fontSize: '12px' }}
  146. >
  147. {thumbnail.view_description || thumbnail.view_type}
  148. </Text>
  149. }
  150. // description={
  151. // <Text type="secondary" style={{ fontSize: '10px' }}>
  152. // ID: {thumbnail.view_id}
  153. // </Text>
  154. // }
  155. />
  156. </Card>
  157. </Col>
  158. ))}
  159. </Row>
  160. </div>
  161. );
  162. };
  163. export default ThumbnailList;