release: bump version to 0.39.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "planet-frontend",
|
||||
"version": "0.38.0",
|
||||
"version": "0.39.0",
|
||||
"private": true,
|
||||
"packageManager": "bun@1",
|
||||
"dependencies": {
|
||||
|
||||
@@ -634,6 +634,15 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.earth-mobile-drawer-slot--situation,
|
||||
.earth-mobile-page,
|
||||
.earth-mobile-stats-grid,
|
||||
.earth-mobile-situation-card,
|
||||
.earth-mobile-situation-legend-list {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.earth-mobile-drawer-slot--situation.is-active {
|
||||
display: grid;
|
||||
}
|
||||
@@ -1024,11 +1033,28 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.earth-mobile-situation-status {
|
||||
color: var(--hud-text);
|
||||
line-height: 1.5;
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.earth-mobile-situation-legend-list .legend-item,
|
||||
.earth-mobile-situation-legend-list .legend-label {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.earth-mobile-situation-legend-list .legend-label {
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.earth-mobile-news-focus,
|
||||
|
||||
@@ -137,6 +137,11 @@ function getMobileDetailRenderKey(type, data) {
|
||||
].join('|');
|
||||
}
|
||||
|
||||
function isMobileDetailsDrawerActive() {
|
||||
const detailsSlot = document.querySelector('[data-drawer-slot="details"]');
|
||||
return detailsSlot instanceof HTMLElement && detailsSlot.classList.contains('is-active');
|
||||
}
|
||||
|
||||
function ensureMobileDetailsListener() {
|
||||
if (mobileDetailsListenerBound) return;
|
||||
mobileDetailsListenerBound = true;
|
||||
@@ -836,6 +841,9 @@ export function showInfoCard(type, data, options = {}) {
|
||||
if (content && type !== 'news') {
|
||||
renderMobileDetailContent(type, config, data);
|
||||
renderedMobileDetailKey = null;
|
||||
} else if (content && type === 'news' && isMobileDetailsDrawerActive()) {
|
||||
renderMobileNewsCardContent(content, data);
|
||||
renderedMobileDetailKey = getMobileDetailRenderKey(type, data);
|
||||
}
|
||||
|
||||
// Show the floating mini popup near the touch point (requires coordinates)
|
||||
|
||||
@@ -3417,7 +3417,7 @@ body {
|
||||
.system-log-console {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
min-height: 480px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
border-radius: 16px;
|
||||
background: #020617;
|
||||
@@ -3448,13 +3448,18 @@ body {
|
||||
.system-log-console__scroll,
|
||||
.system-log-console__scroll .scrollbar__viewport {
|
||||
height: 100%;
|
||||
min-height: 480px;
|
||||
}
|
||||
|
||||
.system-log-console__scroll,
|
||||
.system-log-console__scroll .scrollbar__viewport,
|
||||
.system-log-console__content,
|
||||
.system-log-console__placeholder {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.system-log-console__content {
|
||||
margin: 0;
|
||||
padding: 18px 88px 18px 20px;
|
||||
min-height: 480px;
|
||||
padding: 18px 124px 18px 20px;
|
||||
color: #e2e8f0;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
@@ -3464,7 +3469,6 @@ body {
|
||||
}
|
||||
|
||||
.system-log-console__placeholder {
|
||||
min-height: 480px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -3472,14 +3476,24 @@ body {
|
||||
}
|
||||
|
||||
.logs-page {
|
||||
--logs-filter-toggle-size: 32px;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.logs-page__header-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.logs-page .page-shell__header {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.logs-page__header-desc {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.logs-page__card {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
@@ -3492,6 +3506,7 @@ body {
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.logs-page__card-body {
|
||||
@@ -3499,36 +3514,27 @@ body {
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.logs-page__summary-card {
|
||||
flex: 0 0 auto;
|
||||
padding: 12px 14px;
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fafafa 100%);
|
||||
border: 1px solid rgba(5, 5, 5, 0.06);
|
||||
}
|
||||
|
||||
.logs-page__summary-header {
|
||||
.logs-page__console-shell {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 6px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.logs-page__toolbar {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
padding: 14px 16px;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(245, 247, 250, 0.98) 100%);
|
||||
border: 1px solid rgba(5, 5, 5, 0.08);
|
||||
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.05);
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(247, 249, 252, 0.98) 100%);
|
||||
border: 1px solid rgba(5, 5, 5, 0.07);
|
||||
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row {
|
||||
@@ -3540,7 +3546,9 @@ body {
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--primary {
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(180px, 220px) minmax(220px, 280px) minmax(280px, 1fr) var(--logs-filter-toggle-size);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logs-page__source-select {
|
||||
@@ -3549,12 +3557,13 @@ body {
|
||||
}
|
||||
|
||||
.logs-page__search-input {
|
||||
width: min(560px, 100%);
|
||||
min-width: 220px;
|
||||
width: 100%;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
.logs-page__level-select {
|
||||
width: 220px;
|
||||
width: 100%;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.logs-page__date-range {
|
||||
@@ -3565,15 +3574,62 @@ body {
|
||||
width: 156px;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--search .logs-page__search-input {
|
||||
flex: 1 1 auto;
|
||||
.logs-page__filter-toggle {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
width: var(--logs-filter-toggle-size);
|
||||
height: var(--logs-filter-toggle-size);
|
||||
padding: 0;
|
||||
border: 1px solid rgba(5, 5, 5, 0.08);
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
cursor: pointer;
|
||||
transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
|
||||
}
|
||||
|
||||
.logs-page__filter-toggle:hover {
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
border-color: rgba(5, 5, 5, 0.16);
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.logs-page__filter-toggle.is-expanded {
|
||||
color: #1677ff;
|
||||
border-color: rgba(22, 119, 255, 0.28);
|
||||
background: rgba(22, 119, 255, 0.06);
|
||||
}
|
||||
|
||||
.logs-page__filters-panel {
|
||||
border-top: 1px solid rgba(5, 5, 5, 0.06);
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--secondary {
|
||||
display: grid;
|
||||
grid-template-columns: 156px minmax(260px, 320px) minmax(0, 1fr);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.logs-page__preset-group {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.logs-page__preset-group .ant-space-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logs-page__preset-group .ant-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
@@ -3620,6 +3676,74 @@ body {
|
||||
border-top: 1px solid rgba(5, 5, 5, 0.06);
|
||||
}
|
||||
|
||||
@media (max-width: 1440px), (max-height: 900px) {
|
||||
.logs-page {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.logs-page__header-desc {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logs-page__card .ant-card-body {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.logs-page__toolbar {
|
||||
padding: 8px 10px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--primary {
|
||||
grid-template-columns: minmax(160px, 200px) minmax(180px, 220px) minmax(0, 1fr) var(--logs-filter-toggle-size);
|
||||
grid-template-areas:
|
||||
"source level search toggle";
|
||||
row-gap: 8px;
|
||||
}
|
||||
|
||||
.logs-page__source-select,
|
||||
.logs-page__line-limit-select,
|
||||
.logs-page__level-select,
|
||||
.logs-page__search-input {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.logs-page__source-select {
|
||||
grid-area: source;
|
||||
}
|
||||
|
||||
.logs-page__level-select {
|
||||
grid-area: level;
|
||||
}
|
||||
|
||||
.logs-page__search-input {
|
||||
grid-area: search;
|
||||
}
|
||||
|
||||
.logs-page__filter-toggle {
|
||||
grid-area: toggle;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--secondary {
|
||||
grid-template-columns: 140px minmax(240px, 280px) minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.logs-page__date-range {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.logs-page__console-shell {
|
||||
min-height: clamp(340px, 58vh, 760px);
|
||||
}
|
||||
|
||||
.system-log-console__content {
|
||||
padding: 16px 112px 16px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dashboard-restart-toolbar__meta {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -3630,8 +3754,14 @@ body {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--primary {
|
||||
flex-wrap: wrap;
|
||||
.logs-page__card .ant-card-body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.logs-page__toolbar-row--primary,
|
||||
.logs-page__toolbar-row--secondary {
|
||||
grid-template-columns: 1fr;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.logs-page__source-select,
|
||||
@@ -3641,4 +3771,8 @@ body {
|
||||
.logs-page__line-limit-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logs-page__console-shell {
|
||||
min-height: clamp(280px, 50vh, 620px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Alert, Button, Card, DatePicker, Empty, Input, InputNumber, Select, Space, Spin, Tag, Tooltip, Typography, message } from 'antd'
|
||||
import { CopyOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { CopyOutlined, DownOutlined, InfoCircleOutlined, ReloadOutlined, UpOutlined } from '@ant-design/icons'
|
||||
import axios from 'axios'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import type { CustomTagProps } from 'rc-select/lib/BaseSelect'
|
||||
@@ -104,12 +104,6 @@ function readStoredFilters() {
|
||||
}
|
||||
}
|
||||
|
||||
function getStatusTagColor(status: string): string {
|
||||
if (status === 'ok') return 'success'
|
||||
if (status === 'missing') return 'warning'
|
||||
return 'default'
|
||||
}
|
||||
|
||||
function getStatusLabel(status: string): string {
|
||||
if (status === 'ok') return '可用'
|
||||
if (status === 'missing') return '暂无日志'
|
||||
@@ -173,6 +167,12 @@ function Logs() {
|
||||
const [sourcesLoading, setSourcesLoading] = useState(false)
|
||||
const [logLoading, setLogLoading] = useState(false)
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||
const [filtersExpanded, setFiltersExpanded] = useState(
|
||||
Boolean(
|
||||
storedFilters?.selectedLevels?.length
|
||||
|| (storedFilters?.selectedDateRange?.[0] && storedFilters?.selectedDateRange?.[1]),
|
||||
),
|
||||
)
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
|
||||
const fetchSources = async () => {
|
||||
@@ -279,6 +279,7 @@ function Logs() {
|
||||
const currentResultLines = snapshot?.lines || []
|
||||
const lineCountLabel = currentResultLines.length
|
||||
const hasDateFilter = Boolean(selectedDateRange?.[0] && selectedDateRange?.[1])
|
||||
const hasAdvancedFilters = selectedLevels.length > 0 || hasDateFilter
|
||||
const effectiveLevelLabels = selectedLevels.length === 0
|
||||
? ['ALL']
|
||||
: normalizeSelectedLevels(selectedLevels).map(
|
||||
@@ -309,8 +310,8 @@ function Logs() {
|
||||
<div className="page-shell logs-page">
|
||||
<div className="page-shell__header">
|
||||
<div className="logs-page__header-copy">
|
||||
<Title level={3} style={{ marginBottom: 4 }}>系统日志</Title>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
|
||||
<Title level={3} style={{ marginBottom: 2 }}>系统日志</Title>
|
||||
<Paragraph type="secondary" className="logs-page__header-desc" style={{ marginBottom: 0 }}>
|
||||
统一查看 Planet 当前关键服务日志,并串联 Earth 浏览器端错误、后端异常与服务输出。
|
||||
</Paragraph>
|
||||
</div>
|
||||
@@ -344,27 +345,6 @@ function Logs() {
|
||||
tagRender={renderLevelTag}
|
||||
placeholder="全部级别"
|
||||
/>
|
||||
<Select
|
||||
value={lineLimit}
|
||||
onChange={(value) => setLineLimit(Number(value))}
|
||||
options={LOG_LIMIT_OPTIONS.map((value) => ({ value, label: `最近 ${value} 行` }))}
|
||||
className="logs-page__line-limit-select"
|
||||
dropdownRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<div className="logs-page__line-limit-customizer">
|
||||
<Text type="secondary">自定义行数</Text>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={1000}
|
||||
value={lineLimit}
|
||||
onChange={(value) => setLineLimit(Number(value) || 200)}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<Input.Search
|
||||
allowClear
|
||||
value={searchQuery}
|
||||
@@ -373,81 +353,118 @@ function Logs() {
|
||||
placeholder="搜索日志内容、模块名、错误关键字"
|
||||
className="logs-page__search-input"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className={`logs-page__filter-toggle ${filtersExpanded ? 'is-expanded' : ''}`}
|
||||
onClick={() => setFiltersExpanded((value) => !value)}
|
||||
aria-expanded={filtersExpanded}
|
||||
aria-label={filtersExpanded ? '收起筛选' : '展开筛选'}
|
||||
title={hasAdvancedFilters ? '筛选已启用' : '更多筛选'}
|
||||
>
|
||||
{filtersExpanded ? <UpOutlined /> : <DownOutlined />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="logs-page__toolbar-row logs-page__toolbar-row--secondary">
|
||||
<RangePicker
|
||||
allowClear
|
||||
value={selectedDateRange}
|
||||
onChange={(value) => setSelectedDateRange(normalizeDateRange(value as [Dayjs | null, Dayjs | null] | null))}
|
||||
cellRender={(current, info) => {
|
||||
if (info.type !== 'date' || !isDayjsValue(current)) return info.originNode
|
||||
{filtersExpanded ? (
|
||||
<div className="logs-page__filters-panel">
|
||||
<div className="logs-page__toolbar-row logs-page__toolbar-row--secondary">
|
||||
<Select
|
||||
value={lineLimit}
|
||||
onChange={(value) => setLineLimit(Number(value))}
|
||||
options={LOG_LIMIT_OPTIONS.map((value) => ({ value, label: `最近 ${value} 行` }))}
|
||||
className="logs-page__line-limit-select"
|
||||
popupRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<div className="logs-page__line-limit-customizer">
|
||||
<Text type="secondary">自定义行数</Text>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={1000}
|
||||
value={lineLimit}
|
||||
onChange={(value) => setLineLimit(Number(value) || 200)}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<RangePicker
|
||||
allowClear
|
||||
value={selectedDateRange}
|
||||
onChange={(value) => setSelectedDateRange(normalizeDateRange(value as [Dayjs | null, Dayjs | null] | null))}
|
||||
cellRender={(current, info) => {
|
||||
if (info.type !== 'date' || !isDayjsValue(current)) return info.originNode
|
||||
|
||||
const marker = dailyLogMarkers.get(current.format('YYYY-MM-DD'))
|
||||
if (!marker) return info.originNode
|
||||
const marker = dailyLogMarkers.get(current.format('YYYY-MM-DD'))
|
||||
if (!marker) return info.originNode
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`logs-page__calendar-cell logs-page__calendar-cell--${marker.dominantLevel}`}
|
||||
title={`${current.format('YYYY-MM-DD')} · ${marker.total} lines`}
|
||||
return (
|
||||
<div
|
||||
className={`logs-page__calendar-cell logs-page__calendar-cell--${marker.dominantLevel}`}
|
||||
title={`${current.format('YYYY-MM-DD')} · ${marker.total} lines`}
|
||||
>
|
||||
{info.originNode}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
format="YYYY-MM-DD"
|
||||
placeholder={['开始日期', '结束日期']}
|
||||
className="logs-page__date-range"
|
||||
/>
|
||||
<Space size={6} className="logs-page__preset-group">
|
||||
{DATE_PRESET_OPTIONS.map((option) => (
|
||||
<Button
|
||||
key={option.key}
|
||||
size="small"
|
||||
type={activeDatePreset === option.key ? 'primary' : 'default'}
|
||||
onClick={() => applyDatePreset(option.days)}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSelectedDateRange(null)}
|
||||
disabled={!hasDateFilter}
|
||||
>
|
||||
{info.originNode}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
format="YYYY-MM-DD"
|
||||
placeholder={['开始日期', '结束日期']}
|
||||
className="logs-page__date-range"
|
||||
/>
|
||||
<Space size={6} className="logs-page__preset-group">
|
||||
{DATE_PRESET_OPTIONS.map((option) => (
|
||||
<Button
|
||||
key={option.key}
|
||||
size="small"
|
||||
type={activeDatePreset === option.key ? 'primary' : 'default'}
|
||||
onClick={() => applyDatePreset(option.days)}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setSelectedDateRange(null)}
|
||||
disabled={!hasDateFilter}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
Clear
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="logs-page__summary-card">
|
||||
<div className="logs-page__summary-header">
|
||||
<Space wrap size={8}>
|
||||
<Text strong>{snapshot?.name || selectedMeta?.name || '未选择日志源'}</Text>
|
||||
<Tag color={getStatusTagColor(snapshot?.status || selectedMeta?.status || 'default')}>
|
||||
{getStatusLabel(snapshot?.status || selectedMeta?.status || 'default')}
|
||||
</Tag>
|
||||
<Tag>{(snapshot?.kind || selectedMeta?.kind || 'unknown').toUpperCase()}</Tag>
|
||||
<Text type="secondary">当前显示 {lineCountLabel} 行</Text>
|
||||
</Space>
|
||||
</div>
|
||||
<Space direction="vertical" size={4} style={{ width: '100%' }}>
|
||||
<Text type="secondary">{snapshot?.description || selectedMeta?.description || '-'}</Text>
|
||||
<Text type="secondary">
|
||||
位置: {snapshot?.location || selectedMeta?.location || '-'}
|
||||
{selectedLevels.length > 0 ? ` · 级别: ${effectiveLevelLabels.join(' / ')}` : ''}
|
||||
{selectedDateRange?.[0] && selectedDateRange?.[1]
|
||||
? ` · 日期: ${selectedDateRange[0].format('YYYY-MM-DD')} ~ ${selectedDateRange[1].format('YYYY-MM-DD')}`
|
||||
: ''}
|
||||
{searchQuery.trim() ? ` · 检索: ${searchQuery.trim()}` : ''}
|
||||
</Text>
|
||||
{statusHelp ? <Alert type="info" showIcon message={statusHelp} /> : null}
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div className="system-log-console">
|
||||
<div className="logs-page__console-shell">
|
||||
<div className="system-log-console">
|
||||
<div className="system-log-console__actions">
|
||||
<Tooltip
|
||||
title={
|
||||
<>
|
||||
<div><strong>{snapshot?.name || selectedMeta?.name || '未选择日志源'}</strong></div>
|
||||
<div>状态: {getStatusLabel(snapshot?.status || selectedMeta?.status || 'default')}</div>
|
||||
<div>类型: {(snapshot?.kind || selectedMeta?.kind || 'unknown').toUpperCase()}</div>
|
||||
<div>当前显示: {lineCountLabel} 行</div>
|
||||
{selectedLevels.length > 0 ? <div>级别: {effectiveLevelLabels.join(' / ')}</div> : null}
|
||||
{selectedDateRange?.[0] && selectedDateRange?.[1]
|
||||
? <div>日期: {selectedDateRange[0].format('YYYY-MM-DD')} ~ {selectedDateRange[1].format('YYYY-MM-DD')}</div>
|
||||
: null}
|
||||
{searchQuery.trim() ? <div>检索: {searchQuery.trim()}</div> : null}
|
||||
<div>{snapshot?.description || selectedMeta?.description || '-'}</div>
|
||||
<div>位置: {snapshot?.location || selectedMeta?.location || '-'}</div>
|
||||
{statusHelp ? <div>{statusHelp}</div> : null}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
shape="circle"
|
||||
icon={<InfoCircleOutlined />}
|
||||
className="playground-message__actions-btn"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="刷新日志">
|
||||
<Button
|
||||
type="text"
|
||||
@@ -503,6 +520,7 @@ function Logs() {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user