diff --git a/src/api/DockerAPI.ts b/src/api/DockerAPI.ts index 777a9df..379a7ab 100644 --- a/src/api/DockerAPI.ts +++ b/src/api/DockerAPI.ts @@ -1,35 +1,24 @@ -import { axios } from "timi-web"; +import { axios, Text } from "timi-web"; import { useSettingStore } from "@/store/settingStore"; -import type { - DockerContainerHistoryView, - DockerContainerStatusView, - DockerContainerSummaryView -} from "@/types/Docker"; +import type { DockerContainerHistoryView, DockerContainerStatusView, DockerContainerSummaryView } from "@/types/Docker"; async function getContainers(): Promise { const settingStore = useSettingStore(); - return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container`, { - timeout: 15000 - }); + return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container`); } async function getContainerStatus(containerId: string): Promise { const settingStore = useSettingStore(); - return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container/${encodeURIComponent(containerId)}/status`, { - timeout: 15000 - }); + return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container/${encodeURIComponent(containerId)}/status`); } async function getContainerHistory(containerId: string, params?: { window?: string; }): Promise { const settingStore = useSettingStore(); - return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container/${encodeURIComponent(containerId)}/history`, { - params: { - ...(params?.window ? { window: params.window } : {}) - }, - timeout: 15000 - }); + return await axios.get(`${settingStore.resolveBaseURL()}/system/docker/container/${encodeURIComponent(containerId)}/history?${Text.urlArgs({ + window: params?.window + })}`); } export default { diff --git a/src/components/ProgressGroup.vue b/src/components/ProgressGroup.vue index 5a5547c..3df1455 100644 --- a/src/components/ProgressGroup.vue +++ b/src/components/ProgressGroup.vue @@ -29,7 +29,7 @@ }" /> -
+
(() => { transition: width 320ms var(--tui-bezier); } - .note { + .health { top: 50%; right: .25rem; z-index: 2; diff --git a/src/pages/dashboard/DockerDashboard/DockerContainerDetail.vue b/src/pages/dashboard/DockerDashboard/DockerContainerDetail.vue new file mode 100644 index 0000000..20771cd --- /dev/null +++ b/src/pages/dashboard/DockerDashboard/DockerContainerDetail.vue @@ -0,0 +1,762 @@ + + + + + diff --git a/src/pages/dashboard/DockerDashboard/DockerDashboard.vue b/src/pages/dashboard/DockerDashboard/DockerDashboard.vue index debb2db..999c186 100644 --- a/src/pages/dashboard/DockerDashboard/DockerDashboard.vue +++ b/src/pages/dashboard/DockerDashboard/DockerDashboard.vue @@ -4,188 +4,67 @@
- - - - -
- -
- - -
@@ -789,10 +182,48 @@ async function handleSelectContainer(containerId: string): Promise { .docker-dashboard { gap: 1rem; display: flex; + padding: 0 0 1rem 0; flex-direction: column; .section { + &.overview { + gap: .6rem; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + + .stat { + gap: .25rem; + display: flex; + padding: .5rem; + border-radius: .5rem; + flex-direction: column; + + .label { + color: var(--app-sub); + font-size: .72rem; + } + + .value { + font-size: .95rem; + font-weight: 700; + color: var(--app-text); + + &.ok { + color: #047857; + } + + &.err { + color: #b42318; + } + + &.wait { + color: #8a5b00; + } + } + } + } + &.list { gap: .6rem; display: grid; @@ -807,94 +238,69 @@ async function handleSelectContainer(containerId: string): Promise { text-align: left; border-radius: .75rem; flex-direction: column; - background: var(--app-bg-soft, #f6f7f9); - &.active { - background: color-mix(in srgb, var(--td-brand-color) 12%, var(--app-bg-soft, #f6f7f9)); - box-shadow: 0 0 0 1px color-mix(in srgb, var(--td-brand-color) 45%, transparent); - } - - .top, - .bottom { + .header, + .content { gap: .45rem; display: flex; align-items: center; justify-content: space-between; } - .name { - flex: 1; - color: var(--app-text); - font-size: .85rem; - font-weight: 700; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + .header { + + .name { + flex: 1; + color: var(--app-text); + font-size: .85rem; + font-weight: 700; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .state { + flex: none; + padding: .1rem .4rem; + border-radius: .25rem; + + &.ok { + color: #047857; + background: rgba(16, 185, 129, .15); + } + + &.err { + color: #b42318; + background: rgba(250, 76, 76, .14); + } + + &.wait { + color: #8a5b00; + background: rgba(245, 158, 11, .18); + } + } } .img, - .note { + .health { color: var(--app-sub); font-size: .72rem; } - .img { - flex: 1; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } + .bottom { + display: flex; + align-items: center; + justify-content: space-between; - .state { - flex: none; - padding: .1rem .4rem; - border-radius: .5rem; - - &.ok { - color: #047857; - background: rgba(16, 185, 129, .15); + .id { + color: var(--app-sub); + font-size: .72rem; } - &.err { - color: #b42318; - background: rgba(250, 76, 76, .14); + .goto { + color: var(--td-brand-color); + font-size: .72rem; } - - &.wait { - color: #8a5b00; - background: rgba(245, 158, 11, .18); - } - } - } - } - - &.history { - - .metric-tabs { - width: 100%; - --td-tab-track-width: 4rem; - } - - .chart { - width: 100%; - height: 16rem; - background: #FFF; - } - - .slider { - gap: .5rem; - display: flex; - padding: .5rem 2rem; - align-items: center; - - .label { - flex: none; - font-size: .75rem; - color: var(--app-sub); - } - - .control { - flex: 1; } } } @@ -911,10 +317,6 @@ async function handleSelectContainer(containerId: string): Promise { :global(.theme-dark) .docker-dashboard .section.list .chip { background: rgba(255, 255, 255, .06); - &.active { - background: color-mix(in srgb, var(--td-brand-color) 20%, rgba(255, 255, 255, .06)); - } - .state { &.ok { @@ -930,4 +332,23 @@ async function handleSelectContainer(containerId: string): Promise { } } } + +:global(.theme-dark) .docker-dashboard .section.overview .stat { + background: rgba(255, 255, 255, .06); + + .value { + + &.ok { + color: #86efac; + } + + &.err { + color: #fda4af; + } + + &.wait { + color: #fcd34d; + } + } +} diff --git a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue index a8fc318..9de45ce 100644 --- a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue +++ b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue @@ -733,7 +733,7 @@ onMounted(restartAutoRefresh); font-weight: bold; } - .note { + .health { font-size: .75rem; color: var(--app-sub); } diff --git a/src/pages/file/FileExplorerGrid.vue b/src/pages/file/FileExplorerGrid.vue index 7d0a90a..8d9e6ba 100644 --- a/src/pages/file/FileExplorerGrid.vue +++ b/src/pages/file/FileExplorerGrid.vue @@ -6,7 +6,7 @@ key-field="key" > @@ -94,11 +94,11 @@ function handleOpen(item: ExplorerItem): void { width: 100%; pointer-events: none; - &.top { + &.header { height: var(--top-gap); } - &.bottom { + &.content { height: var(--bottom-gap); } } diff --git a/src/pages/file/FileExplorerList.vue b/src/pages/file/FileExplorerList.vue index 46d7791..9693ac3 100644 --- a/src/pages/file/FileExplorerList.vue +++ b/src/pages/file/FileExplorerList.vue @@ -6,7 +6,7 @@ key-field="path" > @@ -145,16 +145,16 @@ function handlePlay(item: ExplorerItem): void { width: 100%; pointer-events: none; - &.top { + &.header { height: var(--top-gap); } - &.bottom { + &.content { height: var(--bottom-gap); } } - .note { + .health { gap: .375rem; display: flex; flex: 0 0 auto; diff --git a/src/router/index.ts b/src/router/index.ts index e087595..0aa871d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -13,6 +13,7 @@ import ThemeSetting from "@/pages/setting/ThemeSetting.vue"; import ServerDetail from "@/pages/dashboard/ServerDashboard/ServerDetail.vue"; import ServerPerformanceDetail from "@/pages/dashboard/ServerDashboard/ServerPerformanceDetail.vue"; import ServerPartitionsDetail from "@/pages/dashboard/ServerDashboard/ServerPartitionsDetail.vue"; +import DockerContainerDetail from "@/pages/dashboard/DockerDashboard/DockerContainerDetail.vue"; const router = createRouter({ history: createWebHistory("/"), @@ -109,6 +110,19 @@ const router = createRouter({ }, component: ServerPartitionsDetail }, + { + path: "/server/docker-container-detail", + name: "DockerContainerDetail", + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "容器详情", + tabBarVisible: false, + bodyBackground: "#F4F4F4" + }, + component: DockerContainerDetail + }, { path: "/settings/connect", name: "ConnectSetting", diff --git a/src/types/Docker.ts b/src/types/Docker.ts index cc70b3d..364f242 100644 --- a/src/types/Docker.ts +++ b/src/types/Docker.ts @@ -4,13 +4,13 @@ export interface DockerContainerSummaryView { image: string; state: string; status: string; - healthStatus?: string | null; - cpuPercent?: number | null; - memoryUsageBytes?: number | null; - memoryLimitBytes?: number | null; - memoryPercent?: number | null; - networkRxBytes?: number | null; - networkTxBytes?: number | null; + healthStatus?: string; + cpuPercent?: number; + memoryUsageBytes?: number; + memoryLimitBytes?: number; + memoryPercent?: number; + networkRxBytes?: number; + networkTxBytes?: number; updatedAt: number; } @@ -22,21 +22,21 @@ export interface DockerContainerStatusView { createdAt: number; state: string; status: string; - healthStatus?: string | null; - startedAt?: string | null; - finishedAt?: string | null; - exitCode?: number | null; + healthStatus?: string; + startedAt?: string; + finishedAt?: string; + exitCode?: number; restartCount: number; oomKilled: boolean; - cpuPercent?: number | null; - memoryUsageBytes?: number | null; - memoryLimitBytes?: number | null; - memoryPercent?: number | null; - networkRxBytes?: number | null; - networkTxBytes?: number | null; - blockReadBytes?: number | null; - blockWriteBytes?: number | null; - pids?: number | null; + cpuPercent?: number; + memoryUsageBytes?: number; + memoryLimitBytes?: number; + memoryPercent?: number; + networkRxBytes?: number; + networkTxBytes?: number; + blockReadBytes?: number; + blockWriteBytes?: number; + pids?: number; updatedAt: number; } @@ -52,12 +52,12 @@ export interface DockerContainerHistoryView { export interface DockerContainerHistoryPointView { at: number; - cpuPercent?: number | null; - memoryUsageBytes?: number | null; - memoryPercent?: number | null; - networkRxBytes?: number | null; - networkTxBytes?: number | null; - blockReadBytes?: number | null; - blockWriteBytes?: number | null; - pids?: number | null; + cpuPercent?: number; + memoryUsageBytes?: number; + memoryPercent?: number; + networkRxBytes?: number; + networkTxBytes?: number; + blockReadBytes?: number; + blockWriteBytes?: number; + pids?: number; }