全网最帅的硅基批量查余额

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SiliconFlow - 批量余额查询</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        :root {
            --primary: #0062ff;
            --primary-dark: #0050d0;
            --primary-light: #cce0ff;
            --primary-bg: #f0f6ff;
            --success: #05a660;
            --success-light: #e6f6ef;
            --warning: #ff9800;
            --warning-light: #fff4e6;
            --danger: #e53935;
            --danger-light: #ffebee;
            --info: #0288d1;
            --info-light: #e1f5fe;
            --gray-50: #fafafa;
            --gray-100: #f5f5f5;
            --gray-200: #eeeeee;
            --gray-300: #e0e0e0;
            --gray-400: #bdbdbd;
            --gray-500: #9e9e9e;
            --gray-600: #757575;
            --gray-700: #616161;
            --gray-800: #424242;
            --gray-900: #212121;
            --black: #000000;
            --white: #ffffff;
            --radius-xs: 2px;
            --radius-sm: 4px;
            --radius: 8px;
            --radius-md: 12px;
            --radius-lg: 16px;
            --radius-xl: 24px;
            --radius-full: 9999px;
            --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
            --shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
            --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
            --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);
            --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            line-height: 1.5;
            color: var(--gray-800);
            background-color: #f8fafc;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }

        .container {
            width: 100%;
            max-width: 1200px;
            margin: 0 auto;
            padding: 1.5rem;
        }

        .navbar {
            background-color: var(--white);
            box-shadow: var(--shadow);
            position: sticky;
            top: 0;
            z-index: 100;
            padding: 1rem 0;
        }

        .navbar-container {
            display: flex;
            align-items: center;
            justify-content: space-between;
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 1.5rem;
        }

        .navbar-brand {
            display: flex;
            align-items: center;
            gap: 0.75rem;
            text-decoration: none;
        }

        .brand-logo {
            width: 36px;
            height: 36px;
            background: linear-gradient(135deg, var(--primary), #3d5afe);
            border-radius: var(--radius-sm);
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--white);
            font-weight: 600;
            box-shadow: var(--shadow);
        }

        .brand-text {
            font-size: 1.25rem;
            font-weight: 600;
            color: var(--gray-900);
        }

        .page-header {
            margin: 2rem 0 2.5rem;
            text-align: center;
        }

        .page-title {
            font-size: 2rem;
            font-weight: 700;
            color: var(--gray-900);
            margin-bottom: 0.75rem;
        }

        .page-description {
            color: var(--gray-600);
            font-size: 1.125rem;
            max-width: 640px;
            margin: 0 auto;
        }

        .card {
            background-color: var(--white);
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow-md);
            overflow: hidden;
            transition: box-shadow 0.2s;
            margin-bottom: 1.5rem;
        }

        .card:hover {
            box-shadow: var(--shadow-lg);
        }

        .card-header {
            padding: 1.25rem 1.5rem;
            border-bottom: 1px solid var(--gray-200);
            display: flex;
            align-items: center;
            justify-content: space-between;
            background-color: var(--white);
        }

        .card-title {
            font-size: 1.25rem;
            font-weight: 600;
            color: var(--gray-900);
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        .card-title i {
            color: var(--primary);
            font-size: 1.125rem;
        }

        .card-body {
            padding: 1.5rem;
        }

        .form-group {
            margin-bottom: 1.5rem;
        }

        .form-label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: 600;
            color: var(--gray-800);
        }

        .form-helper {
            color: var(--gray-600);
            font-size: 0.875rem;
            margin-top: 0.375rem;
            display: flex;
            align-items: center;
            gap: 0.25rem;
        }

        .form-control {
            width: 100%;
            padding: 0.875rem 1rem;
            font-size: 0.875rem;
            line-height: 1.5;
            color: var(--gray-900);
            background-color: var(--white);
            border: 1px solid var(--gray-300);
            border-radius: var(--radius);
            transition: all 0.2s;
        }

        .form-control:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(0, 98, 255, 0.15);
        }

        textarea.form-control {
            min-height: 120px;
            resize: vertical;
            font-family: inherit;
        }

        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 0.75rem 1.5rem;
            font-size: 1rem;
            font-weight: 500;
            line-height: 1;
            text-align: center;
            white-space: nowrap;
            vertical-align: middle;
            cursor: pointer;
            user-select: none;
            border: 1px solid transparent;
            border-radius: var(--radius);
            transition: all 0.2s;
            gap: 0.5rem;
        }

        .btn:focus {
            outline: none;
            box-shadow: 0 0 0 3px rgba(0, 98, 255, 0.25);
        }

        .btn-primary {
            color: var(--white);
            background-color: var(--primary);
            border-color: var(--primary);
        }

        .btn-primary:hover {
            background-color: var(--primary-dark);
            border-color: var(--primary-dark);
        }

        .btn-outline {
            color: var(--gray-700);
            background-color: var(--white);
            border-color: var(--gray-300);
        }

        .btn-outline:hover {
            background-color: var(--gray-100);
            border-color: var(--gray-400);
        }

        .btn-success {
            color: var(--white);
            background-color: var(--success);
            border-color: var(--success);
        }

        .btn-success:hover {
            background-color: #048f53;
            border-color: #048f53;
        }

        .btn-lg {
            padding: 0.875rem 2rem;
            font-size: 1.125rem;
        }

        .btn-sm {
            padding: 0.5rem 0.75rem;
            font-size: 0.875rem;
            border-radius: var(--radius-sm);
        }

        .btn-icon {
            padding: 0.5rem;
            border-radius: var(--radius-full);
        }

        .btn-block {
            display: flex;
            width: 100%;
        }

        .alert {
            padding: 1rem;
            border-radius: var(--radius);
            margin-bottom: 1.5rem;
            display: flex;
            align-items: center;
            gap: 0.75rem;
            display: none;
        }

        .alert.show {
            display: flex;
        }

        .alert-content {
            flex: 1;
        }

        .alert-icon {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 24px;
            height: 24px;
            border-radius: var(--radius-full);
            flex-shrink: 0;
        }

        .alert-danger {
            background-color: var(--danger-light);
            color: var(--danger);
        }

        .alert-danger .alert-icon {
            background-color: var(--danger);
            color: var(--white);
        }

        .alert-success {
            background-color: var(--success-light);
            color: var(--success);
        }

        .alert-success .alert-icon {
            background-color: var(--success);
            color: var(--white);
        }

        .loading-container {
            padding: 3rem 1.5rem;
            display: none;
            flex-direction: column;
            align-items: center;
            gap: 1.5rem;
        }

        .loading-container.show {
            display: flex;
        }

        .loading-animation {
            position: relative;
            width: 64px;
            height: 64px;
        }

        .loading-circle {
            position: absolute;
            width: 64px;
            height: 64px;
            border: 4px solid rgba(0, 98, 255, 0.1);
            border-top-color: var(--primary);
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        .loading-text {
            font-size: 1.25rem;
            font-weight: 600;
            color: var(--gray-800);
        }

        .loading-subtext {
            color: var(--gray-600);
            margin-top: 0.25rem;
        }

        .progress-container {
            width: 100%;
            max-width: 360px;
        }

        .progress-info {
            display: flex;
            justify-content: space-between;
            margin-bottom: 0.5rem;
            font-size: 0.875rem;
            color: var(--gray-600);
        }

        .progress-bar-bg {
            width: 100%;
            height: 6px;
            background-color: var(--gray-200);
            border-radius: var(--radius-full);
            overflow: hidden;
        }

        .progress-bar {
            height: 100%;
            background-color: var(--primary);
            width: 0%;
            transition: width 0.3s;
        }

        .results-section {
            display: none;
        }

        .results-section.show {
            display: block;
        }

        .summary-grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 1rem;
            margin-bottom: 1.5rem;
        }

        .summary-card {
            background-color: var(--white);
            border-radius: var(--radius);
            padding: 1rem 1.25rem;
            box-shadow: var(--shadow-sm);
            display: flex;
            align-items: center;
            gap: 1rem;
        }

        .summary-icon {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 48px;
            height: 48px;
            border-radius: var(--radius);
            flex-shrink: 0;
        }

        .summary-data {
            flex: 1;
        }

        .summary-value {
            font-size: 1.5rem;
            font-weight: 700;
            line-height: 1.2;
            margin-bottom: 0.25rem;
        }

        .summary-label {
            font-size: 0.875rem;
            color: var(--gray-600);
        }

        .summary-total .summary-icon {
            background-color: var(--primary-bg);
            color: var(--primary);
        }

        .summary-total .summary-value {
            color: var(--primary);
        }

        .summary-valid .summary-icon {
            background-color: var(--success-light);
            color: var(--success);
        }

        .summary-valid .summary-value {
            color: var(--success);
        }

        .summary-invalid .summary-icon {
            background-color: var(--danger-light);
            color: var(--danger);
        }

        .summary-invalid .summary-value {
            color: var(--danger);
        }

        .summary-balance .summary-icon {
            background-color: var(--info-light);
            color: var(--info);
        }

        .summary-balance .summary-value {
            color: var(--info);
        }

        .actions-bar {
            background-color: var(--gray-50);
            border-radius: var(--radius);
            padding: 0.75rem 1rem;
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 1.5rem;
            flex-wrap: wrap;
            gap: 1rem;
        }

        .actions-group {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 0.5rem;
        }
        
        .actions-title {
            font-weight: 500;
            color: var(--gray-700);
            margin-right: 0.75rem;
        }

        .badge-count {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background-color: var(--primary-bg);
            color: var(--primary);
            font-size: 0.75rem;
            font-weight: 600;
            height: 20px;
            min-width: 20px;
            padding: 0 6px;
            border-radius: var(--radius-full);
            margin-left: 0.375rem;
        }

        .table-container {
            border-radius: var(--radius);
            overflow: hidden;
            box-shadow: var(--shadow-sm);
            margin-bottom: 1.5rem;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        thead {
            background-color: var(--gray-50);
            border-bottom: 1px solid var(--gray-200);
        }

        th {
            color: var(--gray-700);
            font-weight: 600;
            font-size: 0.875rem;
            padding: 0.875rem 1rem;
            text-align: left;
            white-space: nowrap;
        }

        th.sortable {
            cursor: pointer;
            user-select: none;
        }

        th.sortable:hover {
            background-color: var(--gray-100);
        }

        th.sortable .sort-icon {
            display: inline-block;
            margin-left: 0.25rem;
            font-size: 0.75rem;
        }

        td {
            padding: 1rem;
            vertical-align: middle;
            border-bottom: 1px solid var(--gray-200);
        }

        tbody tr:last-child td {
            border-bottom: none;
        }

        tbody tr:hover {
            background-color: var(--gray-50);
        }

        .valid-entry:hover {
            background-color: rgba(5, 166, 96, 0.04);
        }

        .invalid-entry:hover {
            background-color: rgba(229, 57, 53, 0.04);
        }

        .user-cell {
            display: flex;
            align-items: center;
            gap: 1rem;
            min-width: 240px;
        }

        .user-avatar {
            width: 40px;
            height: 40px;
            border-radius: var(--radius-full);
            background-color: var(--primary-bg);
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--primary);
            font-weight: 600;
            position: relative;
            flex-shrink: 0;
            overflow: hidden;
        }

        .user-avatar img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .admin-badge {
            position: absolute;
            bottom: 0;
            right: 0;
            width: 14px;
            height: 14px;
            border-radius: var(--radius-full);
            background-color: var(--primary);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 8px;
            border: 1.5px solid white;
        }

        .user-info {
            display: flex;
            flex-direction: column;
            min-width: 0;
        }

        .user-name {
            font-weight: 500;
            color: var(--gray-900);
            margin-bottom: 0.25rem;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .user-meta {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            color: var(--gray-600);
            font-size: 0.75rem;
        }

        .user-contact {
            display: flex;
            align-items: center;
            gap: 0.25rem;
        }

        .user-role {
            display: inline-flex;
            align-items: center;
            padding: 0 6px;
            height: 18px;
            background-color: var(--primary-bg);
            color: var(--primary);
            border-radius: var(--radius-full);
            font-size: 0.75rem;
            font-weight: 500;
        }

        .status-badge {
            display: inline-flex;
            align-items: center;
            gap: 0.25rem;
            padding: 0.25rem 0.75rem;
            border-radius: var(--radius-full);
            font-size: 0.75rem;
            font-weight: 500;
            line-height: 1.5;
        }

        .status-active {
            background-color: var(--success-light);
            color: var(--success);
        }

        .status-warning {
            background-color: var(--warning-light);
            color: var(--warning);
        }

        .status-danger {
            background-color: var(--danger-light);
            color: var(--danger);
        }

        .api-key-cell {
            display: flex;
            align-items: center;
            font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            font-size: 0.813rem;
            color: var(--gray-800);
            gap: 0.5rem;
            max-width: 320px;
        }

        .key-text {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .copy-btn {
            padding: 0.25rem 0.5rem;
            border-radius: var(--radius-sm);
            background-color: var(--gray-100);
            color: var(--gray-700);
            border: 1px solid var(--gray-200);
            font-size: 0.75rem;
            cursor: pointer;
            transition: all 0.2s;
            display: inline-flex;
            align-items: center;
            gap: 0.25rem;
            white-space: nowrap;
            flex-shrink: 0;
        }

        .copy-btn:hover {
            background-color: var(--gray-200);
            color: var(--gray-800);
        }

        .copy-btn.copied {
            background-color: var(--success-light);
            color: var(--success);
            border-color: var(--success);
        }

        .amount-cell {
            font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            font-size: 0.875rem;
            font-weight: 500;
            text-align: center;
            white-space: nowrap;
            width: 100%;
            display: block;
            margin-left: auto;
            margin-right: auto;
        }

        .amount-total {
            color: var(--success);
            font-weight: 600;
        }

        .error-cell {
            color: var(--danger);
            font-size: 0.875rem;
            max-width: 320px;
        }

        .empty-state {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 3rem 1rem;
            text-align: center;
            display: none;
        }

        .empty-state.show {
            display: flex;
        }

        .empty-icon {
            width: 64px;
            height: 64px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: var(--radius-full);
            margin-bottom: 1.25rem;
            font-size: 2rem;
        }

        .empty-valid .empty-icon {
            background-color: var(--success-light);
            color: var(--success);
        }

        .empty-invalid .empty-icon {
            background-color: var(--danger-light);
            color: var(--danger);
        }

        .empty-title {
            font-weight: 600;
            font-size: 1.125rem;
            color: var(--gray-800);
            margin-bottom: 0.5rem;
        }

        .empty-message {
            color: var(--gray-600);
            max-width: 300px;
        }

        .footer {
            margin-top: 3rem;
            padding: 1.5rem;
            text-align: center;
            color: var(--gray-500);
        }

        .footer-text {
            font-size: 0.875rem;
        }

        .toast-container {
            position: fixed;
            bottom: 1.5rem;
            right: 1.5rem;
            z-index: 9999;
        }

        .toast {
            background-color: var(--gray-900);
            color: var(--white);
            border-radius: var(--radius);
            padding: 0.75rem 1rem;
            margin-top: 0.5rem;
            box-shadow: var(--shadow-lg);
            display: flex;
            align-items: center;
            gap: 0.5rem;
            min-width: 200px;
            max-width: 300px;
            transform: translateY(10px);
            opacity: 0;
            transition: transform 0.3s, opacity 0.3s;
        }

        .toast.show {
            transform: translateY(0);
            opacity: 1;
        }

        .toast-success {
            border-left: 4px solid var(--success);
        }

        .toast-error {
            border-left: 4px solid var(--danger);
        }

        .toast-info {
            border-left: 4px solid var(--primary);
        }

        .toast-icon {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 24px;
            height: 24px;
            flex-shrink: 0;
        }

        .toast-content {
            flex: 1;
        }

        .detected-keys {
            display: flex;
            align-items: center;
            padding: 0.5rem 0.75rem;
            background-color: var(--primary-bg);
            border-radius: var(--radius);
            margin-top: 0.75rem;
            font-size: 0.875rem;
            color: var(--primary);
        }

        .detected-keys i {
            margin-right: 0.5rem;
        }

        .detected-count {
            font-weight: 600;
            margin: 0 0.25rem;
        }

        .sort-button {
            display: flex;
            align-items: center;
            gap: 0.375rem;
            margin-right: 0.5rem;
        }

        .sort-button .sort-icon {
            transition: transform 0.2s ease;
        }

        .sort-active .sort-icon {
            color: var(--primary);
        }

        .sort-desc .sort-icon {
            transform: rotate(180deg);
        }

        @media (max-width: 992px) {
            .summary-grid {
                grid-template-columns: repeat(2, 1fr);
            }
        }
        
        @media (max-width: 768px) {
            .card-header {
                flex-direction: column;
                align-items: flex-start;
                gap: 1rem;
            }
            
            .actions-bar {
                flex-direction: column;
                align-items: flex-start;
            }
            
            .table-container {
                display: none;
            }
            
            .cards-view {
                display: block;
            }

            .actions-group {
                display: flex;
                flex-direction: column;
                width: 100%;
                gap: 0.75rem;
            }

            .actions-group .btn {
                width: 100%;
                justify-content: center;
            }
        }
        
        @media (min-width: 769px) {
            .table-container {
                display: block;
            }
            
            .cards-view {
                display: none;
            }
        }
        
        .result-card {
            background-color: var(--white);
            border-radius: var(--radius);
            padding: 1rem;
            margin-bottom: 1rem;
            box-shadow: var(--shadow-sm);
            border-left: 4px solid transparent;
        }
        
        .valid-card {
            border-left-color: var(--success);
        }
        
        .invalid-card {
            border-left-color: var(--danger);
        }
        
        .card-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 0.75rem;
            align-items: center;
        }
        
        .card-row:last-child {
            margin-bottom: 0;
        }
        
        .card-label {
            font-size: 0.75rem;
            color: var(--gray-600);
            margin-bottom: 0.25rem;
            text-align: center;
        }
        
        .card-value {
            font-weight: 500;
        }
        
        .card-divider {
            height: 1px;
            background-color: var(--gray-200);
            margin: 0.75rem 0;
        }
        
        .found-keys-badge {
            display: inline-flex;
            align-items: center;
            padding: 0.375rem 0.75rem;
            background-color: var(--primary-bg);
            color: var(--primary);
            border-radius: var(--radius-full);
            font-size: 0.875rem;
            font-weight: 500;
            margin-top: 0.75rem;
        }
        
        .found-keys-count {
            margin: 0 0.25rem;
            font-weight: 600;
        }

        .card-value.amount-cell {
            text-align: center;
            width: 100%;
            margin: 0 auto;
        }

        .balance-group {
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 33.33%;
            text-align: center;
        }
    </style>
</head>
<body>
    <nav class="navbar">
        <div class="navbar-container">
            <a href="#" class="navbar-brand">
                <div class="brand-logo">SF</div>
                <div class="brand-text">SiliconFlow</div>
            </a>
        </div>
    </nav>

    <div class="container">
        <header class="page-header">
            <h1 class="page-title">批量账户余额查询</h1>
            <p class="page-description">快速检索多个API密钥,获取账户余额和详细信息</p>
        </header>

        <div class="card">
            <div class="card-header">
                <h2 class="card-title">
                    <i class="fas fa-key"></i>
                    输入API密钥
                </h2>
            </div>
            <div class="card-body">
                <div id="errorAlert" class="alert alert-danger">
                    <div class="alert-icon">
                        <i class="fas fa-exclamation-triangle"></i>
                    </div>
                    <div class="alert-content" id="errorMessage"></div>
                </div>
                
                <div id="successAlert" class="alert alert-success">
                    <div class="alert-icon">
                        <i class="fas fa-check"></i>
                    </div>
                    <div class="alert-content" id="successMessage"></div>
                </div>

                <form id="apiKeysForm">
                    <div class="form-group">
                        <label for="apiKeysInput" class="form-label">粘贴任意文本</label>
                        <textarea id="apiKeysInput" class="form-control" placeholder="粘贴任何包含API密钥的文本,系统会自动提取以sk-开头的密钥..."></textarea>
                        <div class="form-helper">
                            <i class="fas fa-info-circle"></i>
                            智能识别:自动从粘贴文本中提取有效密钥,无需手动格式化
                        </div>
                    </div>
                    
                    <div id="detectedKeysInfo" class="detected-keys" style="display: none;">
                        <i class="fas fa-search"></i>
                        已检测到 <span id="detectedKeysCount" class="detected-count">0</span> 个API密钥
                    </div>

                    <button type="submit" class="btn btn-primary btn-block btn-lg">
                        <i class="fas fa-search"></i>
                        开始查询
                    </button>
                </form>

                <div id="loadingContainer" class="loading-container">
                    <div class="loading-animation">
                        <div class="loading-circle"></div>
                    </div>
                    <div>
                        <div class="loading-text">正在查询账户信息</div>
                        <div class="loading-subtext">请稍候,这可能需要一些时间...</div>
                    </div>
                    <div class="progress-container">
                        <div class="progress-info">
                            <span id="progressStatus">已查询 <span id="currentProgress">0</span>/<span id="totalKeys">0</span> 个</span>
                            <span id="progressPercentage">0%</span>
                        </div>
                        <div class="progress-bar-bg">
                        <div id="progressBar" class="progress-bar"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="resultsSection" class="results-section">
        <div class="summary-grid">
            <div class="summary-card summary-total">
                <div class="summary-icon">
                    <i class="fas fa-search"></i>
                </div>
                <div class="summary-data">
                    <div class="summary-value" id="totalQueries">0</div>
                    <div class="summary-label">总查询数</div>
                </div>
            </div>
            <div class="summary-card summary-valid">
                <div class="summary-icon">
                    <i class="fas fa-check-circle"></i>
                </div>
                <div class="summary-data">
                    <div class="summary-value" id="validQueries">0</div>
                    <div class="summary-label">有效密钥</div>
                </div>
            </div>
            <div class="summary-card summary-invalid">
                <div class="summary-icon">
                    <i class="fas fa-times-circle"></i>
                </div>
                <div class="summary-data">
                    <div class="summary-value" id="invalidQueries">0</div>
                    <div class="summary-label">无效密钥</div>
                </div>
            </div>
            <div class="summary-card summary-balance">
                <div class="summary-icon">
                    <i class="fas fa-wallet"></i>
                </div>
                <div class="summary-data">
                    <div class="summary-value" id="totalBalance">¥0.00</div>
                    <div class="summary-label">总余额</div>
                </div>
            </div>
        </div>

        <div class="card" id="validKeysCard">
            <div class="card-header">
                <h2 class="card-title">
                    <i class="fas fa-check-circle"></i>
                    有效密钥 <span class="badge-count" id="validKeyCount">0</span>
                </h2>
                <div class="actions-group">
                    <button id="sortBalanceBtn" class="btn btn-outline btn-sm sort-button">
                        <i class="fas fa-sort-amount-down sort-icon"></i>
                        余额排序
                    </button>
                    <button id="copyCommaBtn" class="btn btn-outline btn-sm">
                        <i class="fas fa-copy"></i>
                        逗号分隔复制
                    </button>
                    <button id="copyLineBtn" class="btn btn-outline btn-sm">
                        <i class="fas fa-copy"></i>
                        换行分隔复制
                    </button>
                    <button id="exportCsvBtn" class="btn btn-outline btn-sm">
                        <i class="fas fa-download"></i>
                        导出CSV
                    </button>
                </div>
            </div>

            <div class="table-container">
                <table>
                    <thead>
                        <tr>
                            <th>用户信息</th>
                            <th>账户状态</th>
                            <th>赠送余额</th>
                            <th>充值余额</th>
                            <th class="sortable" data-sort="totalBalance">
                                总余额
                                <span class="sort-icon"><i class="fas fa-sort"></i></span>
                            </th>
                            <th>API密钥</th>
                        </tr>
                    </thead>
                    <tbody id="validResultsBody">
                    </tbody>
                </table>
            </div>

            <div class="cards-view" id="validCardsView">
            </div>

            <div id="emptyValidState" class="empty-state empty-valid">
                <div class="empty-icon">
                    <i class="fas fa-check-circle"></i>
                </div>
                <h3 class="empty-title">暂无有效密钥</h3>
                <p class="empty-message">查询完成后,有效的API密钥将显示在这里</p>
            </div>
        </div>

        <div class="card" id="invalidKeysCard">
            <div class="card-header">
                <h2 class="card-title">
                    <i class="fas fa-times-circle"></i>
                    无效密钥 <span class="badge-count" id="invalidKeyCount">0</span>
                </h2>
            </div>

            <div class="table-container">
                <table>
                    <thead>
                        <tr>
                            <th>API密钥</th>
                            <th>错误信息</th>
                        </tr>
                    </thead>
                    <tbody id="invalidResultsBody">
                    </tbody>
                </table>
            </div>

            <div class="cards-view" id="invalidCardsView">
            </div>

            <div id="emptyInvalidState" class="empty-state empty-invalid">
                <div class="empty-icon">
                    <i class="fas fa-times-circle"></i>
                </div>
                <h3 class="empty-title">暂无无效密钥</h3>
                <p class="empty-message">查询完成后,无效或失败的API密钥将显示在这里</p>
            </div>
        </div>
    </div>

    <footer class="footer">
        <div class="footer-text">
            &copy; <span id="currentYear"></span> SiliconFlow - 批量账户查询工具
        </div>
    </footer>
</div>

<div class="toast-container" id="toastContainer"></div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        document.getElementById('currentYear').textContent = new Date().getFullYear();
        
        const form = document.getElementById('apiKeysForm');
        const apiKeysInput = document.getElementById('apiKeysInput');
        const errorAlert = document.getElementById('errorAlert');
        const errorMessage = document.getElementById('errorMessage');
        const successAlert = document.getElementById('successAlert');
        const successMessage = document.getElementById('successMessage');
        const loadingContainer = document.getElementById('loadingContainer');
        const currentProgress = document.getElementById('currentProgress');
        const totalKeys = document.getElementById('totalKeys');
        const progressBar = document.getElementById('progressBar');
        const progressPercentage = document.getElementById('progressPercentage');
        const resultsSection = document.getElementById('resultsSection');
        const totalQueriesEl = document.getElementById('totalQueries');
        const validQueriesEl = document.getElementById('validQueries');
        const invalidQueriesEl = document.getElementById('invalidQueries');
        const totalBalanceEl = document.getElementById('totalBalance');
        const validKeyCount = document.getElementById('validKeyCount');
        const invalidKeyCount = document.getElementById('invalidKeyCount');
        const validResultsBody = document.getElementById('validResultsBody');
        const invalidResultsBody = document.getElementById('invalidResultsBody');
        const validCardsView = document.getElementById('validCardsView');
        const invalidCardsView = document.getElementById('invalidCardsView');
        const emptyValidState = document.getElementById('emptyValidState');
        const emptyInvalidState = document.getElementById('emptyInvalidState');
        const sortBalanceBtn = document.getElementById('sortBalanceBtn');
        const copyCommaBtn = document.getElementById('copyCommaBtn');
        const copyLineBtn = document.getElementById('copyLineBtn');
        const exportCsvBtn = document.getElementById('exportCsvBtn');
        const detectedKeysInfo = document.getElementById('detectedKeysInfo');
        const detectedKeysCount = document.getElementById('detectedKeysCount');
        const toastContainer = document.getElementById('toastContainer');
        
        let validResults = [];
        let invalidResults = [];
        let extractedKeys = [];
        
        let sortDirection = 'desc';
        
        function showError(message) {
            errorMessage.textContent = message;
            errorAlert.classList.add('show');
            successAlert.classList.remove('show');
            
            setTimeout(() => {
                errorAlert.classList.remove('show');
            }, 5000);
        }
        
        function showSuccess(message) {
            successMessage.textContent = message;
            successAlert.classList.add('show');
            errorAlert.classList.remove('show');
            
            setTimeout(() => {
                successAlert.classList.remove('show');
            }, 5000);
        }
        
        function showToast(message, type = 'info') {
            const toast = document.createElement('div');
            toast.className = `toast toast-${type}`;
            
            const iconMap = {
                success: 'check-circle',
                error: 'exclamation-circle',
                info: 'info-circle'
            };
            
            toast.innerHTML = `
                <div class="toast-icon">
                    <i class="fas fa-${iconMap[type] || 'info-circle'}"></i>
                </div>
                <div class="toast-content">${message}</div>
            `;
            
            toastContainer.appendChild(toast);
            
            setTimeout(() => {
                toast.classList.add('show');
            }, 10);
            
            setTimeout(() => {
                toast.classList.remove('show');
                setTimeout(() => {
                    toastContainer.removeChild(toast);
                }, 300);
            }, 3000);
        }
        
        async function copyToClipboard(text) {
            try {
                await navigator.clipboard.writeText(text);
                showToast('复制成功', 'success');
                return true;
            } catch (err) {
                console.error('复制失败:', err);
                showToast('复制失败,请手动复制', 'error');
                return false;
            }
        }
        
        function extractApiKeys(text) {
            if (!text.trim()) return [];
            
            const regex = /sk-[a-zA-Z0-9]{48}/g;
            const matches = text.match(regex) || [];
            
            return [...new Set(matches)];
        }
        
        apiKeysInput.addEventListener('input', function() {
            const text = this.value;
            extractedKeys = extractApiKeys(text);
            
            if (extractedKeys.length > 0) {
                detectedKeysCount.textContent = extractedKeys.length;
                detectedKeysInfo.style.display = 'flex';
            } else {
                detectedKeysInfo.style.display = 'none';
            }
        });
        
        function formatCurrency(value) {
            return `¥${parseFloat(value || 0).toFixed(4)}`;
        }
        
        function isPhoneEmail(email) {
            return email && email.endsWith('@sf.cn');
        }
        
        function getRoleDisplay(role) {
            if (!role || role === 'user' || role === 'user_role') {
                return '';
            }
            
            const roleMap = {
                'admin': { text: '管理员' },
                'vip': { text: 'VIP用户' }
            };
            
            const roleInfo = roleMap[role.toLowerCase()] || { text: role };
            return `<div class="user-role">${roleInfo.text}</div>`;
        }
        
        async function queryApiKey(apiKey) {
            try {
                const response = await fetch('https://api.siliconflow.cn/v1/user/info', {
                    method: 'GET',
                    headers: {
                        'Authorization': `Bearer ${apiKey}`
                    }
                });
                
                const data = await response.json();
                
                if (!response.ok || !data.status) {
                    throw new Error(data.message || '获取账户信息失败');
                }
                
                return {
                    success: true,
                    data: data.data,
                    apiKey
                };
            } catch (error) {
                return {
                    success: false,
                    error: error.message || '查询失败',
                    apiKey
                };
            }
        }
        
        function createValidTableRow(result) {
            const row = document.createElement('tr');
            row.className = 'valid-entry';
            row.dataset.totalBalance = parseFloat(result.data.totalBalance || 0);
            
            const user = result.data;
            const initial = ((user.name || '用户')[0] || 'U').toUpperCase();
            
            let contactHTML = '';
            if (user.email) {
                if (isPhoneEmail(user.email)) {
                    contactHTML = `<div class="user-contact"><i class="fas fa-mobile-alt"></i> ${user.email.split('@')[0]}</div>`;
                } else {
                    contactHTML = `<div class="user-contact"><i class="fas fa-envelope"></i> ${user.email}</div>`;
                }
            }
            
            const isNormalStatus = user.status === 'normal';
            const statusClass = isNormalStatus ? 'status-active' : 'status-warning';
            const statusText = isNormalStatus ? '正常' : user.status;
            const statusIcon = isNormalStatus ? 'check-circle' : 'exclamation-circle';
            
            row.innerHTML = `
                <td>
                    <div class="user-cell">
                        <div class="user-avatar">
                            ${user.image ? `<img src="${user.image}" alt="${user.name || '用户'}" />` : initial}
                            ${user.isAdmin ? '<div class="admin-badge"><i class="fas fa-crown"></i></div>' : ''}
                        </div>
                        <div class="user-info">
                            <div class="user-name">${user.name || '未命名用户'}</div>
                            <div class="user-meta">
                                ${contactHTML}
                                ${getRoleDisplay(user.role)}
                            </div>
                        </div>
                    </div>
                </td>
                <td>
                    <span class="status-badge ${statusClass}">
                        <i class="fas fa-${statusIcon}"></i>
                        ${statusText}
                    </span>
                </td>
                <td><span class="amount-cell">${formatCurrency(user.balance)}</span></td>
                <td><span class="amount-cell">${formatCurrency(user.chargeBalance)}</span></td>
                <td><span class="amount-cell amount-total">${formatCurrency(user.totalBalance)}</span></td>
                <td>
                    <div class="api-key-cell">
                        <span class="key-text">${result.apiKey}</span>
                        <button class="copy-btn" data-key="${result.apiKey}">
                            <i class="fas fa-copy"></i> 复制
                        </button>
                    </div>
                </td>
            `;
            
            const copyBtn = row.querySelector('.copy-btn');
            copyBtn.addEventListener('click', async function() {
                const key = this.getAttribute('data-key');
                const success = await copyToClipboard(key);
                
                if (success) {
                    this.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    this.classList.add('copied');
                    
                    setTimeout(() => {
                        this.innerHTML = '<i class="fas fa-copy"></i> 复制';
                        this.classList.remove('copied');
                    }, 2000);
                }
            });
            
            return row;
        }
        
        function createValidCard(result) {
            const card = document.createElement('div');
            card.className = 'result-card valid-card';
            card.dataset.totalBalance = parseFloat(result.data.totalBalance || 0);
            
            const user = result.data;
            const initial = ((user.name || '用户')[0] || 'U').toUpperCase();
            
            let contactText = '未设置';
            let contactIcon = 'user';
            if (user.email) {
                if (isPhoneEmail(user.email)) {
                    contactText = user.email.split('@')[0];
                    contactIcon = 'mobile-alt';
                } else {
                    contactText = user.email;
                    contactIcon = 'envelope';
                }
            }
            
            const isNormalStatus = user.status === 'normal';
            const statusClass = isNormalStatus ? 'status-active' : 'status-warning';
            const statusText = isNormalStatus ? '正常' : user.status;
            const statusIcon = isNormalStatus ? 'check-circle' : 'exclamation-circle';
            
            card.innerHTML = `
                <div class="card-row">
                    <div class="user-cell">
                        <div class="user-avatar">
                            ${user.image ? `<img src="${user.image}" alt="${user.name || '用户'}" />` : initial}
                            ${user.isAdmin ? '<div class="admin-badge"><i class="fas fa-crown"></i></div>' : ''}
                        </div>
                        <div class="user-info">
                            <div class="user-name">${user.name || '未命名用户'}</div>
                            <div class="user-meta">
                                <div class="user-contact">
                                    <i class="fas fa-${contactIcon}"></i> ${contactText}
                                </div>
                                ${getRoleDisplay(user.role)}
                            </div>
                        </div>
                    </div>
                    <span class="status-badge ${statusClass}">
                        <i class="fas fa-${statusIcon}"></i>
                        ${statusText}
                    </span>
                </div>
                
                <div class="card-divider"></div>
                
                <div class="card-row" style="justify-content: center;">
                    <div class="balance-group">
                        <div class="card-label">赠送余额</div>
                        <div class="card-value amount-cell">${formatCurrency(user.balance)}</div>
                    </div>
                    <div class="balance-group">
                        <div class="card-label">充值余额</div>
                        <div class="card-value amount-cell">${formatCurrency(user.chargeBalance)}</div>
                    </div>
                    <div class="balance-group">
                        <div class="card-label">总余额</div>
                        <div class="card-value amount-cell amount-total">${formatCurrency(user.totalBalance)}</div>
                    </div>
                </div>
                
                <div class="card-divider"></div>
                
                <div class="card-row">
                    <div style="flex: 1; min-width: 0;">
                        <div class="card-label">API密钥</div>
                        <div class="card-value api-key-cell">
                            <span class="key-text">${result.apiKey}</span>
                        </div>
                    </div>
                    <button class="copy-btn" data-key="${result.apiKey}">
                        <i class="fas fa-copy"></i> 复制
                    </button>
                </div>
            `;
            
            const copyBtn = card.querySelector('.copy-btn');
            copyBtn.addEventListener('click', async function() {
                const key = this.getAttribute('data-key');
                const success = await copyToClipboard(key);
                
                if (success) {
                    this.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    this.classList.add('copied');
                    
                    setTimeout(() => {
                        this.innerHTML = '<i class="fas fa-copy"></i> 复制';
                        this.classList.remove('copied');
                    }, 2000);
                }
            });
            
            return card;
        }
        
        function createInvalidTableRow(result) {
            const row = document.createElement('tr');
            row.className = 'invalid-entry';
            
            row.innerHTML = `
                <td>
                    <div class="api-key-cell">
                        <span class="key-text">${result.apiKey}</span>
                        <button class="copy-btn" data-key="${result.apiKey}">
                            <i class="fas fa-copy"></i> 复制
                        </button>
                    </div>
                </td>
                <td>
                    <div class="error-cell">${result.error}</div>
                </td>
            `;
            
            const copyBtn = row.querySelector('.copy-btn');
            copyBtn.addEventListener('click', async function() {
                const key = this.getAttribute('data-key');
                const success = await copyToClipboard(key);
                
                if (success) {
                    this.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    this.classList.add('copied');
                    
                    setTimeout(() => {
                        this.innerHTML = '<i class="fas fa-copy"></i> 复制';
                        this.classList.remove('copied');
                    }, 2000);
                }
            });
            
            return row;
        }
        
        function createInvalidCard(result) {
            const card = document.createElement('div');
            card.className = 'result-card invalid-card';
            
            card.innerHTML = `
                <div class="card-row">
                    <div style="flex: 1; min-width: 0;">
                        <div class="card-label">API密钥</div>
                        <div class="card-value api-key-cell">
                            <span class="key-text">${result.apiKey}</span>
                        </div>
                    </div>
                    <button class="copy-btn" data-key="${result.apiKey}">
                        <i class="fas fa-copy"></i> 复制
                    </button>
                </div>
                
                <div class="card-divider"></div>
                
                <div>
                    <div class="card-label">错误信息</div>
                    <div class="card-value error-cell">${result.error}</div>
                </div>
            `;
            
            const copyBtn = card.querySelector('.copy-btn');
            copyBtn.addEventListener('click', async function() {
                const key = this.getAttribute('data-key');
                const success = await copyToClipboard(key);
                
                if (success) {
                    this.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    this.classList.add('copied');
                    
                    setTimeout(() => {
                        this.innerHTML = '<i class="fas fa-copy"></i> 复制';
                        this.classList.remove('copied');
                    }, 2000);
                }
            });
            
            return card;
        }
        
        function sortResultsByBalance() {
            sortDirection = sortDirection === 'desc' ? 'asc' : 'desc';
            
            const sortIcon = sortBalanceBtn.querySelector('.sort-icon');
            sortIcon.className = `fas fa-sort-amount-${sortDirection === 'desc' ? 'down' : 'up'} sort-icon`;
            
            const tableHeaderIcon = document.querySelector('th[data-sort="totalBalance"] .sort-icon i');
            tableHeaderIcon.className = `fas fa-sort-${sortDirection === 'desc' ? 'down' : 'up'}`;
            
            const sortedResults = [...validResults];
            
            sortedResults.sort((a, b) => {
                const balanceA = parseFloat(a.data.totalBalance || 0);
                const balanceB = parseFloat(b.data.totalBalance || 0);
                
                if (sortDirection === 'desc') {
                    return balanceB - balanceA;
                } else {
                    return balanceA - balanceB;
                }
            });
            
            validResultsBody.innerHTML = '';
            validCardsView.innerHTML = '';
            
            sortedResults.forEach(result => {
                validResultsBody.appendChild(createValidTableRow(result));
                validCardsView.appendChild(createValidCard(result));
            });
            
            showToast(`已按总余额${sortDirection === 'desc' ? '从高到低' : '从低到高'}排序`, 'success');
        }
        
        async function batchQueryApiKeys(apiKeys) {
            validResults = [];
            invalidResults = [];
            validResultsBody.innerHTML = '';
            invalidResultsBody.innerHTML = '';
            validCardsView.innerHTML = '';
            invalidCardsView.innerHTML = '';
            
            totalKeys.textContent = apiKeys.length;
            
            let totalBalanceSum = 0;
            
            for (let i = 0; i < apiKeys.length; i++) {
                const apiKey = apiKeys[i];
                
                const progress = Math.round(((i + 1) / apiKeys.length) * 100);
                currentProgress.textContent = i + 1;
                progressBar.style.width = `${progress}%`;
                progressPercentage.textContent = `${progress}%`;
                
                const result = await queryApiKey(apiKey);
                
                if (result.success) {
                    validResults.push(result);
                    totalBalanceSum += parseFloat(result.data.totalBalance || 0);
                    
                    validResultsBody.appendChild(createValidTableRow(result));
                    validCardsView.appendChild(createValidCard(result));
                } else {
                    invalidResults.push(result);
                    
                    invalidResultsBody.appendChild(createInvalidTableRow(result));
                    invalidCardsView.appendChild(createInvalidCard(result));
                }
                
                await new Promise(resolve => setTimeout(resolve, 50));
            }
            
            totalQueriesEl.textContent = apiKeys.length;
            validQueriesEl.textContent = validResults.length;
            invalidQueriesEl.textContent = invalidResults.length;
            totalBalanceEl.textContent = formatCurrency(totalBalanceSum);
            
            validKeyCount.textContent = validResults.length;
            invalidKeyCount.textContent = invalidResults.length;
            
            emptyValidState.style.display = validResults.length > 0 ? 'none' : 'flex';
            emptyInvalidState.style.display = invalidResults.length > 0 ? 'none' : 'flex';
            
            if (validResults.length > 0) {
                const sortedResults = [...validResults].sort((a, b) => {
                    const balanceA = parseFloat(a.data.totalBalance || 0);
                    const balanceB = parseFloat(b.data.totalBalance || 0);
                    return balanceB - balanceA;
                });
                
                validResultsBody.innerHTML = '';
                validCardsView.innerHTML = '';
                
                sortedResults.forEach(result => {
                    validResultsBody.appendChild(createValidTableRow(result));
                    validCardsView.appendChild(createValidCard(result));
                });
                
                const sortIcon = sortBalanceBtn.querySelector('.sort-icon');
                if (sortIcon) sortIcon.className = 'fas fa-sort-amount-down sort-icon';
                
                const tableHeaderIcon = document.querySelector('th[data-sort="totalBalance"] .sort-icon i');
                if (tableHeaderIcon) tableHeaderIcon.className = 'fas fa-sort-down';
            }
            
            return {
                totalQueries: apiKeys.length,
                validResults,
                invalidResults,
                totalBalanceSum
            };
        }
        
        form.addEventListener('submit', async function(e) {
            e.preventDefault();
            
            const text = apiKeysInput.value.trim();
            if (!text) {
                showError('请输入包含API密钥的文本');
                return;
            }
            
            const apiKeys = extractApiKeys(text);
            
            if (apiKeys.length === 0) {
                showError('未检测到有效的API密钥(格式:sk-开头加48个字符)');
                return;
            }
            
            errorAlert.classList.remove('show');
            successAlert.classList.remove('show');
            form.style.display = 'none';
            loadingContainer.classList.add('show');
            
            try {
                await batchQueryApiKeys(apiKeys);
                
                resultsSection.classList.add('show');
                
                showSuccess(`成功查询 ${apiKeys.length} 个API密钥,其中 ${validResults.length} 个有效`);
            } catch (error) {
                showError('批量查询过程中发生错误');
                console.error('批量查询错误:', error);
            } finally {
                loadingContainer.classList.remove('show');
                form.style.display = 'block';
            }
        });
        
        sortBalanceBtn.addEventListener('click', sortResultsByBalance);
        
        document.querySelector('th[data-sort="totalBalance"]').addEventListener('click', sortResultsByBalance);
        
        copyCommaBtn.addEventListener('click', function() {
            if (validResults.length === 0) {
                showToast('没有可复制的有效密钥', 'error');
                return;
            }
            
            const keys = validResults.map(result => result.apiKey);
            copyToClipboard(keys.join(','));
        });
        
        copyLineBtn.addEventListener('click', function() {
            if (validResults.length === 0) {
                showToast('没有可复制的有效密钥', 'error');
                return;
            }
            
            const keys = validResults.map(result => result.apiKey);
            copyToClipboard(keys.join('\n'));
        });
        
        exportCsvBtn.addEventListener('click', function() {
            if (validResults.length === 0 && invalidResults.length === 0) {
                showToast('没有可导出的查询结果', 'error');
                return;
            }
            
            const headers = ['"状态","API密钥","用户名","联系方式","账户状态","赠送余额","充值余额","总余额","错误信息"'];
            const rows = [];
            
            validResults.forEach(result => {
                const user = result.data;
                const userName = user.name || '未命名用户';
                
                let contact = '';
                if (user.email) {
                    contact = isPhoneEmail(user.email) ? user.email.split('@')[0] : user.email;
                } else {
                    contact = '未设置';
                }
                
                const status = user.status === 'normal' ? '正常' : user.status;
                const balance = parseFloat(user.balance || 0).toFixed(4);
                const chargeBalance = parseFloat(user.chargeBalance || 0).toFixed(4);
                const totalBalance = parseFloat(user.totalBalance || 0).toFixed(4);
                
                rows.push(`"有效","${result.apiKey}","${userName}","${contact}","${status}","${balance}","${chargeBalance}","${totalBalance}",""`);
            });
            
            invalidResults.forEach(result => {
                rows.push(`"无效","${result.apiKey}","","","","","","","${result.error}"`);
            });
            
            const csvData = headers.concat(rows).join('\n');
            const blob = new Blob(["\uFEFF" + csvData], { type: 'text/csv;charset=utf-8;' });
            const url = URL.createObjectURL(blob);
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19);
            
            const link = document.createElement('a');
            link.setAttribute('href', url);
            link.setAttribute('download', `SiliconFlow_查询结果_${timestamp}.csv`);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            showToast('导出成功', 'success');
        });
        
        apiKeysInput.addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && e.ctrlKey) {
                form.dispatchEvent(new Event('submit'));
            }
        });
    });
</script>


93 Likes

@yeahhe 还不快试试

8 Likes

优秀,太优秀了

6 Likes


有些太好用了哈哈,感谢强佬!

5 Likes

已使用,牛叉~

5 Likes

太酷啦~

3 Likes

感谢楼主的分享~用上了tieba_026

2 Likes

拿来主义,发动! :heart_eyes:

2 Likes

把余额不够的区分开来比较好吧

佬可以加个设置最低余额吗

好用,好看,顶一个

1 Like

支持批量吗佬

为啥这么帅

真的是很帅

连着贴了好几个 :tieba_025:

2 Likes

帅。省事了

确实帅!

已使用 确实帅

确实好看

用佬的代码改了一下,一个cloudflare worker版本,在线更方便
贴一个demo: SiliconFlow - 批量余额查询

额外加了这两个:

@Baby1 快来


cf-worker-siliconflow-checker.txt (75.7 KB)

8 Likes