Compare commits

...

11 Commits

8 changed files with 3153 additions and 1503 deletions

View File

@@ -27,6 +27,8 @@ jobs:
- name: Build all-in-one HTML
run: npm run build
env:
VERSION: ${{ github.ref_name }}
- name: Prepare release assets
run: |

View File

@@ -10,7 +10,7 @@ Example URL:
https://remote.router-for.me/
Minimum required version: ≥ 6.0.0
Recommended version: ≥ 6.0.19
Recommended version: ≥ 6.1.3
Since version 6.0.19, the WebUI has been rolled into the main program. You can access it by going to `/management.html` on the external port after firing up the main project.
@@ -43,7 +43,6 @@ Since version 6.0.19, the WebUI has been rolled into the main program. You can a
- Download existing authentication files
- Delete single or all authentication files
- Display file details
- **Gemini Web Token**: Direct authentication using browser cookies
### Usage Statistics
- **Real-time Analytics**: Track API usage with interactive charts

View File

@@ -8,7 +8,9 @@ https://github.com/router-for-me/CLIProxyAPI
https://remote.router-for.me/
最低可用版本 ≥ 6.0.0
推荐版本 ≥ 6.0.19
推荐版本 ≥ 6.1.3
自6.0.19起WebUI已经集成在主程序中 可以通过主项目开启的外部端口的`/management.html`访问
## 功能特点
@@ -40,7 +42,6 @@ https://remote.router-for.me/
- 下载现有认证文件
- 删除单个或所有认证文件
- 显示文件详细信息
- **Gemini Web Token**: 使用浏览器 Cookie 直接认证
### 使用统计
- **实时分析**: 通过交互式图表跟踪 API 使用情况

1397
app.js

File diff suppressed because it is too large Load Diff

View File

