/* eslint-disable no-else-return */ /* eslint-disable no-unneeded-ternary */ import React, { useState, useEffect } from 'react'; import { DatePicker, Input, Table, Row, Col, Button, notification, message, Tooltip, Spin, Pagination, Select, Tag, Modal, } from 'antd'; import { SwapRightOutlined, SyncOutlined } from '@ant-design/icons'; import moment from 'moment'; import 'moment/dist/locale/zh-cn'; import locale from 'antd/es/date-picker/locale/zh_CN'; import styles from './index.less'; import { GetCallLogPages } from '@/services/logCenter/api'; const { RangePicker } = DatePicker; const LogCenter = () => { const [loading, setLoading] = useState(false); // 源数据 const [requestUrl, setRequestUrl] = useState(''); // 接口名称筛选 const [label, setLabel] = useState(''); // 标签筛选 const [allTime, setAllTime] = useState([ moment().startOf('month'), moment(new Date(), 'YYYY-MM-DD HH:mm:ss'), ]); const [showSearchStyle, setShowSearchStyle] = useState(false); // 是否显示模糊查询样式 const [total, setTotal] = useState(); const [pageSize, setPageSize] = useState(20); const [currentPage, setCurrentPage] = useState(1); const [keepTableList, setKeepTableList] = useState([]); const [loginCodeFilters, setLoginCodeFilters] = useState([]); const [loginStateCodeFilters, setLoginStateCodeFilters] = useState([]); const [filteredValue, setFilteredValue] = useState([]); const [content, setContent] = useState(); const [modalVisible, setModalVisible] = useState(false); useEffect(() => { getTableList(); }, []); const getTableList = (pageIndex, page, time, url, tag) => { setLoading(true); GetCallLogPages({ pageIndex: pageIndex ? pageIndex : currentPage, pageSize: page ? page : pageSize, sortFieldsAndDirection: '', isAll: true, dateFrom: time ? time[0].format('YYYY-MM-DD HH:mm:ss') : allTime[0].format('YYYY-MM-DD HH:mm:ss'), dateTo: time ? time[1].format('YYYY-MM-DD HH:mm:ss') : allTime[1].format('YYYY-MM-DD HH:mm:ss'), requestUrl: url === '' ? '' : requestUrl, thirdUrl: '', label: tag === '' ? '' : label, }).then(res => { setLoading(false); if (res.code === 0) { setKeepTableList(res.data.list); setTotal(res.data.totalCount); setPageSize(res.data.pageSize); setCurrentPage(res.data.pageIndex); let arr1 = res.data.list.map(item => item.code); arr1 = arr1.filter((value, index) => arr1.indexOf(value) === index); setLoginCodeFilters(arr1.map(item => ({ text: item, value: item }))); let arr2 = res.data.list.map(item => item.statusCode); arr2 = arr2.filter((value, index) => arr2.indexOf(value) === index); setLoginStateCodeFilters(arr2.map(item => ({ text: item, value: item }))); } else { setKeepTableList([]); notification.error({ message: '提示', duration: 3, description: res.msg, }); } }); }; const columns = [ { title: '接口标签', dataIndex: 'label', key: 'label', width: 150, fixed: 'left', render: item => searchStyle1(item), }, { title: '接口名称', dataIndex: 'requestUrl', key: 'requestUrl', width: 300, fixed: 'left', // render: item => searchStyle(item), onCell: () => ({ style: { maxWidth: 400, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', cursor: 'pointer', }, }), render: record => ( <Tooltip placement="topLeft" title={record}> {searchStyle(record)} </Tooltip> ), }, { title: '调用时间', dataIndex: 'time', key: 'time', width: 120, align: 'center', }, { title: '调用结果', dataIndex: 'code', key: 'code', width: 100, align: 'center', filters: loginCodeFilters, onFilter: (value, record) => record.code === value, filteredValue, render: record => { if (record === 0) { return <span style={{ color: '#6ecd3d', fontWeight: 'bold' }}>成功</span>; } else { return <span style={{ color: 'red', fontWeight: 'bold' }}>失败</span>; } }, }, { title: '耗时/ms', dataIndex: 'consumerTime', key: 'consumerTime', align: 'center', width: 80, }, { title: '返回状态码', dataIndex: 'statusCode', key: 'statusCode', width: 100, align: 'center', filters: loginStateCodeFilters, onFilter: (value, record) => record.statusCode === value, filteredValue, }, { title: '请求方法', dataIndex: 'method', key: 'method', width: 80, align: 'center', // render: record => { // if (record === 'GET') { // return <span style={{ color: '#6ecd3d', fontWeight: 'bold' }}>GET</span>; // } else if (record === 'POST') { // return <span style={{ color: '#ffb880', fontWeight: 'bold' }}>POST</span>; // } // }, }, { title: '返回体大小/byte', dataIndex: 'responseSize', key: 'responseSize', width: 130, align: 'center', }, { title: '返回信息', dataIndex: 'message', key: 'message', onCell: () => ({ style: { maxWidth: 400, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', cursor: 'pointer', }, }), render: record => ( <Tooltip placement="topLeft" title={record}> {record} </Tooltip> ), }, { title: '异常信息', dataIndex: 'exception', key: 'exception', align: 'center', width: 100, render: record => { if (record) { return ( <Button size="small" type="primary" onClick={() => { handleLog(record); }} style={{ backgroundColor: 'red' }} > 错误内容 </Button> ); } }, }, ]; const handleLog = text => { setModalVisible(true); setContent(text); }; // 模糊查询匹配的样式 const searchStyle = val => { let n; if (showSearchStyle) { n = val.replace(new RegExp(requestUrl, 'g'), `<span style='color:red'>${requestUrl}</span>`); } else { n = val; } return <div dangerouslySetInnerHTML={{ __html: n }} />; }; const searchStyle1 = val => { let n; if (showSearchStyle) { n = val.replace(new RegExp(label, 'g'), `<span style='color:red'>${label}</span>`); } else { n = val; } return <div dangerouslySetInnerHTML={{ __html: n }} />; }; const changeTime = time => { let time1 = time[0].format('YYYY-MM'); let time2 = time[1].format('YYYY-MM'); if (time1 !== time2) { message.warning('不允许跨月查询'); } else { setAllTime(time); setPageSize(20); setCurrentPage(1); getTableList(1, 20, time); } }; // 近1/6/12/24小时 const setTime = time => { setAllTime([ moment(new Date(new Date().getTime() - time * 60 * 60 * 1000), 'YYYY-MM-DD HH:mm:ss'), moment(new Date(), 'YYYY-MM-DD HH:mm:ss'), ]); }; const handleReset = () => { setAllTime([moment().startOf('month'), moment(new Date(), 'YYYY-MM-DD HH:mm:ss')]); setRequestUrl(''); setLabel(''); setShowSearchStyle(false); getTableList( 1, 20, [moment().startOf('month'), moment(new Date(), 'YYYY-MM-DD HH:mm:ss')], '', '', ); }; const paginationChange = (page, pageSizes) => { getTableList(page, pageSizes); setCurrentPage(page); setPageSize(pageSizes); }; const onChangeInput = filters => { setFilteredValue(filters.code, filters.statusCode); }; return ( <div className={styles.centerLog}> <div className={styles.head}> <span style={{ lineHeight: 2, marginLeft: '7px' }}>时间:</span> <RangePicker locale={locale} showTime format="YYYY-MM-DD HH:mm:ss" onChange={changeTime} value={allTime} allowClear={false} /> <span style={{ marginLeft: '20px' }}>接口名称:</span> <Input style={{ width: '200px' }} placeholder="请输入接口名称" onChange={e => { setRequestUrl(e.target.value); }} value={requestUrl} allowClear /> <span style={{ marginLeft: '20px' }}>接口标签:</span> <Input style={{ width: '200px' }} placeholder="请输入接口标签" onChange={e => { setLabel(e.target.value); }} value={label} allowClear /> <Button type="primary" style={{ marginLeft: '10px' }} onClick={() => { setPageSize(20); setCurrentPage(1); getTableList(1, 20); setShowSearchStyle(true); }} > 查询 </Button> <Button icon={<SyncOutlined className={styles.icon} />} onClick={handleReset} style={{ marginLeft: '25px', verticalAlign: 'middle', marginTop: '-3px', }} > 重置 </Button> </div> <div className={styles.table}> <Table size="small" bordered columns={columns} dataSource={keepTableList} scroll={{ x: 'max-content', y: 'calc(100vh - 225px)' }} pagination={false} onChange={onChangeInput} loading={loading} /> </div> <div className={styles.footer}> <Pagination total={total} showTotal={(aa, range) => `第${range[0]}-${range[1]} 条/共 ${total} 条`} pageSizeOptions={[10, 20, 40, 100]} current={currentPage} onChange={paginationChange} size="small" pageSize={pageSize} showSizeChanger /> </div> <Modal title="详细信息" visible={modalVisible} keyboard={false} maskClosable centered onOk={() => setModalVisible(false)} onCancel={() => setModalVisible(false)} width="1000px" bodyStyle={{ minHeight: '100px', maxHeight: '600px', overflowY: 'scroll', }} style={{ top: '40px' }} footer={[ <Button type="primary" onClick={() => setModalVisible(false)} key="back"> 关闭窗口 </Button>, ]} > {content} </Modal> </div> ); }; export default LogCenter;