page.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. "use client";
  2. import {fetchApi} from "@/app/_modules/func";
  3. import {DeleteOutlined, ExclamationCircleFilled, ReloadOutlined,} from "@ant-design/icons";
  4. import type {ActionType, ProColumns, ProFormInstance,} from "@ant-design/pro-components";
  5. import {PageContainer, ProTable} from "@ant-design/pro-components";
  6. import {Button, Modal} from "antd";
  7. import {useRouter} from "next/navigation";
  8. import {faToggleOff, faToggleOn} from "@fortawesome/free-solid-svg-icons";
  9. import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
  10. import {useRef, useState} from "react";
  11. import globalMessage from "@/app/_modules/globalMessage";
  12. //查询表格数据API
  13. const queryAPI = "/api/monitor/online/list";
  14. //强退用户API
  15. const logoutAPI = "/api/monitor/online";
  16. export default function Online() {
  17. const { push } = useRouter();
  18. // 添加用于控制强退确认模态框的状态
  19. const [logoutModalVisible, setLogoutModalVisible] = useState(false);
  20. const [logoutRecord, setLogoutRecord] = useState<any>(null);
  21. //表格列定义
  22. const columns: ProColumns[] = [
  23. {
  24. title: "序号",
  25. dataIndex: "index",
  26. valueType: "index",
  27. },
  28. {
  29. title: "会话编号",
  30. dataIndex: "tokenId",
  31. ellipsis: true,
  32. search: false,
  33. },
  34. {
  35. title: "用户名称",
  36. fieldProps: {
  37. placeholder: "请输入用户名称",
  38. },
  39. dataIndex: "userName",
  40. order: 1,
  41. },
  42. {
  43. title: "部门名称",
  44. dataIndex: "deptName",
  45. search: false,
  46. },
  47. {
  48. title: "IP地址",
  49. fieldProps: {
  50. placeholder: "请输入IP地址",
  51. },
  52. dataIndex: "ipaddr",
  53. order: 2,
  54. },
  55. {
  56. title: "登录地点",
  57. dataIndex: "loginLocation",
  58. search: false,
  59. },
  60. {
  61. title: "浏览器",
  62. dataIndex: "browser",
  63. search: false,
  64. },
  65. {
  66. title: "操作系统",
  67. dataIndex: "os",
  68. search: false,
  69. },
  70. {
  71. title: "登录时间",
  72. dataIndex: "loginTime",
  73. valueType: "dateTime",
  74. search: false,
  75. },
  76. {
  77. title: "操作",
  78. key: "option",
  79. search: false,
  80. render: (_, record) => [
  81. <Button
  82. key="deleteBtn"
  83. type="link"
  84. danger
  85. icon={<DeleteOutlined />}
  86. onClick={() => onClickLogoutRow(record)}
  87. >
  88. 强退
  89. </Button>,
  90. ],
  91. },
  92. ];
  93. //0.查询表格数据
  94. const queryTableData = async (params: any, sorter: any, filter: any) => {
  95. const searchParams = {
  96. pageNum: params.current,
  97. ...params,
  98. };
  99. delete searchParams.current;
  100. const queryParams = new URLSearchParams(searchParams);
  101. Object.keys(sorter).forEach((key) => {
  102. queryParams.append("orderByColumn", key);
  103. if (sorter[key] === "ascend") {
  104. queryParams.append("isAsc", "ascending");
  105. } else {
  106. queryParams.append("isAsc", "descending");
  107. }
  108. });
  109. return await fetchApi(`${queryAPI}?${queryParams}`, push);
  110. };
  111. //3.删除
  112. //点击删除按钮,展示删除确认框
  113. const onClickLogoutRow = (record?: any) => {
  114. setLogoutRecord(record);
  115. setLogoutModalVisible(true);
  116. };
  117. //确定强退选中的会话
  118. const executeLogoutRow = async () => {
  119. if (!logoutRecord) return;
  120. const tokenId = logoutRecord.tokenId;
  121. const body = await fetchApi(`${logoutAPI}/${tokenId}`, push, {
  122. method: "DELETE",
  123. });
  124. if (body !== undefined) {
  125. if (body.code == 200) {
  126. globalMessage.success("强退成功");
  127. //刷新列表
  128. if (actionTableRef.current) {
  129. actionTableRef.current.reload();
  130. }
  131. } else {
  132. globalMessage.error(body.msg);
  133. }
  134. }
  135. setLogoutModalVisible(false);
  136. setLogoutRecord(null);
  137. };
  138. //取消强退操作
  139. const cancelLogoutRow = () => {
  140. setLogoutModalVisible(false);
  141. setLogoutRecord(null);
  142. };
  143. //搜索栏显示状态
  144. const [showSearch, setShowSearch] = useState(true);
  145. //action对象引用
  146. const actionTableRef = useRef<ActionType>(null);
  147. //搜索表单对象引用
  148. const searchTableFormRef = useRef<ProFormInstance>(null!);
  149. //当前页数和每页条数
  150. const [page, setPage] = useState(1);
  151. const defaultPageSize = 10;
  152. const [pageSize, setPageSize] = useState(defaultPageSize);
  153. const pageChange = (page: number, pageSize: number) => {
  154. setPage(page);
  155. setPageSize(pageSize);
  156. };
  157. return (
  158. <PageContainer title={false}>
  159. <ProTable
  160. formRef={searchTableFormRef}
  161. rowKey="tokenId"
  162. columns={columns}
  163. request={async (params: any, sorter: any, filter: any) => {
  164. // 表单搜索项会从 params 传入,传递给后端接口。
  165. const data = await queryTableData(params, sorter, filter);
  166. if (data !== undefined) {
  167. return Promise.resolve({
  168. data: data.rows,
  169. success: true,
  170. total: data.total,
  171. });
  172. }
  173. return Promise.resolve({
  174. data: [],
  175. success: true,
  176. });
  177. }}
  178. pagination={{
  179. defaultPageSize: defaultPageSize,
  180. showQuickJumper: true,
  181. showSizeChanger: true,
  182. onChange: pageChange,
  183. }}
  184. search={
  185. showSearch
  186. ? {
  187. defaultCollapsed: false,
  188. searchText: "搜索",
  189. }
  190. : false
  191. }
  192. dateFormatter="string"
  193. actionRef={actionTableRef}
  194. toolbar={{
  195. actions: [],
  196. settings: [
  197. {
  198. key: "switch",
  199. icon: showSearch ? (
  200. <FontAwesomeIcon icon={faToggleOn} />
  201. ) : (
  202. <FontAwesomeIcon icon={faToggleOff} />
  203. ),
  204. tooltip: showSearch ? "隐藏搜索栏" : "显示搜索栏",
  205. onClick: (key: string | undefined) => {
  206. setShowSearch(!showSearch);
  207. },
  208. },
  209. {
  210. key: "refresh",
  211. tooltip: "刷新",
  212. icon: <ReloadOutlined />,
  213. onClick: (key: string | undefined) => {
  214. if (actionTableRef.current) {
  215. actionTableRef.current.reload();
  216. }
  217. },
  218. },
  219. ],
  220. }}
  221. />
  222. {/* 强退确认模态框 */}
  223. <Modal
  224. title={
  225. <div style={{ display: 'flex', alignItems: 'center' }}>
  226. <ExclamationCircleFilled style={{ color: '#faad14', marginRight: 8 }} />
  227. <span>系统提示</span>
  228. </div>
  229. }
  230. open={logoutModalVisible}
  231. onOk={executeLogoutRow}
  232. onCancel={cancelLogoutRow}
  233. okText="确认"
  234. cancelText="取消"
  235. >
  236. <p>{`确定强退登录名称为“${logoutRecord?.userName}”的用户?`}</p>
  237. </Modal>
  238. </PageContainer>
  239. );
  240. }