MessageModal.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import React, { useState } from "react";
  2. import { Modal, Button, Tabs, Empty, message } from "antd";
  3. import type { TabsProps } from "antd";
  4. import axios from "axios";
  5. import { MESSAGE_STATUS, MESSAGE_TAB } from "@/constants";
  6. import { useNotificationStore } from "@/store/NotificationStore";
  7. import { Eraser, FileText } from "lucide-react";
  8. import dayjs from "dayjs";
  9. import { renderNoticeLength } from "@/utils/utils";
  10. interface MessageModalProps {
  11. visible: boolean;
  12. onClose: () => void;
  13. socket: any;
  14. }
  15. const MessageModal: React.FC<MessageModalProps> = ({
  16. visible,
  17. onClose,
  18. socket,
  19. }) => {
  20. const [activeKey, setActiveKey] = useState(MESSAGE_TAB.UNREAD);
  21. const { notifications, changeNotification } = useNotificationStore();
  22. const unreadNotifications = notifications.filter(
  23. (notification) => notification.is_read === MESSAGE_STATUS.UNREAD
  24. );
  25. const tabItems: TabsProps["items"] = [
  26. {
  27. key: MESSAGE_TAB.ALL,
  28. label: <span className="flex">全部</span>,
  29. },
  30. {
  31. key: MESSAGE_TAB.UNREAD,
  32. label: (
  33. <span className="flex">
  34. 未读
  35. {!!unreadNotifications.length && (
  36. <span className="ml-1 text-xs text-white bg-red-500 rounded-full w-5 h-5 flex justify-center items-center">
  37. {renderNoticeLength(unreadNotifications)}
  38. </span>
  39. )}
  40. </span>
  41. ),
  42. },
  43. {
  44. key: MESSAGE_TAB.HAS_READ,
  45. label: <span className="flex">已读</span>,
  46. },
  47. ];
  48. return (
  49. <Modal
  50. title={
  51. <div className="flex items-center">
  52. <span>
  53. 消息中心
  54. {!!renderNoticeLength(unreadNotifications) &&
  55. `(${renderNoticeLength(unreadNotifications)})`}
  56. </span>
  57. <div
  58. className="cursor-pointer hover:bg-gray-100 rounded-md px-2 py-1 ml-2 text-xs flex justify-center items-center gap-1"
  59. onClick={async () => {
  60. const res = await axios.post(`/notification/bazb/clearMsg`);
  61. if (res.data.code === 200) {
  62. changeNotification({ type: "clear" });
  63. }
  64. }}
  65. >
  66. <Eraser size={12} />
  67. 清除消息
  68. </div>
  69. </div>
  70. }
  71. open={visible}
  72. onCancel={onClose}
  73. footer={null}
  74. style={{
  75. top: 30,
  76. maxWidth: "90%",
  77. maxHeight: "80%",
  78. }}
  79. >
  80. <div className="flex flex-col h-[80vh]">
  81. <Tabs
  82. activeKey={activeKey}
  83. items={tabItems}
  84. className="mb-4"
  85. onChange={(key) => {
  86. setActiveKey(key);
  87. }}
  88. />
  89. <div className="space-y-4 max-h-[100%] overflow-auto">
  90. {(() => {
  91. let filteredNotifications = notifications;
  92. if (activeKey === MESSAGE_TAB.UNREAD) {
  93. filteredNotifications = notifications.filter(
  94. (notification) => notification.is_read === MESSAGE_STATUS.UNREAD
  95. );
  96. } else if (activeKey === MESSAGE_TAB.HAS_READ) {
  97. filteredNotifications = notifications.filter(
  98. (notification) =>
  99. notification.is_read === MESSAGE_STATUS.HAS_READ
  100. );
  101. }
  102. return (
  103. <>
  104. {filteredNotifications.length === 0 && (
  105. <div className="flex justify-center items-center h-full">
  106. <Empty description="暂无消息" />
  107. </div>
  108. )}
  109. {filteredNotifications.map((message, index) => (
  110. <div
  111. key={index}
  112. className="p-4 bg-gray-50 rounded-lg shadow-sm flex flex-col gap-4"
  113. >
  114. <div className="flex justify-between items-center">
  115. <div className="flex gap-1 items-center">
  116. <div className="p-1 bg-blue-500 rounded-full w-6 h-6 text-white flex justify-center items-center">
  117. <FileText size={14} />
  118. </div>
  119. <div className="font-bold">病例时效提醒</div>
  120. </div>
  121. <div className="text-gray-500 text-xs">
  122. {dayjs(message.timestamp).format("YYYY-MM-DD HH:mm")}
  123. </div>
  124. </div>
  125. <div className="flex items-start space-x-4">
  126. <div className="flex-1">
  127. <div className="flex">
  128. <h4 className="text-sm font-semibold">
  129. {message.title}
  130. </h4>
  131. </div>
  132. <p className="text-gray-700 mt-1 indent-[1.75rem]">
  133. {message.content}
  134. </p>
  135. <p className="text-gray-700 mt-1 indent-[1.75rem]">
  136. {message.footer || "祝您工作顺利!"}
  137. </p>
  138. <div className="mt-2 flex space-x-2 justify-end">
  139. <Button
  140. type="primary"
  141. size="middle"
  142. onClick={() => {
  143. axios.post("/notification/bazb/clearMsg", {
  144. msgId: message.id,
  145. });
  146. changeNotification({
  147. type: "clear",
  148. notification: [message.id],
  149. });
  150. }}
  151. >
  152. 知道了
  153. </Button>
  154. <Button size="middle">去查看</Button>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. ))}
  160. </>
  161. );
  162. })()}
  163. </div>
  164. </div>
  165. </Modal>
  166. );
  167. };
  168. export default MessageModal;