前端重构
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
/**
|
||||
* KRA - System Error Log Page
|
||||
* 系统错误日志页面 - 查看、删除错误日志
|
||||
*/
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Table,
|
||||
Button,
|
||||
Space,
|
||||
Form,
|
||||
Input,
|
||||
DatePicker,
|
||||
Drawer,
|
||||
Descriptions,
|
||||
Tag,
|
||||
message,
|
||||
Tooltip,
|
||||
Popconfirm,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import {
|
||||
SearchOutlined,
|
||||
ReloadOutlined,
|
||||
DeleteOutlined,
|
||||
InfoCircleOutlined,
|
||||
QuestionCircleOutlined,
|
||||
DownOutlined,
|
||||
UpOutlined,
|
||||
RobotOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { PageContainer } from '@ant-design/pro-components';
|
||||
import {
|
||||
getSysErrorList,
|
||||
getSysErrorById,
|
||||
deleteSysError,
|
||||
deleteSysErrorByIds,
|
||||
} from '@/services/kratos/sysError';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import styles from './index.less';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
interface SysError {
|
||||
ID: number;
|
||||
CreatedAt: string;
|
||||
form: string;
|
||||
level: string;
|
||||
status: string;
|
||||
info: string;
|
||||
solution?: string;
|
||||
}
|
||||
|
||||
// Level tag mapping
|
||||
const levelTagMap: Record<string, string> = {
|
||||
fatal: 'error',
|
||||
error: 'warning',
|
||||
};
|
||||
|
||||
const levelLabelMap: Record<string, string> = {
|
||||
fatal: '致命错误',
|
||||
error: '一般错误',
|
||||
};
|
||||
|
||||
// Status tag mapping
|
||||
const statusTagMap: Record<string, string> = {
|
||||
'未处理': 'default',
|
||||
'处理中': 'processing',
|
||||
'处理完成': 'success',
|
||||
'处理失败': 'error',
|
||||
};
|
||||
|
||||
const statusLabelMap: Record<string, string> = {
|
||||
'未处理': '未处理',
|
||||
'处理中': '处理中',
|
||||
'处理完成': '处理完成',
|
||||
'处理失败': '处理失败',
|
||||
};
|
||||
|
||||
const SysErrorPage: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [dataSource, setDataSource] = useState<SysError[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [current, setCurrent] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
const [showAllQuery, setShowAllQuery] = useState(false);
|
||||
|
||||
// Detail drawer
|
||||
const [detailVisible, setDetailVisible] = useState(false);
|
||||
const [detailData, setDetailData] = useState<SysError | null>(null);
|
||||
|
||||
// Fetch table data
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const values = form.getFieldsValue();
|
||||
const params: any = {
|
||||
page: current,
|
||||
pageSize,
|
||||
...values,
|
||||
};
|
||||
if (values.createdAtRange) {
|
||||
params.startCreatedAt = values.createdAtRange[0]?.format('YYYY-MM-DD HH:mm:ss');
|
||||
params.endCreatedAt = values.createdAtRange[1]?.format('YYYY-MM-DD HH:mm:ss');
|
||||
delete params.createdAtRange;
|
||||
}
|
||||
const res = await getSysErrorList(params);
|
||||
if (res.code === 0) {
|
||||
setDataSource(res.data?.list || []);
|
||||
setTotal(res.data?.total || 0);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取错误日志列表失败:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [current, pageSize]);
|
||||
|
||||
// Search
|
||||
const handleSearch = () => {
|
||||
setCurrent(1);
|
||||
fetchData();
|
||||
};
|
||||
|
||||
// Reset
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
setCurrent(1);
|
||||
fetchData();
|
||||
};
|
||||
|
||||
// Delete single row
|
||||
const handleDelete = async (record: SysError) => {
|
||||
try {
|
||||
const res = await deleteSysError({ ID: record.ID });
|
||||
if (res.code === 0) {
|
||||
message.success('删除成功');
|
||||
fetchData();
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
}
|
||||
};
|
||||
|
||||
// Batch delete
|
||||
const handleBatchDelete = async () => {
|
||||
if (selectedRowKeys.length === 0) {
|
||||
message.warning('请选择要删除的数据');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await deleteSysErrorByIds({ ids: selectedRowKeys as number[] });
|
||||
if (res.code === 0) {
|
||||
message.success('删除成功');
|
||||
setSelectedRowKeys([]);
|
||||
fetchData();
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
}
|
||||
};
|
||||
|
||||
// View details
|
||||
const handleViewDetail = async (record: SysError) => {
|
||||
try {
|
||||
const res = await getSysErrorById({ ID: record.ID });
|
||||
if (res.code === 0) {
|
||||
setDetailData(res.data?.reSysError || res.data);
|
||||
setDetailVisible(true);
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('获取详情失败');
|
||||
}
|
||||
};
|
||||
|
||||
// Get AI solution (placeholder - would need backend support)
|
||||
const handleGetSolution = async (id: number) => {
|
||||
message.info('AI方案功能需要后端支持');
|
||||
};
|
||||
|
||||
|
||||
const columns: ColumnsType<SysError> = [
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'CreatedAt',
|
||||
key: 'CreatedAt',
|
||||
width: 180,
|
||||
sorter: true,
|
||||
render: (text) => formatDate(text),
|
||||
},
|
||||
{
|
||||
title: '错误来源',
|
||||
dataIndex: 'form',
|
||||
key: 'form',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '错误等级',
|
||||
dataIndex: 'level',
|
||||
key: 'level',
|
||||
width: 120,
|
||||
render: (level) => (
|
||||
<Tag color={levelTagMap[level] || 'default'}>
|
||||
{levelLabelMap[level] || '一般错误'}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '处理状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 140,
|
||||
render: (status) => (
|
||||
<Tag color={statusTagMap[status] || 'default'}>
|
||||
{statusLabelMap[status] || '未处理'}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '错误内容',
|
||||
dataIndex: 'info',
|
||||
key: 'info',
|
||||
width: 240,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '解决方案',
|
||||
dataIndex: 'solution',
|
||||
key: 'solution',
|
||||
width: 120,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text || '-'}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 280,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{record.status !== '处理中' && (
|
||||
<Button
|
||||
type="link"
|
||||
icon={<RobotOutlined />}
|
||||
onClick={() => handleGetSolution(record.ID)}
|
||||
>
|
||||
方案
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="link"
|
||||
icon={<InfoCircleOutlined />}
|
||||
onClick={() => handleViewDetail(record)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="确定要删除吗?"
|
||||
onConfirm={() => handleDelete(record)}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Button type="link" danger icon={<DeleteOutlined />}>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
{/* Search Form */}
|
||||
<Card className={styles.searchCard}>
|
||||
<Form form={form} layout="inline" onFinish={handleSearch}>
|
||||
<Form.Item
|
||||
name="createdAtRange"
|
||||
label={
|
||||
<span>
|
||||
创建日期
|
||||
<Tooltip title="搜索范围是开始日期(包含)至结束日期(不包含)">
|
||||
<QuestionCircleOutlined style={{ marginLeft: 4 }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<RangePicker showTime style={{ width: 380 }} />
|
||||
</Form.Item>
|
||||
<Form.Item name="form" label="错误来源">
|
||||
<Input placeholder="搜索条件" />
|
||||
</Form.Item>
|
||||
<Form.Item name="info" label="错误内容">
|
||||
<Input placeholder="搜索条件" />
|
||||
</Form.Item>
|
||||
{showAllQuery && (
|
||||
<>
|
||||
{/* Additional query fields can be added here */}
|
||||
</>
|
||||
)}
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" icon={<SearchOutlined />} htmlType="submit">
|
||||
查询
|
||||
</Button>
|
||||
<Button icon={<ReloadOutlined />} onClick={handleReset}>
|
||||
重置
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
icon={showAllQuery ? <UpOutlined /> : <DownOutlined />}
|
||||
onClick={() => setShowAllQuery(!showAllQuery)}
|
||||
>
|
||||
{showAllQuery ? '收起' : '展开'}
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
{/* Table */}
|
||||
<Card>
|
||||
<div className={styles.toolbar}>
|
||||
<Space>
|
||||
<Popconfirm
|
||||
title="确定要删除选中的数据吗?"
|
||||
onConfirm={handleBatchDelete}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
disabled={selectedRowKeys.length === 0}
|
||||
>
|
||||
<Button
|
||||
icon={<DeleteOutlined />}
|
||||
disabled={selectedRowKeys.length === 0}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
</div>
|
||||
<Table
|
||||
rowKey="ID"
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
loading={loading}
|
||||
rowSelection={{
|
||||
selectedRowKeys,
|
||||
onChange: setSelectedRowKeys,
|
||||
}}
|
||||
pagination={{
|
||||
current,
|
||||
pageSize,
|
||||
total,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (t) => `共 ${t} 条`,
|
||||
onChange: (page, size) => {
|
||||
setCurrent(page);
|
||||
setPageSize(size);
|
||||
},
|
||||
}}
|
||||
scroll={{ x: 1200 }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* Detail Drawer */}
|
||||
<Drawer
|
||||
title="查看"
|
||||
open={detailVisible}
|
||||
onClose={() => setDetailVisible(false)}
|
||||
width={600}
|
||||
destroyOnClose
|
||||
>
|
||||
{detailData && (
|
||||
<Descriptions column={2} bordered layout="vertical">
|
||||
<Descriptions.Item label="错误来源">
|
||||
{detailData.form}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="错误等级">
|
||||
<Tag color={levelTagMap[detailData.level] || 'default'}>
|
||||
{levelLabelMap[detailData.level] || '一般错误'}
|
||||
</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理状态">
|
||||
<Tag color={statusTagMap[detailData.status] || 'default'}>
|
||||
{statusLabelMap[detailData.status] || '未处理'}
|
||||
</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="错误内容" span={2}>
|
||||
<pre className={styles.preContent}>{detailData.info}</pre>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="解决方案" span={2}>
|
||||
<pre className={styles.preContent}>{detailData.solution || '-'}</pre>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
)}
|
||||
</Drawer>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default SysErrorPage;
|
||||
Reference in New Issue
Block a user