928 lines
30 KiB
HTML
928 lines
30 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{% block title %}机器人管理后台{% endblock %}</title>
|
|
<link rel="icon" href="/static/favicon.ico">
|
|
|
|
<style>
|
|
:root {
|
|
--bg: #f4f7fb;
|
|
--bg-soft: #eef3f8;
|
|
--surface: rgba(255, 255, 255, 0.86);
|
|
--surface-strong: #ffffff;
|
|
--surface-muted: #f8fafc;
|
|
--border: rgba(148, 163, 184, 0.18);
|
|
--border-strong: rgba(148, 163, 184, 0.26);
|
|
--text: #0f172a;
|
|
--text-soft: #475569;
|
|
--text-faint: #94a3b8;
|
|
--primary: #4f46e5;
|
|
--primary-soft: rgba(79, 70, 229, 0.10);
|
|
--primary-soft-2: rgba(99, 102, 241, 0.16);
|
|
--info: #3b82f6;
|
|
--success: #10b981;
|
|
--warning: #f59e0b;
|
|
--danger: #ef4444;
|
|
--shadow-sm: 0 8px 24px rgba(15, 23, 42, 0.06);
|
|
--shadow-md: 0 18px 48px rgba(15, 23, 42, 0.08);
|
|
--radius-xs: 10px;
|
|
--radius-sm: 14px;
|
|
--radius-md: 18px;
|
|
--radius-lg: 24px;
|
|
--topbar-height: 72px;
|
|
--subnav-height: 64px;
|
|
--content-padding: 24px;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html, body {
|
|
height: 100%;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
min-height: 100vh;
|
|
overflow: hidden;
|
|
color: var(--text);
|
|
background:
|
|
radial-gradient(circle at top left, rgba(99, 102, 241, 0.10), transparent 28%),
|
|
radial-gradient(circle at top right, rgba(56, 189, 248, 0.08), transparent 24%),
|
|
linear-gradient(180deg, #f8fafc 0%, #f3f6fb 100%);
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6, p {
|
|
margin: 0;
|
|
}
|
|
|
|
.app-container {
|
|
min-height: 100vh;
|
|
opacity: 0;
|
|
transition: opacity .24s ease;
|
|
}
|
|
|
|
.app-container.loaded {
|
|
opacity: 1;
|
|
}
|
|
|
|
.topbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 200;
|
|
height: var(--topbar-height);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 18px;
|
|
padding: 0 24px;
|
|
background: rgba(255, 255, 255, 0.72);
|
|
backdrop-filter: blur(18px);
|
|
-webkit-backdrop-filter: blur(18px);
|
|
border-bottom: 1px solid rgba(148, 163, 184, 0.14);
|
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.04);
|
|
}
|
|
|
|
.topbar-left,
|
|
.topbar-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 14px;
|
|
object-fit: cover;
|
|
box-shadow: 0 10px 20px rgba(79, 70, 229, 0.16);
|
|
}
|
|
|
|
.brand-copy {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.brand-title {
|
|
font-size: 17px;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
letter-spacing: 0.01em;
|
|
}
|
|
|
|
.brand-subtitle {
|
|
font-size: 12px;
|
|
color: var(--text-faint);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.main-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
min-width: 0;
|
|
overflow-x: auto;
|
|
padding: 4px;
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.58);
|
|
border: 1px solid rgba(148, 163, 184, 0.14);
|
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.8);
|
|
}
|
|
|
|
.main-nav::-webkit-scrollbar,
|
|
.sub-nav::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.main-nav-link,
|
|
.sub-nav-link {
|
|
appearance: none;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--text-soft);
|
|
cursor: pointer;
|
|
font: inherit;
|
|
white-space: nowrap;
|
|
transition: all .18s ease;
|
|
}
|
|
|
|
.main-nav-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
min-height: 38px;
|
|
padding: 0 16px;
|
|
border-radius: 999px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.main-nav-link:hover {
|
|
background: rgba(255,255,255,0.92);
|
|
color: var(--text);
|
|
}
|
|
|
|
.main-nav-link.is-active {
|
|
color: var(--primary);
|
|
background: linear-gradient(135deg, rgba(79,70,229,0.12), rgba(99,102,241,0.08));
|
|
box-shadow: inset 0 0 0 1px rgba(99,102,241,0.10);
|
|
}
|
|
|
|
.status-pill,
|
|
.user-pill {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 10px 14px;
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.72);
|
|
border: 1px solid var(--border);
|
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.9);
|
|
color: var(--text-soft);
|
|
font-size: 13px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.status-dot,
|
|
.user-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.status-dot {
|
|
background: var(--success);
|
|
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.12);
|
|
}
|
|
|
|
.user-dot {
|
|
background: var(--info);
|
|
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.10);
|
|
}
|
|
|
|
.logout-btn {
|
|
color: var(--text-soft) !important;
|
|
padding: 10px 14px !important;
|
|
border-radius: 999px !important;
|
|
transition: all .18s ease !important;
|
|
}
|
|
|
|
.logout-btn:hover {
|
|
color: var(--primary) !important;
|
|
background: var(--primary-soft) !important;
|
|
}
|
|
|
|
.subnav-bar {
|
|
position: sticky;
|
|
top: var(--topbar-height);
|
|
z-index: 190;
|
|
height: var(--subnav-height);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 0 24px;
|
|
background: rgba(248, 250, 252, 0.84);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
border-bottom: 1px solid rgba(148, 163, 184, 0.12);
|
|
}
|
|
|
|
.subnav-title {
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 3px;
|
|
}
|
|
|
|
.subnav-title h2 {
|
|
font-size: 19px;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
}
|
|
|
|
.subnav-title p {
|
|
font-size: 13px;
|
|
color: var(--text-soft);
|
|
}
|
|
|
|
.sub-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
overflow-x: auto;
|
|
padding-bottom: 2px;
|
|
}
|
|
|
|
.sub-nav-link {
|
|
min-height: 36px;
|
|
padding: 0 14px;
|
|
border-radius: 999px;
|
|
border: 1px solid rgba(148, 163, 184, 0.12);
|
|
background: rgba(255,255,255,0.64);
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.sub-nav-link:hover {
|
|
background: rgba(255,255,255,0.95);
|
|
color: var(--text);
|
|
border-color: rgba(148, 163, 184, 0.18);
|
|
}
|
|
|
|
.sub-nav-link.is-active {
|
|
background: linear-gradient(135deg, rgba(79,70,229,0.12), rgba(99,102,241,0.08));
|
|
color: var(--primary);
|
|
border-color: rgba(99, 102, 241, 0.12);
|
|
}
|
|
|
|
.layout-shell {
|
|
height: calc(100vh - var(--topbar-height) - var(--subnav-height));
|
|
overflow: hidden;
|
|
}
|
|
|
|
.content {
|
|
height: 100%;
|
|
overflow-y: auto;
|
|
padding: var(--content-padding);
|
|
}
|
|
|
|
.content-inner {
|
|
min-height: calc(100vh - var(--topbar-height) - var(--subnav-height) - (var(--content-padding) * 2));
|
|
}
|
|
|
|
.toolbar-card,
|
|
.el-card {
|
|
border-radius: var(--radius-md) !important;
|
|
border: 1px solid var(--border) !important;
|
|
background: rgba(255, 255, 255, 0.82) !important;
|
|
box-shadow: var(--shadow-sm) !important;
|
|
backdrop-filter: blur(8px);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.el-card__header {
|
|
padding: 16px 18px !important;
|
|
background: linear-gradient(180deg, rgba(255,255,255,0.82), rgba(248,250,252,0.92)) !important;
|
|
border-bottom: 1px solid rgba(148, 163, 184, 0.12) !important;
|
|
color: var(--text) !important;
|
|
}
|
|
|
|
.el-card__body {
|
|
padding: 18px !important;
|
|
}
|
|
|
|
.el-button {
|
|
border-radius: 12px !important;
|
|
font-weight: 500 !important;
|
|
transition: all .18s ease !important;
|
|
}
|
|
|
|
.el-button--primary {
|
|
background: linear-gradient(135deg, #4f46e5, #6366f1) !important;
|
|
border-color: transparent !important;
|
|
box-shadow: 0 10px 20px rgba(79, 70, 229, 0.18) !important;
|
|
}
|
|
|
|
.el-button--primary:hover,
|
|
.el-button--primary:focus {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 14px 24px rgba(79, 70, 229, 0.22) !important;
|
|
}
|
|
|
|
.el-button--primary.is-plain,
|
|
.el-button--success.is-plain,
|
|
.el-button--warning.is-plain,
|
|
.el-button--danger.is-plain,
|
|
.el-button--info.is-plain {
|
|
background: rgba(255, 255, 255, 0.96) !important;
|
|
box-shadow: 0 6px 16px rgba(15, 23, 42, 0.06) !important;
|
|
}
|
|
|
|
.el-button--primary.is-plain {
|
|
color: #4338ca !important;
|
|
border-color: rgba(99, 102, 241, 0.34) !important;
|
|
}
|
|
|
|
.el-button--primary.is-plain:hover,
|
|
.el-button--primary.is-plain:focus {
|
|
color: #ffffff !important;
|
|
border-color: transparent !important;
|
|
background: linear-gradient(135deg, #4f46e5, #6366f1) !important;
|
|
box-shadow: 0 12px 22px rgba(79, 70, 229, 0.20) !important;
|
|
}
|
|
|
|
.el-button--success.is-plain {
|
|
color: #047857 !important;
|
|
border-color: rgba(16, 185, 129, 0.34) !important;
|
|
}
|
|
|
|
.el-button--success.is-plain:hover,
|
|
.el-button--success.is-plain:focus {
|
|
color: #ffffff !important;
|
|
border-color: transparent !important;
|
|
background: linear-gradient(135deg, #10b981, #34d399) !important;
|
|
box-shadow: 0 12px 22px rgba(16, 185, 129, 0.20) !important;
|
|
}
|
|
|
|
.el-button--warning.is-plain {
|
|
color: #b45309 !important;
|
|
border-color: rgba(245, 158, 11, 0.34) !important;
|
|
}
|
|
|
|
.el-button--warning.is-plain:hover,
|
|
.el-button--warning.is-plain:focus {
|
|
color: #ffffff !important;
|
|
border-color: transparent !important;
|
|
background: linear-gradient(135deg, #f59e0b, #fbbf24) !important;
|
|
box-shadow: 0 12px 22px rgba(245, 158, 11, 0.20) !important;
|
|
}
|
|
|
|
.el-button--danger.is-plain {
|
|
color: #b91c1c !important;
|
|
border-color: rgba(239, 68, 68, 0.34) !important;
|
|
}
|
|
|
|
.el-button--danger.is-plain:hover,
|
|
.el-button--danger.is-plain:focus {
|
|
color: #ffffff !important;
|
|
border-color: transparent !important;
|
|
background: linear-gradient(135deg, #ef4444, #f87171) !important;
|
|
box-shadow: 0 12px 22px rgba(239, 68, 68, 0.20) !important;
|
|
}
|
|
|
|
.el-button--info.is-plain {
|
|
color: #475569 !important;
|
|
border-color: rgba(100, 116, 139, 0.34) !important;
|
|
}
|
|
|
|
.el-button--info.is-plain:hover,
|
|
.el-button--info.is-plain:focus {
|
|
color: #ffffff !important;
|
|
border-color: transparent !important;
|
|
background: linear-gradient(135deg, #64748b, #94a3b8) !important;
|
|
box-shadow: 0 12px 22px rgba(100, 116, 139, 0.20) !important;
|
|
}
|
|
|
|
.el-button--default {
|
|
background: rgba(255,255,255,0.85) !important;
|
|
border-color: var(--border-strong) !important;
|
|
color: var(--text) !important;
|
|
}
|
|
|
|
.el-button--default:hover,
|
|
.el-button--default:focus {
|
|
border-color: rgba(99,102,241,0.3) !important;
|
|
color: var(--primary) !important;
|
|
background: rgba(255,255,255,0.96) !important;
|
|
}
|
|
|
|
.el-button--text,
|
|
.el-button--text:not(.is-disabled) {
|
|
color: #334155 !important;
|
|
font-weight: 600 !important;
|
|
padding: 6px 10px !important;
|
|
border-radius: 10px !important;
|
|
background: rgba(248, 250, 252, 0.9) !important;
|
|
border: 1px solid rgba(148, 163, 184, 0.14) !important;
|
|
}
|
|
|
|
.el-button--text:hover,
|
|
.el-button--text:focus,
|
|
.el-button--text:not(.is-disabled):hover,
|
|
.el-button--text:not(.is-disabled):focus {
|
|
color: var(--primary) !important;
|
|
background: rgba(99, 102, 241, 0.08) !important;
|
|
border-color: rgba(99, 102, 241, 0.18) !important;
|
|
}
|
|
|
|
.el-button--text [class*="el-icon-"],
|
|
.el-button--text span {
|
|
color: inherit !important;
|
|
}
|
|
|
|
.el-table .el-button--text,
|
|
.el-table .el-button--text:not(.is-disabled),
|
|
.el-card .el-button--text,
|
|
.el-card .el-button--text:not(.is-disabled) {
|
|
color: #1e293b !important;
|
|
background: rgba(255, 255, 255, 0.92) !important;
|
|
border-color: rgba(100, 116, 139, 0.18) !important;
|
|
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04) !important;
|
|
}
|
|
|
|
.el-table .el-button--text:hover,
|
|
.el-table .el-button--text:focus,
|
|
.el-card .el-button--text:hover,
|
|
.el-card .el-button--text:focus {
|
|
color: var(--primary) !important;
|
|
background: rgba(99, 102, 241, 0.10) !important;
|
|
border-color: rgba(99, 102, 241, 0.20) !important;
|
|
box-shadow: 0 8px 16px rgba(79, 70, 229, 0.10) !important;
|
|
}
|
|
|
|
.el-button--success,
|
|
.el-button--warning,
|
|
.el-button--danger,
|
|
.el-button--info {
|
|
color: #fff !important;
|
|
border-color: transparent !important;
|
|
}
|
|
|
|
.el-button--success { background: linear-gradient(135deg, #10b981, #34d399) !important; }
|
|
.el-button--warning { background: linear-gradient(135deg, #f59e0b, #fbbf24) !important; }
|
|
.el-button--danger { background: linear-gradient(135deg, #ef4444, #f87171) !important; }
|
|
.el-button--info { background: linear-gradient(135deg, #64748b, #94a3b8) !important; }
|
|
|
|
.el-input__inner,
|
|
.el-textarea__inner {
|
|
height: 40px;
|
|
border-radius: 12px !important;
|
|
background: rgba(248,250,252,0.9) !important;
|
|
border-color: rgba(148,163,184,0.22) !important;
|
|
color: var(--text) !important;
|
|
transition: all .18s ease !important;
|
|
}
|
|
|
|
.el-textarea__inner {
|
|
min-height: 110px;
|
|
}
|
|
|
|
.el-input__inner::placeholder,
|
|
.el-textarea__inner::placeholder {
|
|
color: var(--text-faint) !important;
|
|
}
|
|
|
|
.el-input__inner:focus,
|
|
.el-textarea__inner:focus {
|
|
border-color: rgba(99,102,241,0.42) !important;
|
|
box-shadow: 0 0 0 4px rgba(99,102,241,0.10) !important;
|
|
background: #fff !important;
|
|
}
|
|
|
|
.el-tag {
|
|
border-radius: 999px !important;
|
|
border: none !important;
|
|
padding: 0 10px !important;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.el-table {
|
|
color: var(--text) !important;
|
|
background: transparent !important;
|
|
border-radius: 14px !important;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.el-table::before,
|
|
.el-table--group::after,
|
|
.el-table--border::after,
|
|
.el-table__fixed-right::before,
|
|
.el-table__fixed::before {
|
|
display: none !important;
|
|
}
|
|
|
|
.el-table th {
|
|
background: rgba(248,250,252,0.95) !important;
|
|
color: var(--text-soft) !important;
|
|
font-weight: 600 !important;
|
|
border-bottom: 1px solid rgba(148,163,184,0.12) !important;
|
|
}
|
|
|
|
.el-table tr,
|
|
.el-table td,
|
|
.el-table__expanded-cell {
|
|
background: rgba(255,255,255,0.45) !important;
|
|
}
|
|
|
|
.el-table td,
|
|
.el-table th.is-leaf {
|
|
border-bottom: 1px solid rgba(148,163,184,0.10) !important;
|
|
}
|
|
|
|
.el-table--border,
|
|
.el-table--group {
|
|
border: 1px solid rgba(148,163,184,0.14) !important;
|
|
}
|
|
|
|
.el-table--border th,
|
|
.el-table--border td {
|
|
border-right: 1px solid rgba(148,163,184,0.08) !important;
|
|
}
|
|
|
|
.el-table__row:hover > td {
|
|
background: rgba(99,102,241,0.05) !important;
|
|
}
|
|
|
|
.el-dialog,
|
|
.el-message-box {
|
|
border-radius: 22px !important;
|
|
overflow: hidden !important;
|
|
border: 1px solid rgba(148,163,184,0.14) !important;
|
|
box-shadow: var(--shadow-md) !important;
|
|
background: rgba(255,255,255,0.94) !important;
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
}
|
|
|
|
.el-dialog__header,
|
|
.el-message-box__header {
|
|
padding: 18px 20px !important;
|
|
border-bottom: 1px solid rgba(148,163,184,0.10) !important;
|
|
background: rgba(248,250,252,0.86) !important;
|
|
}
|
|
|
|
.el-dialog__body,
|
|
.el-message-box__content {
|
|
color: var(--text) !important;
|
|
}
|
|
|
|
.el-pagination .el-pager li,
|
|
.el-pagination button {
|
|
border-radius: 10px !important;
|
|
border: 1px solid rgba(148,163,184,0.14) !important;
|
|
background: rgba(255,255,255,0.92) !important;
|
|
}
|
|
|
|
.el-pagination .el-pager li.active {
|
|
background: linear-gradient(135deg, #4f46e5, #6366f1) !important;
|
|
color: #fff !important;
|
|
}
|
|
|
|
.el-tabs__item {
|
|
color: var(--text-soft) !important;
|
|
}
|
|
|
|
.el-tabs__item.is-active,
|
|
.el-tabs__item:hover {
|
|
color: var(--primary) !important;
|
|
}
|
|
|
|
.el-tabs__active-bar {
|
|
background: var(--primary) !important;
|
|
height: 3px !important;
|
|
border-radius: 999px !important;
|
|
}
|
|
|
|
.toolbar-card {
|
|
margin-bottom: 18px;
|
|
}
|
|
|
|
.time-filter-form {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.v-modal {
|
|
background: rgba(15, 23, 42, 0.16) !important;
|
|
backdrop-filter: blur(4px);
|
|
-webkit-backdrop-filter: blur(4px);
|
|
}
|
|
|
|
a {
|
|
color: var(--primary);
|
|
}
|
|
|
|
a:hover {
|
|
color: #4338ca;
|
|
}
|
|
|
|
@media (max-width: 1320px) {
|
|
.topbar,
|
|
.subnav-bar,
|
|
.content {
|
|
padding-left: 18px;
|
|
padding-right: 18px;
|
|
}
|
|
|
|
.topbar {
|
|
gap: 12px;
|
|
}
|
|
|
|
.status-pill {
|
|
display: none;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<link rel="stylesheet" href="/static/css/element-ui/theme-chalk/index.min.css">
|
|
{% block styles %}{% endblock %}
|
|
<script src="/static/js/chart.js"></script>
|
|
<script src="/static/js/vue.js"></script>
|
|
<script src="/static/js/element-ui/index.min.js"></script>
|
|
<script src="/static/js/axios.min.js"></script>
|
|
{% block head %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<div id="app" class="app-container">
|
|
<header class="topbar">
|
|
<div class="topbar-left">
|
|
<div class="brand">
|
|
<img src="/static/logo.png" class="brand-logo" alt="logo">
|
|
<div class="brand-copy">
|
|
<div class="brand-title">机器人控制台</div>
|
|
<div class="brand-subtitle">更产品化的运营、消息与系统工作台</div>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="main-nav" aria-label="主导航">
|
|
<button
|
|
v-for="item in navGroups"
|
|
:key="item.key"
|
|
class="main-nav-link"
|
|
:class="{ 'is-active': activeGroup === item.key }"
|
|
@click="goToPrimary(item)">
|
|
<i :class="item.icon"></i>
|
|
<span>{% raw %}{{ item.label }}{% endraw %}</span>
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="topbar-right">
|
|
<div class="status-pill">
|
|
<span class="status-dot"></span>
|
|
<span>控制台在线</span>
|
|
</div>
|
|
<div class="user-pill">
|
|
<span class="user-dot"></span>
|
|
<span>管理员已登录</span>
|
|
</div>
|
|
<el-button type="text" class="logout-btn" @click="logout">
|
|
<i class="el-icon-switch-button"></i> 退出
|
|
</el-button>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="subnav-bar">
|
|
<div class="subnav-title">
|
|
<h2>{% raw %}{{ activeGroupMeta.label }}{% endraw %}</h2>
|
|
<p>{% raw %}{{ activeGroupMeta.description }}{% endraw %}</p>
|
|
</div>
|
|
<nav class="sub-nav" aria-label="二级导航">
|
|
<button
|
|
v-for="item in currentSubNav"
|
|
:key="item.path"
|
|
class="sub-nav-link"
|
|
:class="{ 'is-active': isPathActive(item.path) }"
|
|
@click="go(item.path)">
|
|
{% raw %}{{ item.label }}{% endraw %}
|
|
</button>
|
|
</nav>
|
|
</section>
|
|
|
|
<div class="layout-shell">
|
|
<main class="content">
|
|
<div class="content-inner">
|
|
<el-row v-if="showTimeRangeSelector" :gutter="12" style="margin-bottom: 18px;">
|
|
<el-col :span="24">
|
|
<el-card class="toolbar-card">
|
|
<el-form :inline="true" size="small" class="time-filter-form">
|
|
<el-form-item label="统计区间" style="margin-bottom:0;">
|
|
<el-select v-model="timeRange" @change="loadData">
|
|
<el-option label="最近7天" value="7"></el-option>
|
|
<el-option label="最近30天" value="30"></el-option>
|
|
<el-option label="最近90天" value="90"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item style="margin-bottom:0;">
|
|
<el-button type="primary" @click="loadData">刷新数据</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const NAV_GROUPS = [
|
|
{
|
|
key: 'overview',
|
|
label: '概览',
|
|
icon: 'el-icon-s-home',
|
|
description: '查看整体运行、趋势与核心经营指标',
|
|
defaultPath: '/',
|
|
items: [
|
|
{ label: '首页概览', path: '/' }
|
|
]
|
|
},
|
|
{
|
|
key: 'messages',
|
|
label: '消息',
|
|
icon: 'el-icon-chat-line-square',
|
|
description: '处理消息、日志与定时推送相关工作',
|
|
defaultPath: '/messages',
|
|
items: [
|
|
{ label: '消息列表', path: '/messages' },
|
|
{ label: '定时推送', path: '/message_push' }
|
|
]
|
|
},
|
|
{
|
|
key: 'friend-circle',
|
|
label: '朋友圈',
|
|
icon: 'el-icon-picture-outline-round',
|
|
description: '集中管理朋友圈查看、发布、点赞与评论流程',
|
|
defaultPath: '/friend_circle',
|
|
items: [
|
|
{ label: '朋友圈管理', path: '/friend_circle' }
|
|
]
|
|
},
|
|
{
|
|
key: 'groups',
|
|
label: '群组',
|
|
icon: 'el-icon-s-cooperation',
|
|
description: '管理群组、权限、通讯录与虚拟群组能力',
|
|
defaultPath: '/groups',
|
|
items: [
|
|
{ label: '群组统计', path: '/groups' },
|
|
{ label: '通讯录', path: '/contacts' },
|
|
{ label: '虚拟群组', path: '/virtual_group' }
|
|
]
|
|
},
|
|
{
|
|
key: 'plugins',
|
|
label: '插件',
|
|
icon: 'el-icon-s-grid',
|
|
description: '查看插件使用、管理插件与接口说明',
|
|
defaultPath: '/plugins',
|
|
items: [
|
|
{ label: '插件统计', path: '/plugins' },
|
|
{ label: '插件管理', path: '/plugins_manage' },
|
|
{ label: '接口文档', path: '/api_docs' }
|
|
]
|
|
},
|
|
{
|
|
key: 'system',
|
|
label: '系统',
|
|
icon: 'el-icon-cpu',
|
|
description: '关注用户、资源与文件等平台基础能力',
|
|
defaultPath: '/users',
|
|
items: [
|
|
{ label: '用户统计', path: '/users' },
|
|
{ label: '资源监控', path: '/system_status' },
|
|
{ label: '全局配置', path: '/system_llm' },
|
|
{ label: '文件浏览', path: '/file_browser' },
|
|
{ label: '运行日志', path: '/wx_logs' },
|
|
{ label: '错误日志', path: '/errors' }
|
|
]
|
|
}
|
|
];
|
|
|
|
const baseApp = {
|
|
data() {
|
|
return {
|
|
currentView: '1',
|
|
timeRange: '7',
|
|
showTimeRangeSelector: false,
|
|
navGroups: NAV_GROUPS
|
|
}
|
|
},
|
|
computed: {
|
|
activeGroup() {
|
|
const path = this.normalizePath(window.location.pathname);
|
|
const matched = this.navGroups.find(group =>
|
|
group.items.some(item => this.normalizePath(item.path) === path)
|
|
);
|
|
return matched ? matched.key : 'overview';
|
|
},
|
|
activeGroupMeta() {
|
|
return this.navGroups.find(group => group.key === this.activeGroup) || this.navGroups[0];
|
|
},
|
|
currentSubNav() {
|
|
return this.activeGroupMeta.items || [];
|
|
}
|
|
},
|
|
created() {
|
|
const path = window.location.pathname;
|
|
this.showTimeRangeSelector = ['/', '/plugins', '/users', '/groups', '/errors'].includes(path);
|
|
},
|
|
mounted() {
|
|
document.querySelector('.app-container').classList.add('loaded');
|
|
},
|
|
methods: {
|
|
normalizePath(path) {
|
|
if (!path) return '/';
|
|
if (path.length > 1 && path.endsWith('/')) {
|
|
return path.slice(0, -1);
|
|
}
|
|
return path;
|
|
},
|
|
isPathActive(path) {
|
|
return this.normalizePath(window.location.pathname) === this.normalizePath(path);
|
|
},
|
|
go(path) {
|
|
if (path && this.normalizePath(window.location.pathname) !== this.normalizePath(path)) {
|
|
window.location.href = path;
|
|
}
|
|
},
|
|
goToPrimary(group) {
|
|
if (!group) return;
|
|
const current = this.normalizePath(window.location.pathname);
|
|
const ownPaths = (group.items || []).map(item => this.normalizePath(item.path));
|
|
if (ownPaths.includes(current)) return;
|
|
this.go(group.defaultPath || (group.items && group.items[0] && group.items[0].path));
|
|
},
|
|
handleSelect(key) {
|
|
const routes = {
|
|
'1': '/',
|
|
'2': '/plugins',
|
|
'3': '/users',
|
|
'4': '/groups',
|
|
'5': '/errors',
|
|
'7': '/messages',
|
|
'9': '/wx_logs',
|
|
'10': '/contacts',
|
|
'11': '/plugins_manage',
|
|
'12': '/virtual_group',
|
|
'13': '/api_docs',
|
|
'14': '/system_status',
|
|
'17': '/system_llm',
|
|
'15': '/file_browser',
|
|
'16': '/message_push'
|
|
};
|
|
if (routes[key] && window.location.pathname !== routes[key]) {
|
|
window.location.href = routes[key];
|
|
}
|
|
},
|
|
logout() {
|
|
this.$confirm('确认退出登录吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
window.location.href = '/logout';
|
|
});
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
{% block scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|