- 💡 要使用管理功能,请先进行身份验证 -
-diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..ced5226 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,981 @@ +/* ===== CSS Variables (shadcn/ui inspired) ===== */ +:root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 330 81% 60%; + --primary-foreground: 0 0% 100%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 330 45% 96%; + --accent-foreground: 330 81% 30%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 100%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 330 81% 60%; + --radius: 0.5rem; +} + +.dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + --primary: 330 81% 68%; + --primary-foreground: 330 20% 10%; + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --accent: 330 25% 15%; + --accent-foreground: 330 81% 68%; + --destructive: 0 62.8% 50%; + --destructive-foreground: 210 40% 98%; + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 330 81% 68%; +} + +/* ===== Base Styles ===== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; + background-color: hsl(var(--background)); + color: hsl(var(--foreground)); + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +/* ===== Layout ===== */ +.app-container { + display: flex; + min-height: 100vh; +} + +/* Sidebar */ +.sidebar { + width: 280px; + border-right: 1px solid hsl(var(--border)); + background-color: hsl(var(--card)); + display: flex; + flex-direction: column; + position: fixed; + height: 100vh; + overflow-y: auto; +} + +.sidebar-header { + padding: 1.5rem 1.5rem 1rem; + border-bottom: 1px solid hsl(var(--border)); +} + +.sidebar-brand { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.25rem; + font-weight: 600; +} + +.sidebar-nav { + flex: 1; + padding: 1rem 0.75rem; +} + +.nav-section { + margin-bottom: 1.5rem; +} + +.nav-section-title { + padding: 0.5rem 0.75rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: hsl(var(--muted-foreground)); +} + +.nav-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.625rem 0.75rem; + margin: 0.125rem 0; + border-radius: var(--radius); + color: hsl(var(--foreground)); + text-decoration: none; + cursor: pointer; + transition: all 0.15s; + font-size: 0.875rem; + font-weight: 500; + border: none; + background: none; + width: 100%; + text-align: left; +} + +.nav-item:hover { + background-color: hsl(var(--accent)); + color: hsl(var(--accent-foreground)); +} + +.nav-item.active { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); +} + +.nav-item-icon { + font-size: 1.25rem; + width: 1.25rem; + height: 1.25rem; + display: flex; + align-items: center; + justify-content: center; +} + +.sidebar-footer { + padding: 1rem 1.5rem; + border-top: 1px solid hsl(var(--border)); +} + +/* Main Content */ +.main-content { + flex: 1; + margin-left: 280px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.main-header { + position: sticky; + top: 0; + z-index: 10; + background-color: hsl(var(--background) / 0.95); + backdrop-filter: blur(8px); + border-bottom: 1px solid hsl(var(--border)); + padding: 1rem 2rem; +} + +.header-content { + display: flex; + align-items: center; + justify-content: space-between; + max-width: 1400px; +} + +.header-title { + font-size: 1.5rem; + font-weight: 600; +} + +.header-actions { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.content-wrapper { + flex: 1; + padding: 2rem; + max-width: 1400px; +} + +/* ===== Components ===== */ +/* Card */ +.card { + background-color: hsl(var(--card)); + border: 1px solid hsl(var(--border)); + border-radius: calc(var(--radius) + 2px); + box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; +} + +.card-header { + padding: 1.5rem; + border-bottom: 1px solid hsl(var(--border)); + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.card-header > .flex { + margin-left: auto; +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + line-height: 1; +} + +.card-description { + font-size: 0.875rem; + color: hsl(var(--muted-foreground)); + margin-top: 0.375rem; +} + +.card-content { + padding: 1.5rem; + margin-top: 0; +} + +.card-footer { + padding: 1.5rem; + border-top: 1px solid hsl(var(--border)); + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Button */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + border-radius: var(--radius); + font-size: 0.875rem; + font-weight: 500; + padding: 0.625rem 1rem; + border: none; + cursor: pointer; + transition: all 0.15s; + text-decoration: none; + white-space: nowrap; +} + +.btn:disabled { + pointer-events: none; + opacity: 0.5; +} + +.btn-primary { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); +} + +.btn-primary:hover { + background-color: hsl(var(--primary) / 0.9); +} + +.btn-secondary { + background-color: hsl(var(--secondary)); + color: hsl(var(--secondary-foreground)); +} + +.btn-secondary:hover { + background-color: hsl(var(--secondary) / 0.8); +} + +.btn-outline { + background-color: transparent; + border: 1px solid hsl(var(--input)); + color: hsl(var(--foreground)); +} + +.btn-outline:hover { + background-color: hsl(var(--accent)); + color: hsl(var(--accent-foreground)); +} + +.btn-destructive { + background-color: hsl(var(--destructive)); + color: hsl(var(--destructive-foreground)); +} + +.btn-destructive:hover { + background-color: hsl(var(--destructive) / 0.9); +} + +.btn-ghost { + background-color: transparent; + color: hsl(var(--foreground)); +} + +.btn-ghost:hover { + background-color: hsl(var(--accent)); + color: hsl(var(--accent-foreground)); +} + +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.8125rem; +} + +.btn-lg { + padding: 0.75rem 1.5rem; + font-size: 1rem; +} + +/* Input */ +.input { + display: flex; + width: 100%; + border-radius: var(--radius); + border: 1px solid hsl(var(--input)); + background-color: hsl(var(--background)); + padding: 0.625rem 0.75rem; + font-size: 0.875rem; + transition: all 0.15s; + color: hsl(var(--foreground)); +} + +select.input[multiple] { + display: block; + padding: 0.5rem; +} + +select.input[multiple] option { + padding: 0.5rem; + border-radius: 4px; + margin-bottom: 2px; +} + +select.input[multiple] option:checked { + background: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); +} + +/* Multi-Select Component */ +.multi-select-wrapper { + position: relative; + width: 100%; +} + +.multi-select-trigger { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + padding: 0.625rem 0.75rem; + border: 1px solid hsl(var(--input)); + border-radius: var(--radius); + background-color: hsl(var(--background)); + cursor: pointer; + transition: all 0.15s; +} + +.multi-select-trigger:hover { + border-color: hsl(var(--ring)); +} + +.multi-select-value { + flex: 1; + font-size: 0.875rem; + color: hsl(var(--foreground)); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.multi-select-value.placeholder { + color: hsl(var(--muted-foreground)); +} + +.multi-select-arrow { + font-size: 0.75rem; + color: hsl(var(--muted-foreground)); + transition: transform 0.2s; +} + +.multi-select-trigger.open .multi-select-arrow { + transform: rotate(180deg); +} + +.multi-select-dropdown { + position: absolute; + top: calc(100% + 0.25rem); + left: 0; + right: 0; + background: hsl(var(--background)); + border: 1px solid hsl(var(--input)); + border-radius: var(--radius); + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1); + z-index: 50; + max-height: 300px; + overflow: hidden; + display: flex; + flex-direction: column; +} + +.multi-select-search { + padding: 0.5rem; + border-bottom: 1px solid hsl(var(--border)); +} + +.multi-select-search .input { + padding: 0.5rem; + font-size: 0.875rem; +} + +.multi-select-options { + overflow-y: auto; + max-height: 250px; +} + +.multi-select-option { + display: flex; + align-items: center; + padding: 0.625rem 0.75rem; + cursor: pointer; + transition: background-color 0.15s; + gap: 0.5rem; +} + +.multi-select-option:hover { + background-color: hsl(var(--accent)); +} + +.multi-select-option input[type="checkbox"] { + width: 1rem; + height: 1rem; + cursor: pointer; +} + +.multi-select-option label { + flex: 1; + font-size: 0.875rem; + cursor: pointer; + margin: 0; +} + +.multi-select-loading, +.multi-select-empty { + padding: 1rem; + text-align: center; + color: hsl(var(--muted-foreground)); + font-size: 0.875rem; +} + +.input:focus { + outline: none; + border-color: hsl(var(--ring)); + box-shadow: 0 0 0 2px hsl(var(--ring) / 0.2); +} + +.input:disabled { + cursor: not-allowed; + opacity: 0.5; +} + +/* Label */ +.label { + display: block; + font-size: 0.875rem; + font-weight: 500; + margin-bottom: 0.5rem; + color: hsl(var(--foreground)); +} + +/* Badge */ +.badge { + display: inline-flex; + align-items: center; + border-radius: calc(var(--radius) - 2px); + padding: 0.25rem 0.625rem; + font-size: 0.75rem; + font-weight: 600; + line-height: 1; + transition: all 0.15s; +} + +.badge-default { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); +} + +.badge-secondary { + background-color: hsl(var(--secondary)); + color: hsl(var(--secondary-foreground)); +} + +.badge-success { + background-color: hsl(142.1 76.2% 36.3%); + color: hsl(0 0% 100%); +} + +.badge-warning { + background-color: hsl(47.9 95.8% 53.1%); + color: hsl(26 83.3% 14.1%); +} + +.badge-destructive { + background-color: hsl(var(--destructive)); + color: hsl(var(--destructive-foreground)); +} + +.badge-outline { + background-color: transparent; + border: 1px solid hsl(var(--border)); + color: hsl(var(--foreground)); +} + +/* Table */ +.table-container { + overflow-x: auto; + border-radius: var(--radius); + border: 1px solid hsl(var(--border)); +} + +.table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +.table thead { + background-color: hsl(var(--muted)); +} + +.table th { + padding: 0.75rem 1rem; + text-align: left; + font-weight: 600; + color: hsl(var(--muted-foreground)); + border-bottom: 1px solid hsl(var(--border)); +} + +.table td { + padding: 0.75rem 1rem; + border-bottom: 1px solid hsl(var(--border)); +} + +.table tbody tr:hover { + background-color: hsl(var(--muted) / 0.5); +} + +.table tbody tr:last-child td { + border-bottom: none; +} + +/* Alert */ +.alert { + padding: 1rem; + border-radius: var(--radius); + border: 1px solid hsl(var(--border)); + margin-bottom: 1rem; +} + +.alert-info { + background-color: hsl(330 100% 97%); + border-color: hsl(330 81% 85%); + color: hsl(330 81% 30%); +} + +.dark .alert-info { + background-color: hsl(330 40% 15%); + border-color: hsl(330 40% 25%); + color: hsl(330 81% 85%); +} + +.alert-success { + background-color: hsl(142.1 76.2% 36.3% / 0.1); + border-color: hsl(142.1 76.2% 36.3% / 0.3); +} + +.alert-warning { + background-color: hsl(47.9 95.8% 53.1% / 0.1); + border-color: hsl(47.9 95.8% 53.1% / 0.3); +} + +.alert-error { + background-color: hsl(var(--destructive) / 0.1); + border-color: hsl(var(--destructive) / 0.3); +} + +/* Modal */ +.modal-overlay { + position: fixed; + inset: 0; + background-color: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + z-index: 50; + display: none; + align-items: center; + justify-content: center; + animation: fadeIn 0.2s ease; +} + +.modal-overlay.active { + display: flex; +} + +.modal-content { + background-color: hsl(var(--card)); + border: 1px solid hsl(var(--border)); + border-radius: calc(var(--radius) + 4px); + box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + max-width: 32rem; + width: 90%; + max-height: 90vh; + overflow-y: auto; + animation: slideUp 0.2s ease; +} + +.modal-header { + padding: 1.5rem; + border-bottom: 1px solid hsl(var(--border)); +} + +.modal-title { + font-size: 1.25rem; + font-weight: 600; +} + +.modal-body { + padding: 1.5rem; +} + +.modal-footer { + padding: 1.5rem; + border-top: 1px solid hsl(var(--border)); + display: flex; + justify-content: flex-end; + gap: 0.75rem; +} + +/* Form Group */ +.form-group { + margin-bottom: 1.25rem; +} + +.form-group:last-child { + margin-bottom: 0; +} + +/* Grid */ +.grid { + display: grid; + gap: 1.5rem; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, 1fr); +} + +.grid-cols-3 { + grid-template-columns: repeat(3, 1fr); +} + +.grid-cols-4 { + grid-template-columns: repeat(4, 1fr); +} + +/* Stats Card */ +.stats-card { + background-color: hsl(var(--card)); + border: 1px solid hsl(var(--border)); + border-radius: calc(var(--radius) + 2px); + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.stats-card-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.stats-card-title { + font-size: 0.875rem; + font-weight: 500; + color: hsl(var(--muted-foreground)); +} + +.stats-card-value { + font-size: 2rem; + font-weight: 700; +} + +.stats-card-trend { + font-size: 0.875rem; + color: hsl(var(--muted-foreground)); +} + +/* Animations */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideIn { + from { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} + +@keyframes fadeOut { + from { opacity: 1; } + to { opacity: 0; } +} + +/* Utilities */ +.hidden { + display: none !important; +} + +.flex { + display: flex; +} + +.items-center { + align-items: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-4 { + gap: 1rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.text-sm { + font-size: 0.875rem; +} + +.text-center { + text-align: center; +} + +.text-muted { + color: hsl(var(--muted-foreground)); +} + +.font-medium { + font-weight: 500; +} + +.font-semibold { + font-weight: 600; +} + +.w-full { + width: 100%; +} + +code { + background-color: hsl(var(--muted)); + padding: 0.125rem 0.25rem; + border-radius: 0.25rem; + font-size: 0.875em; + font-family: 'Courier New', monospace; +} + +/* Tab Content */ +.tab-content { + display: none; +} + +.tab-content.active { + display: flex; + flex-direction: column; + flex: 1; +} + +/* Responsive */ +@media (max-width: 1024px) { + .sidebar { + transform: translateX(-100%); + transition: transform 0.3s; + } + + .sidebar.mobile-open { + transform: translateX(0); + } + + .main-content { + margin-left: 0; + } + + .grid-cols-2, + .grid-cols-3, + .grid-cols-4 { + grid-template-columns: 1fr; + } +} + +/* ===== Loading Overlay ===== */ +#loadingOverlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + z-index: 9999; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.2s; + pointer-events: none; +} + +#loadingOverlay.active { + opacity: 1; + pointer-events: auto; +} + +.loading-spinner { + width: 48px; + height: 48px; + border: 3px solid rgba(255, 255, 255, 0.2); + border-top-color: hsl(var(--primary)); + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +.loading-text { + margin-top: 1rem; + color: white; + font-size: 0.875rem; + font-weight: 500; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* ===== Item List Styles ===== */ +#tokenListView, +#channelListView, +#pricingContent { + display: flex; + flex-direction: column; + flex: 1; +} + +.item-list { + flex: 1; + overflow-y: auto; + padding: 1.5rem; + padding-right: 1.5rem; + min-height: 0; +} + +.item-list::-webkit-scrollbar { + width: 6px; +} + +.item-list::-webkit-scrollbar-track { + background: hsl(var(--muted)); + border-radius: 3px; +} + +.item-list::-webkit-scrollbar-thumb { + background: hsl(var(--border)); + border-radius: 3px; +} + +.item-list::-webkit-scrollbar-thumb:hover { + background: hsl(var(--muted-foreground)); +} + +.item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 18px 20px; + border: 1px solid hsl(var(--border)); + border-radius: var(--radius); + margin-bottom: 12px; + background: hsl(var(--card)); + transition: all 0.2s ease; +} + +.item:hover { + border-color: hsl(var(--primary)); + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + transform: translateX(4px); +} + +.item-info { + flex: 1; + min-width: 0; +} + +.item-key { + font-weight: 600; + color: hsl(var(--foreground)); + margin-bottom: 6px; + font-size: 15px; +} + +.item-details { + font-size: 13px; + color: hsl(var(--muted-foreground)); + line-height: 1.5; +} + +.actions { + display: flex; + gap: 8px; + flex-shrink: 0; +} + +.btn-danger { + background-color: hsl(var(--destructive)); + color: hsl(var(--destructive-foreground)); +} + +.btn-danger:hover { + opacity: 0.9; +} diff --git a/public/index.html b/public/index.html index 34e0f5e..813b4c5 100644 --- a/public/index.html +++ b/public/index.html @@ -1,3096 +1,590 @@ -
-- 💡 要使用管理功能,请先进行身份验证 -
-