@@ -49,6 +49,35 @@ function escapeForStyle(content) {
return content.replace(/<\/(style)/gi, '<\\/$1');
}
function getVersion() {
// 1. 优先从环境变量获取GitHub Actions 会设置)
if (process.env.VERSION) {
return process.env.VERSION;
}
// 2. 尝试从 git tag 获取
try {
const { execSync } = require('child_process');
const gitTag = execSync('git describe --tags --exact-match 2>/dev/null || git describe --tags 2>/dev/null || echo ""', { encoding: 'utf8' }).trim();
if (gitTag) {
return gitTag;
}
} catch (err) {
console.warn('无法从 git 获取版本号');
}
// 3. 回退到 package.json
try {
const packageJson = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
return 'v' + packageJson.version;
} catch (err) {
console.warn('无法从 package.json 读取版本号');
}
// 4. 最后使用默认值
return 'v0.0.0-dev';
}
function ensureDistDir() {
if (fs.existsSync(distDir)) {
fs.rmSync(distDir, { recursive: true, force: true });
@@ -82,6 +111,11 @@ function build() {
const css = escapeForStyle(readFile(sourceFiles.css));
const i18n = escapeForScript(readFile(sourceFiles.i18n));
const app = escapeForScript(readFile(sourceFiles.app));
// 获取版本号并替换
const version = getVersion();
console.log(`使用版本号: ${version}`);
html = html.replace(/__VERSION__/g, version);
html = html.replace(
'<link rel="stylesheet" href="styles.css">',

1512
i18n.js

File diff suppressed because it is too large Load Diff

1047
index.html

File diff suppressed because it is too large Load Diff

View File

@@ -9,30 +9,30 @@
:root {
/* 布局尺寸 */
--navbar-height: 69px;
/* 亮色主题(默认) */
--bg-primary: #f5f7fa;
--bg-secondary: #ffffff;
--bg-tertiary: #f8f9fb;
--bg-quaternary: #f7fafc;
--bg-modal: rgba(0, 0, 0, 0.5);
/* 侧边栏颜色 */
--sidebar-bg: #ffffff;
--sidebar-hover: #f0f2f5;
--sidebar-active: #e8f4ff;
--sidebar-border: #e5e7eb;
--text-primary: #1f2937;
--text-secondary: #4b5563;
--text-tertiary: #6b7280;
--text-quaternary: #9ca3af;
--text-inverse: white;
--border-primary: #e5e7eb;
--border-secondary: #d1d5db;
--border-focus: #3b82f6;
--accent-primary: #3b82f6;
--accent-secondary: #e5e7eb;
--accent-tertiary: #f3f4f6;
@@ -40,25 +40,25 @@
--primary-hover: #2563eb;
--card-bg: #ffffff;
--border-color: #e5e7eb;
--success-bg: #d1fae5;
--success-text: #065f46;
--success-border: #6ee7b7;
--error-bg: #fee2e2;
--error-text: #991b1b;
--error-border: #fca5a5;
--warning-bg: #fef3c7;
--warning-text: #92400e;
--warning-border: #fbbf24;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-primary: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 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-secondary: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-modal: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--glass-bg: rgba(255, 255, 255, 0.95);
--glass-border: rgba(229, 231, 235, 0.8);
}
@@ -70,23 +70,23 @@
--bg-tertiary: #1a202c;
--bg-quaternary: #2d3748;
--bg-modal: rgba(0, 0, 0, 0.7);
/* 侧边栏颜色 */
--sidebar-bg: #1f2937;
--sidebar-hover: #374151;
--sidebar-active: #1e3a5f;
--sidebar-border: #374151;
--text-primary: #f9fafb;
--text-secondary: #e5e7eb;
--text-tertiary: #d1d5db;
--text-quaternary: #9ca3af;
--text-inverse: #ffffff;
--border-primary: #374151;
--border-secondary: #4b5563;
--border-focus: #60a5fa;
--accent-primary: #3b82f6;
--accent-secondary: #374151;
--accent-tertiary: #1f2937;
@@ -94,25 +94,25 @@
--primary-hover: #3b82f6;
--card-bg: #1f2937;
--border-color: #374151;
--success-bg: #064e3b;
--success-text: #6ee7b7;
--success-border: #059669;
--error-bg: #7f1d1d;
--error-text: #fca5a5;
--error-border: #dc2626;
--warning-bg: #78350f;
--warning-text: #fbbf24;
--warning-border: #f59e0b;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-primary: 0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
--shadow-secondary: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
--shadow-modal: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.3);
--glass-bg: rgba(31, 41, 59, 0.95);
--glass-border: rgba(75, 85, 99, 0.8);
}
@@ -149,8 +149,13 @@
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.auto-login-content h2 {
@@ -198,7 +203,8 @@
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
margin-top: 8px; /* 与标题拉开距离,避免遮挡 */
margin-top: 8px;
/* 与标题拉开距离,避免遮挡 */
margin-bottom: 20px;
}
@@ -537,29 +543,31 @@
margin: 10px;
max-width: 100%;
}
.login-header-top {
flex-direction: column;
gap: 20px;
align-items: center;
margin-bottom: 30px;
}
.header-controls {
flex-direction: row;
justify-content: center;
gap: 8px;
margin-bottom: 10px; /* 在小屏幕上给控制按钮组添加下边距 */
margin-bottom: 10px;
/* 在小屏幕上给控制按钮组添加下边距 */
}
/* 登录页面小屏幕优化 */
.login-header-top .header-controls {
margin: 8px auto 0 auto; /* 顶部留白,避免与标题拥挤 */
margin: 8px auto 0 auto;
/* 顶部留白,避免与标题拥挤 */
background: rgba(255, 255, 255, 0.08);
padding: 6px;
border-radius: 10px;
}
.login-header-top .language-btn,
.login-header-top .theme-btn {
padding: 6px 10px;
@@ -567,14 +575,15 @@
height: 32px;
min-width: 32px;
}
.language-btn,
.theme-btn {
padding: 8px 16px;
font-size: 13px;
height: 36px; /* 在小屏幕上稍微减小高度 */
height: 36px;
/* 在小屏幕上稍微减小高度 */
}
.login-title {
font-size: 1.5rem;
flex-direction: column;
@@ -583,16 +592,16 @@
justify-content: center;
margin-bottom: 25px;
}
#login-logo {
height: 50px;
}
.login-form .input-group {
flex-direction: column;
align-items: stretch;
}
.login-form .btn-secondary {
width: 100%;
margin-top: 10px;
@@ -851,7 +860,7 @@ body {
margin-left: auto;
}
.top-navbar-actions > * {
.top-navbar-actions>* {
display: inline-flex;
align-items: center;
height: 36px;
@@ -892,7 +901,7 @@ body {
gap: 8px;
}
.top-navbar-actions > * {
.top-navbar-actions>* {
height: 34px;
min-height: 34px;
}
@@ -933,7 +942,7 @@ body {
.header-actions .btn span {
display: none;
}
.header-actions .btn {
padding: 6px 10px;
}
@@ -1017,7 +1026,7 @@ body {
align-items: flex-start;
gap: 8px;
}
.info-value {
max-width: 100%;
width: 100%;
@@ -1049,6 +1058,7 @@ body {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
@@ -1293,11 +1303,11 @@ textarea::placeholder {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
input:checked + .slider {
input:checked+.slider {
background: var(--primary-color);
}
input:checked + .slider:before {
input:checked+.slider:before {
transform: translateX(20px);
}
@@ -1457,6 +1467,7 @@ input:checked + .slider:before {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
@@ -1612,34 +1623,34 @@ input:checked + .slider:before {
transform: translateX(0);
box-shadow: var(--shadow-secondary);
}
/* 移动端强制恢复侧栏展开状态 */
.sidebar.collapsed {
width: 240px !important;
}
.sidebar.collapsed .nav-item span {
opacity: 1 !important;
width: auto !important;
overflow: visible !important;
}
.sidebar.collapsed .nav-item {
justify-content: flex-start !important;
padding: 10px 14px !important;
}
.sidebar.collapsed .nav-item i {
margin-right: 12px !important;
}
.main-wrapper {
margin-left: 0;
width: 100%;
min-height: calc(100vh - var(--navbar-height, 69px));
overflow: hidden;
}
.main-content {
padding: 20px 16px;
}
@@ -1649,18 +1660,18 @@ input:checked + .slider:before {
.top-navbar {
padding: 12px 16px;
}
.top-navbar-title {
font-size: 18px;
}
.top-navbar-actions {
gap: 6px;
flex-wrap: wrap;
justify-content: flex-end;
}
.top-navbar-actions > * {
.top-navbar-actions>* {
height: 34px;
min-height: 34px;
}
@@ -1681,66 +1692,66 @@ input:checked + .slider:before {
.top-navbar-actions .btn span {
display: none;
}
.btn {
padding: 6px 12px;
font-size: 13px;
}
.card {
border-radius: 8px;
}
.card-header {
padding: 16px 20px;
}
.card-content {
padding: 20px;
}
.input-group {
flex-direction: column;
align-items: stretch;
}
.card-header {
flex-direction: column;
gap: 12px;
align-items: flex-start;
}
.card-header .header-actions {
width: 100%;
justify-content: flex-start;
}
/* 模态框响应式 */
.modal-content {
margin: 5% auto;
width: 95%;
max-width: none;
}
#modal-body {
padding: 40px 20px 20px 20px;
}
#modal-body h3 {
font-size: 18px;
margin-bottom: 16px;
}
#modal-body .modal-actions {
flex-direction: column-reverse;
gap: 10px;
}
#modal-body .modal-actions .btn {
width: 100%;
margin: 0;
}
.content-section h2 {
font-size: 20px;
margin-bottom: 20px;
@@ -1803,7 +1814,9 @@ input:checked + .slider:before {
}
@keyframes spin {
to { transform: rotate(360deg); }
to {
transform: rotate(360deg);
}
}
/* 空状态 */
@@ -1899,53 +1912,17 @@ input:checked + .slider:before {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
/* Gemini Web Token 模态框样式 */
.gemini-web-form .form-group {
margin-bottom: 20px;
}
.gemini-web-form .form-group label {
display: block;
margin-bottom: 8px;
color: var(--text-secondary);
font-weight: 600;
font-size: 14px;
}
.gemini-web-form .form-group input {
width: 100%;
padding: 12px 16px;
border: 2px solid var(--border-primary);
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
background: var(--bg-tertiary);
color: var(--text-primary);
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}
.gemini-web-form .form-group input:focus {
outline: none;
border-color: var(--border-focus);
box-shadow: 0 0 0 3px var(--border-primary);
}
.gemini-web-form .form-hint {
margin-top: 6px;
color: var(--text-tertiary);
font-size: 12px;
line-height: 1.4;
}
/* 使用统计样式 */
.stats-overview {
display: grid;
@@ -2211,3 +2188,480 @@ input:checked + .slider:before {
align-self: center;
}
/* Codex OAuth 样式 */
#codex-oauth-content {
transition: all 0.3s ease;
}
#codex-oauth-url {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#codex-oauth-url:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
#codex-oauth-status {
font-weight: 500;
padding: 8px 12px;
border-radius: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
transition: all 0.3s ease;
}
#codex-oauth-status.success {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success-text);
}
#codex-oauth-status.error {
background: var(--error-bg);
border-color: var(--error-border);
color: var(--error-text);
}
#codex-oauth-status.warning {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning-text);
}
/* Codex OAuth 按钮样式 */
#codex-open-link,
#codex-copy-link {
min-width: 100px;
white-space: nowrap;
}
#codex-open-link {
background: var(--primary-color);
border-color: var(--primary-color);
}
#codex-open-link:hover {
background: var(--primary-hover);
border-color: var(--primary-hover);
}
#codex-copy-link {
background: var(--bg-secondary);
border-color: var(--border-primary);
color: var(--text-secondary);
}
#codex-copy-link:hover {
background: var(--bg-tertiary);
border-color: var(--border-secondary);
color: var(--text-primary);
}
/* 响应式设计 - Codex OAuth */
@media (max-width: 768px) {
#codex-oauth-content .input-group {
flex-direction: column;
align-items: stretch;
}
#codex-open-link,
#codex-copy-link {
width: 100%;
margin-top: 8px;
}
#codex-oauth-url {
font-size: 12px;
}
}
/* Anthropic OAuth 样式 */
#anthropic-oauth-content {
transition: all 0.3s ease;
}
#anthropic-oauth-url {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#anthropic-oauth-url:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
#anthropic-oauth-status {
font-weight: 500;
padding: 8px 12px;
border-radius: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
transition: all 0.3s ease;
}
#anthropic-oauth-status.success {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success-text);
}
#anthropic-oauth-status.error {
background: var(--error-bg);
border-color: var(--error-border);
color: var(--error-text);
}
#anthropic-oauth-status.warning {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning-text);
}
/* Anthropic OAuth 按钮样式 */
#anthropic-open-link,
#anthropic-copy-link {
min-width: 100px;
white-space: nowrap;
}
#anthropic-open-link {
background: var(--primary-color);
border-color: var(--primary-color);
}
#anthropic-open-link:hover {
background: var(--primary-hover);
border-color: var(--primary-hover);
}
#anthropic-copy-link {
background: var(--bg-secondary);
border-color: var(--border-primary);
color: var(--text-secondary);
}
#anthropic-copy-link:hover {
background: var(--bg-tertiary);
border-color: var(--border-secondary);
color: var(--text-primary);
}
/* 响应式设计 - Anthropic OAuth */
@media (max-width: 768px) {
#anthropic-oauth-content .input-group {
flex-direction: column;
align-items: stretch;
}
#anthropic-open-link,
#anthropic-copy-link {
width: 100%;
margin-top: 8px;
}
#anthropic-oauth-url {
font-size: 12px;
}
}
/* Gemini CLI OAuth 样式 */
#gemini-cli-oauth-content {
transition: all 0.3s ease;
}
#gemini-cli-oauth-url {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#gemini-cli-oauth-url:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
#gemini-cli-oauth-status {
font-weight: 500;
padding: 8px 12px;
border-radius: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
transition: all 0.3s ease;
}
#gemini-cli-oauth-status.success {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success-text);
}
#gemini-cli-oauth-status.error {
background: var(--error-bg);
border-color: var(--error-border);
color: var(--error-text);
}
#gemini-cli-oauth-status.warning {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning-text);
}
/* Gemini CLI OAuth 按钮样式 */
#gemini-cli-open-link,
#gemini-cli-copy-link {
min-width: 100px;
white-space: nowrap;
}
#gemini-cli-open-link {
background: var(--primary-color);
border-color: var(--primary-color);
}
#gemini-cli-open-link:hover {
background: var(--primary-hover);
border-color: var(--primary-hover);
}
#gemini-cli-copy-link {
background: var(--bg-secondary);
border-color: var(--border-primary);
color: var(--text-secondary);
}
#gemini-cli-copy-link:hover {
background: var(--bg-tertiary);
border-color: var(--border-secondary);
color: var(--text-primary);
}
/* Gemini CLI 项目 ID 输入框样式 */
#gemini-cli-project-id {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#gemini-cli-project-id:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
/* 响应式设计 - Gemini CLI OAuth */
@media (max-width: 768px) {
#gemini-cli-oauth-content .input-group {
flex-direction: column;
align-items: stretch;
}
#gemini-cli-open-link,
#gemini-cli-copy-link {
width: 100%;
margin-top: 8px;
}
#gemini-cli-oauth-url {
font-size: 12px;
}
#gemini-cli-project-id {
font-size: 12px;
}
}
/* Qwen OAuth 样式 */
#qwen-oauth-content {
transition: all 0.3s ease;
}
#qwen-oauth-url {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#qwen-oauth-url:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
#qwen-oauth-status {
font-weight: 500;
padding: 8px 12px;
border-radius: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
transition: all 0.3s ease;
}
#qwen-oauth-status.success {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success-text);
}
#qwen-oauth-status.error {
background: var(--error-bg);
border-color: var(--error-border);
color: var(--error-text);
}
#qwen-oauth-status.warning {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning-text);
}
/* Qwen OAuth 按钮样式 */
#qwen-open-link,
#qwen-copy-link {
min-width: 100px;
white-space: nowrap;
}
#qwen-open-link {
background: var(--primary-color);
border-color: var(--primary-color);
}
#qwen-open-link:hover {
background: var(--primary-hover);
border-color: var(--primary-hover);
}
#qwen-copy-link {
background: var(--bg-secondary);
border-color: var(--border-primary);
color: var(--text-secondary);
}
#qwen-copy-link:hover {
background: var(--bg-tertiary);
border-color: var(--border-secondary);
color: var(--text-primary);
}
/* 响应式设计 - Qwen OAuth */
@media (max-width: 768px) {
#qwen-oauth-content .input-group {
flex-direction: column;
align-items: stretch;
}
#qwen-open-link,
#qwen-copy-link {
width: 100%;
margin-top: 8px;
}
#qwen-oauth-url {
font-size: 12px;
}
}
/* iFlow OAuth 样式 */
#iflow-oauth-content {
transition: all 0.3s ease;
}
#iflow-oauth-url {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
#iflow-oauth-url:focus {
border-color: var(--border-focus);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
#iflow-oauth-status {
font-weight: 500;
padding: 8px 12px;
border-radius: 6px;
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
transition: all 0.3s ease;
}
#iflow-oauth-status.success {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success-text);
}
#iflow-oauth-status.error {
background: var(--error-bg);
border-color: var(--error-border);
color: var(--error-text);
}
#iflow-oauth-status.warning {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning-text);
}
/* iFlow OAuth 按钮样式 */
#iflow-open-link,
#iflow-copy-link {
min-width: 100px;
white-space: nowrap;
}
#iflow-open-link {
background: var(--primary-color);
border-color: var(--primary-color);
}
#iflow-open-link:hover {
background: var(--primary-hover);
border-color: var(--primary-hover);
}
#iflow-copy-link {
background: var(--bg-secondary);
border-color: var(--border-primary);
color: var(--text-secondary);
}
#iflow-copy-link:hover {
background: var(--bg-tertiary);
border-color: var(--border-secondary);
color: var(--text-primary);
}
/* 响应式设计 - iFlow OAuth */
@media (max-width: 768px) {
#iflow-oauth-content .input-group {
flex-direction: column;
align-items: stretch;
}
#iflow-open-link,
#iflow-copy-link {
width: 100%;
margin-top: 8px;
}
#iflow-oauth-url {
font-size: 12px;
}
}