Update: Js 4 Log.html 95% --next move the loglevel to settingserver

This commit is contained in:
XOF
2025-11-27 00:51:04 +08:00
parent c86e7a7ba4
commit 166437c0ac
26 changed files with 20500 additions and 2435 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -449,6 +449,9 @@
.z-50 {
z-index: 50;
}
.z-1000 {
z-index: 1000;
}
.z-\[100\] {
z-index: 100;
}
@@ -503,6 +506,9 @@
.my-2 {
margin-block: calc(var(--spacing) * 2);
}
.mt-0 {
margin-top: calc(var(--spacing) * 0);
}
.mt-0\.5 {
margin-top: calc(var(--spacing) * 0.5);
}
@@ -624,6 +630,9 @@
width: calc(var(--spacing) * 6);
height: calc(var(--spacing) * 6);
}
.h-0 {
height: calc(var(--spacing) * 0);
}
.h-0\.5 {
height: calc(var(--spacing) * 0.5);
}
@@ -708,6 +717,9 @@
.w-0 {
width: calc(var(--spacing) * 0);
}
.w-1 {
width: calc(var(--spacing) * 1);
}
.w-1\/4 {
width: calc(1/4 * 100%);
}
@@ -822,6 +834,9 @@
.flex-1 {
flex: 1;
}
.flex-shrink {
flex-shrink: 1;
}
.shrink-0 {
flex-shrink: 0;
}
@@ -834,6 +849,9 @@
.caption-bottom {
caption-side: bottom;
}
.border-collapse {
border-collapse: collapse;
}
.origin-center {
transform-origin: center;
}
@@ -860,6 +878,10 @@
--tw-translate-x: 100%;
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.-translate-y-1 {
--tw-translate-y: calc(var(--spacing) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.-translate-y-1\/2 {
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -1028,6 +1050,9 @@
margin-block-end: calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)));
}
}
.gap-x-1 {
column-gap: calc(var(--spacing) * 1);
}
.gap-x-1\.5 {
column-gap: calc(var(--spacing) * 1.5);
}
@@ -1180,6 +1205,9 @@
.\!border-primary {
border-color: var(--color-primary) !important;
}
.border-black {
border-color: var(--color-black);
}
.border-black\/10 {
border-color: color-mix(in srgb, #000 10%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1207,6 +1235,9 @@
.border-green-200 {
border-color: var(--color-green-200);
}
.border-primary {
border-color: var(--color-primary);
}
.border-primary\/20 {
border-color: var(--color-primary);
@supports (color: color-mix(in lab, red, red)) {
@@ -1243,12 +1274,18 @@
.border-zinc-300 {
border-color: var(--color-zinc-300);
}
.border-zinc-500 {
border-color: var(--color-zinc-500);
}
.border-zinc-500\/30 {
border-color: color-mix(in srgb, oklch(55.2% 0.016 285.938) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
border-color: color-mix(in oklab, var(--color-zinc-500) 30%, transparent);
}
}
.border-zinc-700 {
border-color: var(--color-zinc-700);
}
.border-zinc-700\/50 {
border-color: color-mix(in srgb, oklch(37% 0.013 285.805) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1324,6 +1361,9 @@
.bg-gray-500 {
background-color: var(--color-gray-500);
}
.bg-gray-950 {
background-color: var(--color-gray-950);
}
.bg-gray-950\/5 {
background-color: color-mix(in srgb, oklch(13% 0.028 261.692) 5%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1538,6 +1578,10 @@
--tw-gradient-position: to right in oklab;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.from-blue-500 {
--tw-gradient-from: var(--color-blue-500);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.from-blue-500\/30 {
--tw-gradient-from: color-mix(in srgb, oklch(62.3% 0.214 259.815) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1608,6 +1652,9 @@
.px-8 {
padding-inline: calc(var(--spacing) * 8);
}
.py-0 {
padding-block: calc(var(--spacing) * 0);
}
.py-0\.5 {
padding-block: calc(var(--spacing) * 0.5);
}
@@ -1656,6 +1703,9 @@
.pr-20 {
padding-right: calc(var(--spacing) * 20);
}
.pb-1 {
padding-bottom: calc(var(--spacing) * 1);
}
.pb-1\.5 {
padding-bottom: calc(var(--spacing) * 1.5);
}
@@ -1765,6 +1815,9 @@
.break-words {
overflow-wrap: break-word;
}
.wrap-break-word {
overflow-wrap: break-word;
}
.break-all {
word-break: break-all;
}
@@ -1949,6 +2002,9 @@
--tw-ordinal: ordinal;
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
}
.underline {
text-decoration-line: underline;
}
.opacity-0 {
opacity: 0%;
}
@@ -2010,6 +2066,10 @@
--tw-inset-shadow: inset 0 2px 4px var(--tw-inset-shadow-color, oklab(from rgb(0 0 0 / 0.05) l a b / 25%));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.inset-shadow-sm {
--tw-inset-shadow: inset 0 2px 4px var(--tw-inset-shadow-color, rgb(0 0 0 / 0.05));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-black {
--tw-ring-color: var(--color-black);
}
@@ -2034,12 +2094,19 @@
.ring-input {
--tw-ring-color: var(--color-input);
}
.ring-zinc-500 {
--tw-ring-color: var(--color-zinc-500);
}
.ring-zinc-500\/30 {
--tw-ring-color: color-mix(in srgb, oklch(55.2% 0.016 285.938) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
--tw-ring-color: color-mix(in oklab, var(--color-zinc-500) 30%, transparent);
}
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
@@ -2145,6 +2212,13 @@
.ring-inset {
--tw-ring-inset: inset;
}
.group-hover\:opacity-0 {
&:is(:where(.group):hover *) {
@media (hover: hover) {
opacity: 0%;
}
}
}
.group-hover\:opacity-100 {
&:is(:where(.group):hover *) {
@media (hover: hover) {
@@ -2152,6 +2226,38 @@
}
}
}
.even\:bg-zinc-50\/50 {
&:nth-child(even) {
background-color: color-mix(in srgb, oklch(98.5% 0 0) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-zinc-50) 50%, transparent);
}
}
}
.even\:bg-zinc-100\/50 {
&:nth-child(even) {
background-color: color-mix(in srgb, oklch(96.7% 0.001 286.375) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-zinc-100) 50%, transparent);
}
}
}
.even\:bg-zinc-200\/30 {
&:nth-child(even) {
background-color: color-mix(in srgb, oklch(92% 0.004 286.32) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-zinc-200) 30%, transparent);
}
}
}
.even\:bg-zinc-200\/50 {
&:nth-child(even) {
background-color: color-mix(in srgb, oklch(92% 0.004 286.32) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-zinc-200) 50%, transparent);
}
}
}
.focus-within\:border-blue-500 {
&:focus-within {
border-color: var(--color-blue-500);
@@ -3129,6 +3235,106 @@
}
}
}
.dark\:even\:bg-black\/5 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 5%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 5%, transparent);
}
}
}
}
.dark\:even\:bg-black\/10 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 10%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 10%, transparent);
}
}
}
}
.dark\:even\:bg-black\/20 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 20%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 20%, transparent);
}
}
}
}
.dark\:even\:bg-black\/30 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 30%, transparent);
}
}
}
}
.dark\:even\:bg-black\/50 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 50%, transparent);
}
}
}
}
.dark\:even\:bg-black\/60 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 60%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 60%, transparent);
}
}
}
}
.dark\:even\:bg-black\/90 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #000 90%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 90%, transparent);
}
}
}
}
.dark\:even\:bg-white\/5 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #fff 5%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 5%, transparent);
}
}
}
}
.dark\:even\:bg-white\/15 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #fff 15%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 15%, transparent);
}
}
}
}
.dark\:even\:bg-white\/50 {
&:where(.dark, .dark *) {
&:nth-child(even) {
background-color: color-mix(in srgb, #fff 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 50%, transparent);
}
}
}
}
.dark\:hover\:border-blue-400 {
&:where(.dark, .dark *) {
&:hover {
@@ -3448,7 +3654,6 @@
border-radius: var(--radius-lg);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: var(--color-border);
border-color: color-mix(in srgb, oklch(55.2% 0.016 285.938) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
border-color: color-mix(in oklab, var(--color-zinc-500) 30%, transparent);
@@ -3564,7 +3769,7 @@
font-weight: var(--font-weight-semibold);
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
width: 5.5rem;
width: calc(var(--spacing) * 22);
border-style: var(--tw-border-style);
border-width: 0px;
background-color: transparent;
@@ -4165,7 +4370,6 @@
transition-duration: 200ms;
}
.task-stage-content {
display: flex;
flex-grow: 1;
align-items: baseline;
justify-content: space-between;
@@ -4916,7 +5120,7 @@
.tag-input-container {
margin-top: calc(var(--spacing) * 1);
display: flex;
min-height: 40px;
min-height: calc(var(--spacing) * 10);
width: 100%;
flex-wrap: wrap;
align-items: center;
@@ -5582,6 +5786,11 @@
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-blur {
syntax: "*";
inherits: false;
@@ -5679,11 +5888,6 @@
syntax: "*";
inherits: false;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@keyframes spin {
to {
transform: rotate(360deg);
@@ -5749,6 +5953,7 @@
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-outline-style: solid;
--tw-blur: initial;
--tw-brightness: initial;
--tw-contrast: initial;
@@ -5773,7 +5978,6 @@
--tw-backdrop-sepia: initial;
--tw-duration: initial;
--tw-ease: initial;
--tw-outline-style: solid;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1609,7 +1609,7 @@ var LogList = class {
const requestTime = new Date(log.RequestTime).toLocaleString();
const checkedAttr = isChecked ? "checked" : "";
return `
<tr class="table-row" data-log-id="${log.ID}" ${errorMessageAttr}>
<tr class="table-row group" data-log-id="${log.ID}" ${errorMessageAttr}>
<td class="table-cell">
<input type="checkbox" class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500" ${checkedAttr}>
</td>
@@ -1620,10 +1620,26 @@ var LogList = class {
<td class="table-cell">${errorInfo.statusCodeHtml}</td>
<td class="table-cell">${modelNameFormatted}</td>
<td class="table-cell text-muted-foreground text-xs">${requestTime}</td>
<td class="table-cell">
<button class="btn btn-ghost btn-icon btn-sm" aria-label="\u67E5\u770B\u8BE6\u60C5">
<i class="fas fa-ellipsis-h h-4 w-4"></i>
</button>
<td class="table-cell relative">
<!-- [MODIFIED] - 2. \u66FF\u6362\u539F\u6709\u6309\u94AE\u4E3A\u60AC\u6D6E\u64CD\u4F5C\u83DC\u5355 -->
<div class="flex items-center justify-center">
<!-- \u9ED8\u8BA4\u663E\u793A\u7684\u56FE\u6807 -->
<span class="text-zinc-400 group-hover:opacity-0 transition-opacity">
<i class="fas fa-ellipsis-h h-4 w-4"></i>
</span>
<!-- \u60AC\u6D6E\u65F6\u663E\u793A\u7684\u64CD\u4F5C\u6309\u94AE -->
<div class="absolute right-2 top-1/2 -translate-y-1/2 flex items-center bg-zinc-100 dark:bg-zinc-700 rounded-full shadow-md opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10">
<button class="px-2 py-1 text-zinc-500 hover:text-blue-500" data-action="view-log-details" title="\u67E5\u770B\u8BE6\u60C5">
<i class="fas fa-eye"></i>
</button>
<button class="px-2 py-1 text-zinc-500 hover:text-green-500" data-action="copy-api-key" title="\u590D\u5236APIKey">
<i class="fas fa-copy"></i>
</button>
<button class="px-2 py-1 text-zinc-500 hover:text-red-500" data-action="delete-log" title="\u5220\u9664\u65E5\u5FD7">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</div>
</td>
</tr>
`;
@@ -2559,8 +2575,14 @@ var LogsPage = class {
this.elements.selectAllCheckbox.addEventListener("change", (event) => this.handleSelectAllChange(event));
}
if (this.elements.tableBody) {
this.elements.tableBody.addEventListener("change", (event) => {
if (event.target.type === "checkbox") this.handleSelectionChange(event.target);
this.elements.tableBody.addEventListener("click", (event) => {
const checkbox = event.target.closest('input[type="checkbox"]');
const actionButton = event.target.closest("button[data-action]");
if (checkbox) {
this.handleSelectionChange(checkbox);
} else if (actionButton) {
this._handleLogRowAction(actionButton);
}
});
}
if (this.elements.searchInput) {
@@ -2663,6 +2685,115 @@ var LogsPage = class {
deleteSelectedBtn.disabled = !hasSelection;
}
}
async _handleLogRowAction(button) {
const action = button.dataset.action;
const row = button.closest(".table-row");
const isDarkMode = document.documentElement.classList.contains("dark");
if (!row) return;
const logId = parseInt(row.dataset.logId, 10);
const log = this.state.logs.find((l) => l.ID === logId);
if (!log) {
Swal.fire({ toast: true, position: "top-end", icon: "error", title: "\u627E\u4E0D\u5230\u65E5\u5FD7\u6570\u636E", showConfirmButton: false, timer: 2e3 });
return;
}
switch (action) {
case "view-log-details": {
const detailsHtml = `
<div class="space-y-3 text-left text-sm p-2">
<div class="flex"><p class="w-24 font-semibold text-zinc-500 shrink-0">\u72B6\u6001\u7801</p><p class="font-mono text-zinc-800 dark:text-zinc-200">${log.StatusCode || "N/A"}</p></div>
<div class="flex"><p class="w-24 font-semibold text-zinc-500 shrink-0">\u72B6\u6001</p><p class="font-mono text-zinc-800 dark:text-zinc-200">${log.Status || "N/A"}</p></div>
<div class="flex"><p class="w-24 font-semibold text-zinc-500 shrink-0">\u6A21\u578B</p><p class="font-mono text-zinc-800 dark:text-zinc-200">${log.ModelName || "N/A"}</p></div>
<div class="border-t border-zinc-200 dark:border-zinc-700 my-2"></div>
<div>
<p class="font-semibold text-zinc-500 mb-1">\u9519\u8BEF\u6D88\u606F</p>
<div class="max-h-40 overflow-y-auto bg-zinc-100 dark:bg-zinc-800 p-2 rounded-md text-zinc-700 dark:text-zinc-300 break-words text-xs">
${log.ErrorMessage ? log.ErrorMessage.replace(/\n/g, "<br>") : "\u65E0\u9519\u8BEF\u6D88\u606F\u3002"}
</div>
</div>
</div>
`;
Swal.fire({
target: "#main-content-wrapper",
width: "32rem",
backdrop: `rgba(0,0,0,0.5)`,
heightAuto: false,
customClass: {
popup: `swal2-custom-style rounded-xl ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}`,
title: "text-lg font-bold",
htmlContainer: "m-0 text-left"
},
title: "\u65E5\u5FD7\u8BE6\u60C5",
html: detailsHtml,
showCloseButton: false,
showConfirmButton: false
});
break;
}
case "copy-api-key": {
const key = dataStore.keys.get(log.KeyID);
if (key && key.APIKey) {
navigator.clipboard.writeText(key.APIKey).then(() => {
Swal.fire({ toast: true, position: "top-end", customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` }, icon: "success", title: "API Key \u5DF2\u590D\u5236", showConfirmButton: false, timer: 1500 });
}).catch((err) => {
Swal.fire({ toast: true, position: "top-end", icon: "error", title: "\u590D\u5236\u5931\u8D25", text: err.message, showConfirmButton: false, timer: 2e3 });
});
} else {
Swal.fire({ toast: true, position: "top-end", icon: "warning", title: "\u672A\u627E\u5230\u5B8C\u6574\u7684API Key", showConfirmButton: false, timer: 2e3 });
return;
}
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(key.APIKey).then(() => {
Swal.fire({ toast: true, position: "top-end", icon: "success", title: "API Key \u5DF2\u590D\u5236", showConfirmButton: false, timer: 1500 });
}).catch((err) => {
Swal.fire({ toast: true, position: "top-end", icon: "error", title: "\u590D\u5236\u5931\u8D25", text: err.message, showConfirmButton: false, timer: 2e3 });
});
} else {
Swal.fire({
icon: "error",
title: "\u590D\u5236\u5931\u8D25",
text: "\u6B64\u529F\u80FD\u9700\u8981\u5B89\u5168\u8FDE\u63A5 (HTTPS) \u6216\u5728 localhost \u73AF\u5883\u4E0B\u4F7F\u7528\u3002",
target: "#main-content-wrapper",
customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` }
});
}
break;
}
case "delete-log": {
Swal.fire({
width: "20rem",
backdrop: `rgba(0,0,0,0.5)`,
heightAuto: false,
customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` },
title: "\u786E\u8BA4\u5220\u9664",
text: `\u60A8\u786E\u5B9A\u8981\u5220\u9664\u8FD9\u6761\u65E5\u5FD7\u5417\uFF1F\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\u3002`,
showCancelButton: true,
confirmButtonText: "\u786E\u8BA4\u5220\u9664",
cancelButtonText: "\u53D6\u6D88",
reverseButtons: false,
confirmButtonColor: "#ef4444",
cancelButtonColor: "#6b7280",
focusCancel: true,
target: "#main-content-wrapper"
}).then(async (result) => {
if (result.isConfirmed) {
try {
const url = `/admin/logs?ids=${logId}`;
const { success, message } = await apiFetchJson(url, { method: "DELETE" });
if (success) {
Swal.fire({ toast: true, position: "top-end", icon: "success", title: "\u5220\u9664\u6210\u529F", showConfirmButton: false, timer: 2e3, timerProgressBar: true });
this.loadAndRenderLogs();
} else {
throw new Error(message || "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
}
} catch (error) {
Swal.fire({ icon: "error", title: "\u64CD\u4F5C\u5931\u8D25", text: error.message, target: "#main-content-wrapper" });
}
}
});
break;
}
}
}
changePageSize(newSize) {
this.state.filters.page_size = newSize;
this.state.filters.page = 1;

1237
web/static/js/main.css Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,13 @@
<link href="/static/css/output.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.cn/css2?family=Pixelify+Sans:wght@400..700&family=QuinqueFive&display=swap">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="stylesheet" href="/static/vendor/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/static/js/main.css">
<style>
.fas, .fa-solid {
font-display: swap;
}
</style>
<title>{% block title %}GEMINI BALANCER{% endblock %}</title>
{% block head_extra %}{% endblock %}
@@ -122,8 +128,6 @@
</div>
{% block core_scripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.23.0/sweetalert2.all.min.js"></script>
<script src="/static/js/main.js" type="module" defer></script>
{% endblock core_scripts %}
<!-- [核心] Block 2: 留给子页面的脚本扩展插槽 -->

View File

@@ -91,8 +91,8 @@
</div>
</div>
<!-- [新增] 3.2 系统日志的快捷操作栏 (默认隐藏) -->
<div id="system-logs-controls" class="hidden flex items-center justify-end shrink-0 py-4 space-x-4">
<!--3.2 系统日志的快捷操作栏 (默认隐藏) -->
<div id="system-logs-controls" class="flex items-center justify-end shrink-0 py-4 space-x-4">
<div id="terminal-status-indicator" class="flex items-center text-xs text-zinc-500 dark:text-zinc-400">
<span class="relative flex h-2 w-2 mr-2">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-zinc-400 dark:bg-zinc-500 opacity-75"></span>