943 lines
61 KiB
HTML
943 lines
61 KiB
HTML
|
||
{% extends "base.html" %}
|
||
{% block title %}API 分组管理 - GEMINI BALANCER{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="w-full h-full flex flex-col pl-0 pr-3 lg:px-0">
|
||
<!-- [核心] 页面顶栏:标题与全局控制器 -->
|
||
<div class="flex items-center justify-between mb-6 shrink-0">
|
||
<h2 class="text-3xl font-bold tracking-tight">API 管理</h2>
|
||
<button class="lg:hidden text-zinc-500 dark:text-zinc-400">
|
||
<i class="fas fa-search text-lg"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="flex flex-col lg:flex-row flex-grow gap-x-4 overflow-hidden min-h-0">
|
||
|
||
<!-- 左侧分栏: Group 列表 -->
|
||
<aside class="w-full lg:w-1/4 flex flex-col p-0 relative mb-3 lg:mb-0 lg:min-h-0 shrink-0">
|
||
<!-- 桌面端搜索框 -->
|
||
<div class="relative mb-3 mr-4 shrink-0 hidden lg:block">
|
||
<input type="text" class="pl-8 h-9 bg-transparent border border-gray-300 dark:border-gray-700 dark:text-white w-full rounded-md text-sm transition-colors duration-200 ease-in-out focus:outline-none focus:border-blue-500 dark:focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:ring-inset" placeholder="Search Groups...">
|
||
<i class="fas fa-search w-4 absolute text-gray-400 top-1/2 transform -translate-y-1/2 left-3"></i>
|
||
</div>
|
||
|
||
<!-- 移动端首屏控件 -->
|
||
<div class="lg:hidden flex items-center gap-x-2">
|
||
<div class="mobile-group-selector">
|
||
<div>
|
||
<h3 class="font-semibold text-sm">Loading...</h3>
|
||
<p class="card-sub-text">当前选择</p>
|
||
</div>
|
||
<button id="group-menu-toggle" class="text-zinc-500 dark:text-zinc-400">
|
||
<i class="fas fa-bars text-lg"></i>
|
||
</button>
|
||
</div>
|
||
<div id="add-group-btn-container-mobile" class="shrink-0">
|
||
<button class="add-group-btn add-group-btn-mobile flex items-center justify-center rounded-lg border-2 border-dashed transition-all duration-200">
|
||
<i class="fas fa-plus text-lg"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="group-list-collapsible" class="hidden lg:flex flex-col flex-grow overflow-y-auto pr-1">
|
||
<div id="desktop-group-cards-list" class="hidden lg:flex flex-col">
|
||
|
||
<div class="card-list-content space-y-2"><!-- JS通过 desktopGroupContainer 选择器填充这里 --></div>
|
||
|
||
<div id="add-group-btn-container" class="sticky pr-1 bottom-0 mt-2 mr-2 shrink-0 pt-2 bg-white dark:bg-zinc-800">
|
||
<button class="add-group-btn add-group-btn-desktop flex items-center justify-center rounded-lg border-2 border-dashed transition-all duration-200">
|
||
<i class="fas fa-plus text-lg"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- [移动端] 列表 -->
|
||
<div id="mobile-group-cards-list" class="block lg:hidden space-y-2"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
{# 右侧主内容区: Group 详情与 API 管理 #}
|
||
<main class="w-full lg:w-3/4 flex flex-grow flex-col gap-y-4 overflow-y-auto lg:min-h-0">
|
||
<!-- Group Dashboard -->
|
||
<div id="group-dashboard" class="bg-zinc-100 dark:bg-zinc-900/50 border border-zinc-200 dark:border-zinc-700/60 rounded-lg p-4 shrink-0">
|
||
<!-- Header -->
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold">默认分组 (Default)</h2>
|
||
<div class="flex items-center gap-x-3 text-zinc-400">
|
||
<button data-action="clone-group" class="hover:text-blue-500 transition-colors duration-200" title="克隆分组"><i class="fas fa-clone"></i></button>
|
||
<button data-action="edit-group" class="hover:text-blue-500 transition-colors duration-200" title="编辑分组"><i class="fas fa-cog"></i></button>
|
||
<button data-action="open-settings" class="hover:text-blue-500 transition-colors duration-200" title="高级请求设置"><i class="fas fa-sliders-h"></i></button>
|
||
<button data-action="delete-group" class="hover:text-red-500 transition-colors duration-200" title="删除分组"><i class="fas fa-trash"></i></button>
|
||
</div>
|
||
</div>
|
||
<!-- Stats -->
|
||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 text-center">
|
||
<!-- 密钥统计 -->
|
||
<div>
|
||
<p class="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">7 / 10</p>
|
||
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">有效密钥 / 总密钥数</p>
|
||
<div class="mt-2 h-4"></div> <!-- 健康度图标占位 -->
|
||
</div>
|
||
<!-- 请求总览 -->
|
||
<div>
|
||
<p class="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">0</p>
|
||
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">24小时请求数</p>
|
||
<div class="mt-2 h-4"></div> <!-- 健康度图标占位 -->
|
||
</div>
|
||
<!-- Token 消耗 -->
|
||
<div>
|
||
<p class="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">0</p>
|
||
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">24小时消耗</p>
|
||
<div class="mt-2 h-4"></div> <!-- 健康度图标占位 -->
|
||
</div>
|
||
<!-- 请求成功率 -->
|
||
<div>
|
||
<p class="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">0%</p>
|
||
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">24小时成功率</p>
|
||
<div class="mt-2 h-4"></div> <!-- 健康度图标占位 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- API Management Area -->
|
||
<div class="bg-zinc-100 border border-zinc-200 dark:border-zinc-700/60 dark:bg-zinc-900/50 rounded-lg p-4 flex-grow flex flex-col lg:min-h-0">
|
||
<!-- Controls Header (已进行响应式重构 - V3 Final) -->
|
||
<div class="flex flex-col gap-y-3 mb-4">
|
||
|
||
<!--
|
||
============================================================
|
||
移动端第一行 / 桌面端完整操作行
|
||
============================================================
|
||
- 使用 justify-between 将左右两组推开。
|
||
-->
|
||
<div class="flex items-center justify-between">
|
||
<!-- 左侧主要操作 (始终显示) -->
|
||
<div class="flex items-center gap-x-2">
|
||
<button id="add-api-btn" class="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors">
|
||
<i class="fas fa-plus mr-1"></i> KEY
|
||
</button>
|
||
<button id="delete-api-btn" class="px-3 py-1.5 text-sm bg-red-600/80 text-white rounded-md hover:bg-red-700 transition-colors">
|
||
<i class="fas fa-minus mr-1"></i> KEY
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 右侧操作组 -->
|
||
<div class="flex items-center gap-x-2">
|
||
<!-- 移动端: 快速处置 -->
|
||
<div class="lg:hidden items-center gap-x-2 relative inline-block custom-select" id="mobile-quick-actions-dropdown">
|
||
<button class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors custom-select-trigger">
|
||
<i class="fas fa-bolt"></i>
|
||
</button>
|
||
<div class="dropdown-panel z-30 w-48 custom-select-panel hidden" id="mobile-quick-actions-panel">
|
||
<!-- Dropdown content will be injected by JavaScript -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 桌面端操作组 (lg及以上屏幕显示) -->
|
||
<div class="hidden lg:flex items-center gap-x-2">
|
||
<div class="relative inline-block batch-action-dropdown custom-select">
|
||
<button class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors flex items-center gap-x-2 batch-action-btn custom-select-trigger">
|
||
<span>批量操作</span>
|
||
<i class="fas fa-chevron-down text-xs text-zinc-400"></i>
|
||
</button>
|
||
<div class="dropdown-panel batch-action-panel custom-select-panel hidden">
|
||
<div class="py-1">
|
||
<button data-batch-action="copy-to-clipboard" class="menu-item">
|
||
<i class="fas fa-copy menu-item-icon menu-item-icon-neutral"></i>
|
||
<span>批量复制</span>
|
||
</button>
|
||
<button data-batch-action="set-status-active" class="menu-item">
|
||
<i class="fas fa-check-circle menu-item-icon text-green-500"></i>
|
||
<span>批量启用</span>
|
||
</button>
|
||
<button data-batch-action="set-status-disabled" class="menu-item">
|
||
<i class="fas fa-ban menu-item-icon text-yellow-500"></i>
|
||
<span>批量禁用</span>
|
||
</button>
|
||
<button data-batch-action="revalidate" class="menu-item">
|
||
<i class="fas fa-rocket menu-item-icon text-blue-500"></i>
|
||
<span>批量验证</span>
|
||
</button>
|
||
|
||
<!-- Use the new .menu-divider class -->
|
||
<div class="menu-divider"></div>
|
||
|
||
<!-- Use the base class and the danger modifier -->
|
||
<button data-batch-action="delete" class="menu-item menu-item-danger">
|
||
<i class="fas fa-trash-alt menu-item-icon"></i> <!-- Color is inherited from .menu-item-danger -->
|
||
<span>批量移除</span>
|
||
</button>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 桌面端: 快速处置 -->
|
||
<div class="relative inline-block custom-select" id="desktop-quick-actions-dropdown">
|
||
<button class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors flex items-center gap-x-2 custom-select-trigger">
|
||
<i class="fas fa-bolt"></i>
|
||
<span>快速处置</span>
|
||
</button>
|
||
<div class="dropdown-panel z-30 w-48 custom-select-panel hidden" id="desktop-quick-actions-panel">
|
||
<!-- Dropdown content will be injected by JavaScript -->
|
||
</div>
|
||
</div>
|
||
<div class="relative inline-block text-left">
|
||
<!-- 1. The Trigger Button -->
|
||
<button data-toggle="custom-select"
|
||
data-target="#desktop-multifunction-panel"
|
||
class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors">
|
||
<i class="fas fa-ellipsis-h"></i>
|
||
</button>
|
||
|
||
<!-- 2. The Dropdown Panel (initially hidden) -->
|
||
<div id="desktop-multifunction-panel"
|
||
class="custom-select-panel absolute right-0 z-30 mt-2 min-w-max origin-top-right rounded-md bg-white dark:bg-zinc-800 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none hidden">
|
||
<!-- JS will inject menu items here -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!--
|
||
============================================================
|
||
移动端第二行 / 桌面端完整过滤行
|
||
============================================================
|
||
- display: lg:hidden 表示此行在桌面端将被隐藏,仅用于移动端布局。
|
||
-->
|
||
<div class="flex items-center justify-between lg:hidden">
|
||
<!-- 左侧:状态选择器 -->
|
||
<div class="custom-select relative status-filter-select">
|
||
<select class="hidden">
|
||
<option value="all">所有状态</option>
|
||
<option value="active">有效</option>
|
||
<option value="cooldown">冷却</option>
|
||
<option value="pending">待验证</option>
|
||
<option value="disabled">禁用</option>
|
||
<option value="banned">无效</option>
|
||
</select>
|
||
<div class="custom-select-trigger flex items-center justify-between w-32 cursor-pointer rounded-md border border-zinc-300 dark:border-zinc-600 bg-transparent px-3 py-1.5">
|
||
<span>所有状态</span>
|
||
<i class="fas fa-chevron-down text-xs text-zinc-400"></i>
|
||
</div>
|
||
<div class="custom-select-panel hidden absolute z-10 mt-1 w-full rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-600 dark:bg-zinc-700"></div>
|
||
</div>
|
||
<!-- 右侧:批量操作 和 多功能按钮 -->
|
||
<div class="flex items-center gap-x-2">
|
||
<div class="relative inline-block batch-action-dropdown custom-select">
|
||
<button class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors flex items-center gap-x-2 batch-action-btn custom-select-trigger">
|
||
<span>批量操作</span>
|
||
<i class="fas fa-chevron-down text-xs text-zinc-400"></i>
|
||
</button>
|
||
<div class="dropdown-panel batch-action-panel custom-select-panel hidden">
|
||
<div class="py-1">
|
||
<button data-batch-action="copy-to-clipboard" class="menu-item">
|
||
<i class="fas fa-copy menu-item-icon menu-item-icon-neutral"></i>
|
||
<span>批量复制</span>
|
||
</button>
|
||
<button data-batch-action="set-status-active" class="menu-item">
|
||
<i class="fas fa-check-circle menu-item-icon text-green-500"></i>
|
||
<span>批量启用</span>
|
||
</button>
|
||
<button data-batch-action="set-status-disabled" class="menu-item">
|
||
<i class="fas fa-ban menu-item-icon text-yellow-500"></i>
|
||
<span>批量禁用</span>
|
||
</button>
|
||
<button data-batch-action="revalidate" class="menu-item">
|
||
<i class="fas fa-rocket menu-item-icon text-blue-500"></i>
|
||
<span>批量验证</span>
|
||
</button>
|
||
|
||
<!-- Use the new .menu-divider class -->
|
||
<div class="menu-divider"></div>
|
||
|
||
<!-- Use the base class and the danger modifier -->
|
||
<button data-batch-action="delete" class="menu-item menu-item-danger">
|
||
<i class="fas fa-trash-alt menu-item-icon"></i> <!-- Color is inherited from .menu-item-danger -->
|
||
<span>批量移除</span>
|
||
</button>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="relative inline-block text-left">
|
||
<!-- 1. The Trigger Button -->
|
||
<button data-toggle="custom-select"
|
||
data-target="#desktop-multifunction-panel"
|
||
class="px-3 py-1.5 text-sm bg-zinc-200 dark:bg-zinc-700 rounded-md hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors">
|
||
<i class="fas fa-ellipsis-h"></i>
|
||
</button>
|
||
|
||
<!-- 2. The Dropdown Panel (initially hidden) -->
|
||
<div id="mobile-multifunction-panel"
|
||
class="custom-select-panel absolute right-0 z-30 mt-2 min-w-max origin-top-right rounded-md bg-white dark:bg-zinc-800 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none hidden">
|
||
<!-- JS will inject menu items here -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!--
|
||
============================================================
|
||
移动端第三行 / 合并入桌面端的第二行
|
||
============================================================
|
||
- 这个容器在两个断点都存在,但其内部元素的可见性不同。
|
||
-->
|
||
<div class="flex items-center justify-between text-sm">
|
||
<!-- 桌面端左侧: 状态选择器 -->
|
||
<div class="custom-select relative hidden lg:block status-filter-select">
|
||
<select class="hidden">
|
||
<option value="all">所有状态</option>
|
||
<option value="active">有效</option>
|
||
<option value="cooldown">冷却</option>
|
||
<option value="pending">待验证</option>
|
||
<option value="disabled">禁用</option>
|
||
<option value="banned">无效</option>
|
||
</select>
|
||
<div class="custom-select-trigger flex items-center justify-between w-32 cursor-pointer rounded-md border border-zinc-300 dark:border-zinc-600 bg-transparent px-3 py-1.5">
|
||
<span>所有状态</span>
|
||
<i class="fas fa-chevron-down text-xs text-zinc-400"></i>
|
||
</div>
|
||
<div class="custom-select-panel hidden absolute z-10 mt-1 w-full rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-600 dark:bg-zinc-700"></div>
|
||
</div>
|
||
|
||
<!-- 移动端左侧: 搜索图标 -->
|
||
<button id="mobile-search-btn" class="px-2 py-1.5 text-sm bg-transparent rounded-md hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors lg:hidden">
|
||
<i class="fas fa-search text-zinc-500"></i>
|
||
</button>
|
||
|
||
<!-- 右侧组 (通用) -->
|
||
<div class="flex items-center gap-x-3">
|
||
<!-- 桌面端搜索框 -->
|
||
<div id="desktop-search-container" class="relative hidden lg:block w-full sm:w-48">
|
||
<i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-zinc-500 dark:text-zinc-300"></i>
|
||
<input type="text" id="desktop-search-input" placeholder="模糊查找..." class="w-full pl-9 pr-3 py-1.5 text-sm text-zinc-500 dark:text-zinc-400 border border-zinc-300 dark:border-zinc-600 rounded-md bg-transparent focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||
</div>
|
||
<!-- 通用分页与选择 -->
|
||
<div class="custom-select relative items-per-page-select"> <!-- [ADD CLASS] -->
|
||
<select class="hidden">
|
||
<option value="20" selected>20</option> <!-- [ADD VALUE & SELECTED] -->
|
||
<option value="50">50</option>
|
||
<option value="100">100</option>
|
||
</select>
|
||
<div class="custom-select-trigger flex items-center justify-between w-28 cursor-pointer rounded-md border border-zinc-300 dark:border-zinc-600 bg-transparent px-3 py-1.5">
|
||
<span>20 / 页</span>
|
||
<i class="fas fa-chevron-down text-xs text-zinc-400"></i>
|
||
</div>
|
||
<div class="custom-select-panel hidden absolute z-30 mt-1 w-full rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-600 dark:bg-zinc-700"></div>
|
||
</div>
|
||
<div class="flex items-center gap-x-2">
|
||
<input type="checkbox" id="select-all" class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500">
|
||
<label for="select-all" class="text-zinc-600 dark:text-zinc-300">全选</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- API List Container -->
|
||
<div id="api-list-container" class="flex-grow overflow-y-auto pr-2 -mr-2 main-content-scroll">
|
||
<!-- Content will be rendered here by JS -->
|
||
</div>
|
||
|
||
<!-- Pagination Controls -->
|
||
<div class="pagination-controls flex justify-center items-center mt-4 pt-4 border-t border-zinc-200 dark:border-zinc-700 space-x-2 lg:shrink-0"> <!-- [ADD CLASS] -->
|
||
<!-- Content will be rendered here by JS -->
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block modals %}
|
||
<!-- Add/Edit Group Modal -->
|
||
<div id="keygroup-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel max-w-3xl max-h-[90vh]">
|
||
<!-- Header -->
|
||
<div class="modal-header shrink-0">
|
||
<h2 id="modal-title" class="modal-title">创建新的 Key Group</h2>
|
||
<button data-modal-close="keygroup-modal" id="modal-close-btn" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Form Body -->
|
||
<div class="modal-body flex-grow overflow-y-auto pr-4 -mr-4">
|
||
<div class="grid grid-cols-2 gap-x-6 gap-y-4">
|
||
<!-- Name -->
|
||
<div>
|
||
<label for="group-name" class="flex items-center modal-label">
|
||
<span>分组名称<span class="text-red-500">*</span></span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="分组的唯一程序内标识符,例如 'default-group'。创建后不可修改。"></i>
|
||
</label>
|
||
<input type="text" id="group-name" class="modal-input">
|
||
</div>
|
||
<!-- Display Name -->
|
||
<div>
|
||
<label for="group-display-name" class="flex items-center modal-label">
|
||
<span>显示名称<span class="text-red-500">*</span></span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="显示在UI上的名称,方便识别,例如'默认分组'。"></i>
|
||
</label>
|
||
<input type="text" id="group-display-name" class="modal-input">
|
||
</div>
|
||
<!-- Description -->
|
||
<div class="col-span-2">
|
||
<label for="group-description" class="flex items-center modal-label">
|
||
<span>描述</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="关于此分组用途的简短说明。"></i>
|
||
</label>
|
||
<textarea id="group-description" rows="2" class="modal-input"></textarea>
|
||
</div>
|
||
<!-- Allowed Models -->
|
||
<div class="col-span-2">
|
||
<label class="flex items-center modal-label">
|
||
<span>允许模型</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="允许该分组使用的模型ID列表。留空表示允许所有模型。"></i>
|
||
</label>
|
||
<div id="allowed-models-container" class="tag-input-container">
|
||
<span class="tag-item">gemini-pro<button class="tag-delete">×</button></span>
|
||
<span class="tag-item">gemini-1.5-pro-latest<button class="tag-delete">×</button></span>
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
<!-- Allowed Tokens -->
|
||
<div class="col-span-2">
|
||
<label class="flex items-center modal-label">
|
||
<span>专属密钥</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="只有列表中的认证令牌 (Auth Tokens) 才能使用此分组。留空则所有密钥都可用。"></i>
|
||
</label>
|
||
<div id="allowed-tokens-container" class="tag-input-container">
|
||
<input type="text" placeholder="添加专属密钥..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
<!-- Polling Strategy -->
|
||
<div>
|
||
<label for="group-strategy" class="flex items-center modal-label">
|
||
<span>轮询模式</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="从此分组中选择可用API Key的策略。"></i>
|
||
</label>
|
||
<select id="group-strategy" class="modal-input">
|
||
<option value="random">随机</option>
|
||
<option value="sequential">顺序</option>
|
||
<option value="weighted">加权</option>
|
||
</select>
|
||
</div>
|
||
<!-- Channel Type -->
|
||
<div>
|
||
<label for="group-channel-type" class="flex items-center modal-label">
|
||
<span>渠道类型</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="此分组关联的上游渠道类型,由系统确定。"></i>
|
||
</label>
|
||
<input type="text" id="group-channel-type" class="modal-input bg-zinc-100 dark:bg-zinc-700/50" value="Gemini" disabled>
|
||
</div>
|
||
|
||
<!-- Max Retries (新增) -->
|
||
<div>
|
||
<label for="group-max-retries" class="flex items-center modal-label">
|
||
<span>重试次数</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="单个请求使用不同Key的最大重试次数。"></i>
|
||
</label>
|
||
<input type="number" id="group-max-retries" class="modal-input" placeholder="默认: 3">
|
||
</div>
|
||
|
||
<!-- Failure Threshold-->
|
||
<div>
|
||
<label for="group-key-blacklist-threshold" class="flex items-center modal-label">
|
||
<span>失败阈值</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="连续失败多少次后将密钥列入冷却状态。"></i>
|
||
</label>
|
||
<input type="number" id="group-key-blacklist-threshold" class="modal-input" placeholder="默认: 3">
|
||
</div>
|
||
|
||
<!-- Enable Proxy -->
|
||
<div class="flex items-center">
|
||
<label for="group-enable-proxy" class="modal-label flex-grow flex items-center">
|
||
<span>启用代理</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="是否为此分组的请求启用系统配置的代理。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="group-enable-proxy" id="group-enable-proxy" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="group-enable-proxy" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
<!-- Enable Smart Gateway -->
|
||
<div class="flex items-center">
|
||
<label for="group-enable-smart-gateway" class="modal-label flex-grow flex items-center">
|
||
<span>启用智能网关</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="是否启用智能网关功能,自动处理模型映射和重试。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="group-enable-smart-gateway" id="group-enable-smart-gateway" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="group-enable-smart-gateway" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
<!-- Allowed Upstreams -->
|
||
<div class="col-span-2">
|
||
<label class="flex items-center modal-label">
|
||
<span>上游地址</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="指定可用的上游API地址。如果留空,将使用系统默认地址。"></i>
|
||
</label>
|
||
<div id="allowed-upstreams-container" class="tag-input-container">
|
||
<input type="text" placeholder="添加上游地址..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
<!-- Max Retries (Moved to Advanced Request Settings) -->
|
||
|
||
<!-- API Key Auto Validation -->
|
||
<div class="col-span-2 mt-2">
|
||
<div class="flex items-center justify-between">
|
||
<label for="group-enable-key-check" class="modal-label flex-grow flex items-center font-semibold">
|
||
<span>开启自动验证</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="启用后,系统将定期自动验证该分组下所有密钥的有效性。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="group-enable-key-check" id="group-enable-key-check" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer" checked>
|
||
<label for="group-enable-key-check" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
<!-- Collapsible settings for key check -->
|
||
<div id="key-check-settings" class="grid grid-cols-2 gap-x-6 gap-y-4 mt-4 ">
|
||
<!-- Detection Model (从全宽收缩为半宽,并移到最前) -->
|
||
<div>
|
||
<label for="group-key-check-model" class="flex items-center modal-label">
|
||
<span>检测模型</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="用于验证此分组下API Key有效性的模型ID。"></i>
|
||
</label>
|
||
<input type="text" id="group-key-check-model" class="modal-input" placeholder="默认: gemini-1.5-flash">
|
||
</div>
|
||
<!-- Detection Interval -->
|
||
<div>
|
||
<label for="group-key-check-interval-minutes" class="flex items-center modal-label">
|
||
<span>检测周期 (分钟)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="每隔多少分钟对分组内的密钥进行一次健康检查。"></i>
|
||
</label>
|
||
<input type="number" id="group-key-check-interval-minutes" class="modal-input" placeholder="默认: 60">
|
||
</div>
|
||
<!-- Detection Concurrency -->
|
||
<div>
|
||
<label for="group-key-check-concurrency" class="flex items-center modal-label">
|
||
<span>检测并发数</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="同时执行密钥验证的最大并发数。"></i>
|
||
</label>
|
||
<input type="number" id="group-key-check-concurrency" class="modal-input" placeholder="默认: 5">
|
||
</div>
|
||
<!-- Cooldown Duration -->
|
||
<div>
|
||
<label for="group-key-cooldown-minutes" class="flex items-center modal-label">
|
||
<span>冷却时长 (分钟)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="密钥进入冷却状态后,需要等待多长时间才能被再次检查。"></i>
|
||
</label>
|
||
<input type="number" id="group-key-cooldown-minutes" class="modal-input" placeholder="默认: 10">
|
||
</div>
|
||
<!-- Detection Endpoint (保持全宽) -->
|
||
<div class="col-span-2">
|
||
<label for="group-key-check-endpoint" class="flex items-center modal-label">
|
||
<span>检测端点</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="用于密钥验证的上游API地址。如果留空,将使用系统默认地址。"></i>
|
||
</label>
|
||
<input type="text" id="group-key-check-endpoint" class="modal-input" placeholder="留空以使用全局默认">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div class="modal-footer shrink-0">
|
||
<button data-modal-close="keygroup-modal" id="modal-cancel-btn" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button id="modal-save-btn" class="modal-btn modal-btn-primary">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add API Modal -->
|
||
<div id="add-api-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel">
|
||
<!-- Header -->
|
||
<div class="modal-header">
|
||
<h2 id="add-api-modal-title" class="modal-title">批量添加 API Keys</h2>
|
||
<button data-modal-close="add-api-modal" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Body 现在包含两个可切换的视图 -->
|
||
<div class="modal-body">
|
||
<!-- 视图 1: 输入视图 (默认显示) -->
|
||
<div id="add-api-input-view">
|
||
<label for="api-add-textarea" class="modal-label">API Keys (每行一个)</label>
|
||
<textarea id="api-add-textarea" rows="15" class="modal-input mt-1 font-mono text-xs"
|
||
placeholder="sk-abc... AIza... gsk_..."></textarea>
|
||
</div>
|
||
|
||
<!-- 视图 2: 结果/进度视图 (默认隐藏) -->
|
||
<div id="add-api-result-view" class="hidden">
|
||
<!-- 这里的内容将由JS动态填充 -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div id="add-api-modal-footer" class="modal-footer justify-between">
|
||
<!-- 左側:新增的驗證開關 -->
|
||
<div class="flex items-center space-x-4">
|
||
<input type="checkbox" id="validate-on-import-checkbox" class="form-checkbox h-5 w-5 ml-2 text-blue-600 focus:ring-blue-500 border-gray-300" checked>
|
||
<label for="validate-on-import-checkbox" class="text-sm font-medium text-zinc-700 dark:text-zinc-300 select-none"> 同步验证</label>
|
||
<i class="fas fa-question-circle text-gray-400 tooltip-icon"
|
||
data-tooltip-text="推荐开启。密钥导入后同步调用测试模型对API进行有效性验证,无效Key将被隔离。"></i>
|
||
</div>
|
||
|
||
<!-- 右側:現有的按鈕組 -->
|
||
<div class="flex items-center space-x-2">
|
||
<button data-modal-close="add-api-modal" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button id="add-api-import-btn" class="modal-btn modal-btn-primary">導入</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Delete API Modal -->
|
||
<div id="delete-api-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel">
|
||
<!-- Header -->
|
||
<div class="modal-header">
|
||
<h2 class="modal-title">批量删除 API Keys</h2>
|
||
<button data-modal-close="delete-api-modal" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
<!-- Body -->
|
||
<div class="modal-body">
|
||
<label for="api-delete-textarea" class="text-sm font-medium text-zinc-700 dark:text-zinc-300">API Keys (每行一个)</label>
|
||
<textarea id="api-delete-textarea" rows="15" class="modal-input mt-1 font-mono text-xs" placeholder="sk-abc... AIza... gsk_..."></textarea>
|
||
</div>
|
||
<!-- Footer -->
|
||
<div class="modal-footer">
|
||
<button data-modal-close="delete-api-modal" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button class="modal-btn modal-btn-danger">删除</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Delete Group Confirmation Modal -->
|
||
<div id="delete-group-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel">
|
||
<!-- Header -->
|
||
<div class="modal-header">
|
||
<h2 id="delete-group-modal-title" class="modal-title">确认删除分组</h2>
|
||
<button data-modal-close="delete-group-modal" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
<!-- Body -->
|
||
<div class="modal-body space-y-4">
|
||
<p class="text-sm text-zinc-600 dark:text-zinc-400">
|
||
这是一个危险且不可逆的操作。请仔细阅读以下警告:
|
||
</p>
|
||
<ul class="list-disc list-inside space-y-2 text-sm bg-yellow-100 dark:bg-yellow-900/30 p-3 rounded-lg border border-yellow-300 dark:border-yellow-700">
|
||
<li>此操作将解除所有 API Key 与该分组的关联。</li>
|
||
<li class="font-semibold">未与其他分组关联的 Key 将被 <strong class="text-red-500">彻底从数据库中删除</strong>。</li>
|
||
<li>该操作无法撤销。</li>
|
||
</ul>
|
||
<div>
|
||
<label for="delete-group-confirm-input" class="text-sm font-medium text-zinc-700 dark:text-zinc-300">
|
||
请输入 <code class="text-red-500 bg-zinc-200 dark:bg-zinc-700 px-1 py-0.5 rounded">删除</code> 来确认操作:
|
||
</label>
|
||
<input type="text" id="delete-group-confirm-input" class="modal-input mt-1 font-mono" autocomplete="off">
|
||
</div>
|
||
</div>
|
||
<!-- Footer -->
|
||
<div class="modal-footer">
|
||
<button data-modal-close="delete-group-modal" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button id="delete-group-confirm-btn" class="modal-btn modal-btn-danger" disabled>确认删除</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Clone Group Confirmation Modal -->
|
||
<div id="clone-group-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel">
|
||
<!-- Header -->
|
||
<div class="modal-header">
|
||
<h2 id="clone-group-modal-title" class="modal-title">确认克隆分组</h2>
|
||
<button data-modal-close="clone-group-modal" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
<!-- Body -->
|
||
<div class="modal-body space-y-4">
|
||
<p class="text-sm text-zinc-600 dark:text-zinc-400">
|
||
此操作将创建一个当前分组的完整副本,包括:
|
||
</p>
|
||
<ul class="list-disc list-inside space-y-2 text-sm bg-blue-100 dark:bg-blue-900/30 p-3 rounded-lg border border-blue-300 dark:border-blue-700">
|
||
<li>所有相同的 API Key 关联关系。</li>
|
||
<li>所有允许的模型和上游设置。</li>
|
||
<li>所有请求配置和运营设置。</li>
|
||
</ul>
|
||
<p class="text-sm text-zinc-600 dark:text-zinc-400">
|
||
新分组的名称将被自动命名为 <code class="bg-zinc-200 dark:bg-zinc-700 px-1 py-0.5 rounded">[原名称]-clone-[时间戳]</code>,您可以在之后对其进行编辑。
|
||
</p>
|
||
</div>
|
||
<!-- Footer -->
|
||
<div class="modal-footer">
|
||
<button data-modal-close="clone-group-modal" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button id="clone-group-confirm-btn" class="modal-btn modal-btn-primary">确认克隆</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========================================================================== -->
|
||
<!-- NEW: Advanced Request Settings Modal -->
|
||
<!-- ========================================================================== -->
|
||
<div id="request-settings-modal" class="modal-overlay hidden">
|
||
<div class="modal-panel max-w-3xl max-h-[90vh]">
|
||
<!-- Header -->
|
||
<div class="modal-header shrink-0">
|
||
<h2 class="modal-title">高级请求设置</h2>
|
||
<button data-modal-close="request-settings-modal" class="modal-close-btn">
|
||
<i class="fas fa-times text-lg"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Form Body -->
|
||
<div class="modal-body flex-grow overflow-y-auto pr-4 -mr-4 space-y-8"> <!-- 增加了 space-y-8 来拉开分区距离 -->
|
||
|
||
<!-- 1. Custom Headers -->
|
||
<div>
|
||
<label class="flex items-center modal-label text-lg font-semibold">
|
||
<i class="fas fa-file-alt w-6 text-center text-zinc-400 mr-2"></i> <!-- ICON -->
|
||
<span>自定义请求头 (Custom Headers)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="在这里添加的键值对将被添加到所有出站API请求的Header中。"></i>
|
||
</label>
|
||
<div id="CUSTOM_HEADERS_container" class="mt-2 space-y-2">
|
||
<!-- JS will populate this -->
|
||
</div>
|
||
<button id="addCustomHeaderBtn" type="button" class="mt-2 text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 font-medium">
|
||
<i class="fas fa-plus mr-1"></i> 添加 Header
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 2. Streaming Optimization (折叠优化) -->
|
||
<div class="border-t dark:border-zinc-700 pt-6"> <!-- 分隔线 -->
|
||
<div class="flex items-center justify-between">
|
||
<label class="flex items-center modal-label text-lg font-semibold">
|
||
<i class="fas fa-stream w-6 text-center text-zinc-400 mr-2"></i> <!-- ICON -->
|
||
<span>流式输出优化</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="启用后,可对流式输出进行延迟、分块等优化,改善用户体验。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="STREAM_OPTIMIZER_ENABLED" id="STREAM_OPTIMIZER_ENABLED" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="STREAM_OPTIMIZER_ENABLED" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
<!-- [折叠容器] 这个容器将由JS控制显示/隐藏 -->
|
||
<div id="streaming-settings-panel" class="hidden mt-4">
|
||
<div class="grid grid-cols-2 gap-x-6 gap-y-4">
|
||
<div>
|
||
<label for="STREAM_MIN_DELAY" class="flex items-center modal-label"><span>最小延迟 (ms)</span></label>
|
||
<input type="number" id="STREAM_MIN_DELAY" class="modal-input" placeholder="例如: 16">
|
||
</div>
|
||
<div>
|
||
<label for="STREAM_MAX_DELAY" class="flex items-center modal-label"><span>最大延迟 (ms)</span></label>
|
||
<input type="number" id="STREAM_MAX_DELAY" class="modal-input" placeholder="例如: 24">
|
||
</div>
|
||
<div>
|
||
<label for="STREAM_SHORT_TEXT_THRESHOLD" class="flex items-center modal-label"><span>短文本阈值</span></label>
|
||
<input type="number" id="STREAM_SHORT_TEXT_THRESHOLD" class="modal-input" placeholder="例如: 10">
|
||
</div>
|
||
<div>
|
||
<label for="STREAM_LONG_TEXT_THRESHOLD" class="flex items-center modal-label"><span>长文本阈值</span></label>
|
||
<input type="number" id="STREAM_LONG_TEXT_THRESHOLD" class="modal-input" placeholder="例如: 50">
|
||
</div>
|
||
<div class="col-span-2">
|
||
<label for="STREAM_CHUNK_SIZE" class="flex items-center modal-label"><span>分块大小</span></label>
|
||
<input type="number" id="STREAM_CHUNK_SIZE" class="modal-input" placeholder="例如: 5">
|
||
</div>
|
||
</div>
|
||
<!-- [假流式输出同行] -->
|
||
<div class="border-t dark:border-zinc-700 pt-4 mt-4 flex items-center justify-between gap-x-6">
|
||
<div class="flex items-center flex-grow translate-y-3">
|
||
<label for="FAKE_STREAM_ENABLED" class="modal-label flex items-center">
|
||
<span>启用假流式输出</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="当启用时,将调用非流式接口,并在等待响应期间发送空数据以维持连接。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 ml-auto mr-2 align-middle select-none">
|
||
<input type="checkbox" name="FAKE_STREAM_ENABLED" id="FAKE_STREAM_ENABLED" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="FAKE_STREAM_ENABLED" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
<div class="flex-grow">
|
||
<label for="FAKE_STREAM_EMPTY_DATA_INTERVAL_SECONDS" class="flex items-center modal-label"><span>发送间隔 (s)</span></label>
|
||
<input type="number" id="FAKE_STREAM_EMPTY_DATA_INTERVAL_SECONDS" class="modal-input" placeholder="例如: 5">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3. Safety Settings -->
|
||
<div class="border-t dark:border-zinc-700 pt-6"> <!-- 分隔线 -->
|
||
<label class="flex items-center modal-label text-lg font-semibold">
|
||
<i class="fas fa-shield-alt w-6 text-center text-zinc-400 mr-2"></i> <!-- ICON -->
|
||
<span>安全设置 (Safety Settings)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="配置模型的安全过滤级别,例如 HARM_CATEGORY_HARASSMENT: BLOCK_NONE。"></i>
|
||
</label>
|
||
<div id="SAFETY_SETTINGS_container" class="mt-2 space-y-2">
|
||
<!-- JS will populate this -->
|
||
</div>
|
||
<button id="addSafetySettingBtn" type="button" class="mt-2 text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 font-medium">
|
||
<i class="fas fa-plus mr-1"></i> 添加安全设置
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 4. Advanced Model Settings (保持折叠) -->
|
||
<div class="border-t dark:border-zinc-700 pt-6"> <!-- 分隔线 -->
|
||
<details>
|
||
<summary class="cursor-pointer text-lg font-semibold text-zinc-700 dark:text-zinc-300 flex items-center">
|
||
<i class="fas fa-cogs w-6 text-center text-zinc-400 mr-2"></i> <!-- ICON -->
|
||
<span>高级模型设置</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="配置模型的高级设置,自定义图像模型/搜索模型/思考设置等,非熟知不建议修改。"></i>
|
||
<i class="fas fa-chevron-down text-sm ml-auto transition-transform"></i>
|
||
</summary>
|
||
<div class="mt-4 space-y-6">
|
||
<!-- Image Models -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>图像模型 (Image Models)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="支持图像处理的模型列表。"></i>
|
||
</label>
|
||
<div id="IMAGE_MODELS_container" class="tag-input-container">
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
<!-- Search Models -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>搜索模型 (Search Models)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="支持搜索功能的模型列表。"></i>
|
||
</label>
|
||
<div id="SEARCH_MODELS_container" class="tag-input-container">
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
<!-- Filtered Models -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>过滤模型 (Filtered Models)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="需要从模型列表中排除的模型。"></i>
|
||
</label>
|
||
<div id="FILTERED_MODELS_container" class="tag-input-container">
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Enable Code Execution -->
|
||
<div class="flex items-center">
|
||
<label for="TOOLS_CODE_EXECUTION_ENABLED" class="modal-label flex-grow flex items-center">
|
||
<span>启用代码执行工具</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="是否为模型启用代码执行工具。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="TOOLS_CODE_EXECUTION_ENABLED" id="TOOLS_CODE_EXECUTION_ENABLED" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="TOOLS_CODE_EXECUTION_ENABLED" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Enable URL Context -->
|
||
<div class="flex items-center">
|
||
<label for="URL_CONTEXT_ENABLED" class="modal-label flex-grow flex items-center">
|
||
<span>启用网址上下文</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="是否启用网址上下文功能。"></i>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="URL_CONTEXT_ENABLED" id="URL_CONTEXT_ENABLED" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="URL_CONTEXT_ENABLED" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- URL Context Models -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>网址上下文模型</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="支持网址上下文功能的模型列表。"></i>
|
||
</label>
|
||
<div id="URL_CONTEXT_MODELS_container" class="tag-input-container">
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Show Search Link -->
|
||
<div class="flex items-center">
|
||
<label for="SHOW_SEARCH_LINK" class="modal-label flex-grow flex items-center">
|
||
<span>显示搜索链接</span>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="SHOW_SEARCH_LINK" id="SHOW_SEARCH_LINK" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="SHOW_SEARCH_LINK" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Show Thinking Process -->
|
||
<div class="flex items-center">
|
||
<label for="SHOW_THINKING_PROCESS" class="modal-label flex-grow flex items-center">
|
||
<span>显示思考过程</span>
|
||
</label>
|
||
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
||
<input type="checkbox" name="SHOW_THINKING_PROCESS" id="SHOW_THINKING_PROCESS" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
|
||
<label for="SHOW_THINKING_PROCESS" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Thinking Models -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>思考模型 (Thinking Models)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="用于“思考过程”的模型列表。"></i>
|
||
</label>
|
||
<div id="THINKING_MODELS_container" class="tag-input-container">
|
||
<input type="text" placeholder="添加模型..." class="tag-input-new">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Thinking Budget Map -->
|
||
<div>
|
||
<label class="flex items-center modal-label">
|
||
<span>思考模型预算映射</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="为每个思考模型设置预算(-1为auto),此项与上方模型列表自动关联。"></i>
|
||
</label>
|
||
<div id="THINKING_BUDGET_MAP_container" class="mt-2 space-y-2">
|
||
<!-- JS will populate this -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<!-- 5. Config Overrides (折叠优化) -->
|
||
<div class="border-t dark:border-zinc-700 pt-6"> <!-- 分隔线 -->
|
||
<details>
|
||
<summary class="cursor-pointer text-lg font-semibold text-zinc-700 dark:text-zinc-300 flex items-center">
|
||
<i class="fas fa-code w-6 text-center text-zinc-400 mr-2"></i> <!-- ICON -->
|
||
<span>覆盖参数 (JSON)</span>
|
||
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="使用JSON格式覆盖默认的请求参数。"></i>
|
||
<i class="fas fa-chevron-down text-sm ml-auto transition-transform"></i>
|
||
</summary>
|
||
<!-- [修复] 将 placeholder 内容放在一行,避免被截断 -->
|
||
<textarea id="group-config-overrides" rows="6" class="mt-2 modal-input font-mono text-xs" placeholder='{
|
||
"temperature": 0.8
|
||
}'></textarea>
|
||
</details>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div class="modal-footer shrink-0">
|
||
<button data-modal-close="request-settings-modal" class="modal-btn modal-btn-secondary">取消</button>
|
||
<button id="request-settings-save-btn" class="modal-btn modal-btn-primary">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{% endblock modals %}
|
||
|
||
{% block page_scripts %}
|
||
{% endblock page_scripts %} |