diff --git a/.dockerignore b/.dockerignore index 252b0ab5..f10a08c1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -55,12 +55,15 @@ coverage/ .nyc_output/ # Build files -dist/ +# dist/ # 前端构建阶段需要复制源文件,所以不能忽略 build/ *.pid *.seed *.pid.lock +# 但可以忽略本地已构建的 dist 目录 +web/admin-spa/dist/ + # CI/CD .travis.yml .gitlab-ci.yml diff --git a/.github/workflows/auto-release-pipeline.yml b/.github/workflows/auto-release-pipeline.yml index a4abbb26..12a59522 100644 --- a/.github/workflows/auto-release-pipeline.yml +++ b/.github/workflows/auto-release-pipeline.yml @@ -103,52 +103,7 @@ jobs: echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT echo "new_tag=v$NEW_VERSION" >> $GITHUB_OUTPUT - - name: Check if frontend build is needed - id: check_frontend - if: steps.check.outputs.needs_bump == 'true' - run: | - # 检查 web/admin-spa 目录是否有变更 - FRONTEND_CHANGES=false - CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only $(git rev-list --max-parents=0 HEAD)..HEAD) - - while IFS= read -r file; do - if [[ "$file" =~ ^web/admin-spa/ ]] && - [[ ! "$file" =~ ^web/admin-spa/dist/ ]] && - [[ ! "$file" =~ \.(md|txt)$ ]] && - [[ "$file" != "web/admin-spa/.gitignore" ]]; then - echo "Found frontend change in: $file" - FRONTEND_CHANGES=true - break - fi - done <<< "$CHANGED_FILES" - - echo "needs_build=$FRONTEND_CHANGES" >> $GITHUB_OUTPUT - - - name: Setup Node.js - if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true' - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: web/admin-spa/package-lock.json - - - name: Build admin-spa - if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true' - run: | - echo "Building admin-spa frontend..." - cd web/admin-spa - npm ci - npm run build - cd ../.. - - # 确认 dist 目录已创建 - if [ -d "web/admin-spa/dist" ]; then - echo "✅ Frontend build successful" - ls -la web/admin-spa/dist/ - else - echo "❌ Frontend build failed - dist directory not found" - exit 1 - fi + # 前端构建已移至 Docker 构建流程中 - name: Update VERSION file if: steps.check.outputs.needs_bump == 'true' @@ -159,19 +114,9 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - # 检查是否需要添加 dist 目录 - if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ] && [ -d "web/admin-spa/dist" ]; then - git add -f web/admin-spa/dist/ - echo "Added frontend dist directory to commit" - fi - - # 提交VERSION文件和可能的dist目录 - 添加 [skip ci] 以避免再次触发 + # 提交VERSION文件 - 添加 [skip ci] 以避免再次触发 git add VERSION - if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ]; then - git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} and rebuild frontend [skip ci]" - else - git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]" - fi + git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]" - name: Install git-cliff if: steps.check.outputs.needs_bump == 'true' diff --git a/Dockerfile b/Dockerfile index 339da465..c6306ca3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,22 @@ -# 🐳 使用官方 Node.js 18 Alpine 镜像 +# 🎯 前端构建阶段 +FROM node:18-alpine AS frontend-builder + +# 📁 设置工作目录 +WORKDIR /app/web/admin-spa + +# 📦 复制前端依赖文件 +COPY web/admin-spa/package*.json ./ + +# 🔽 安装前端依赖 +RUN npm ci + +# 📋 复制前端源代码 +COPY web/admin-spa/ ./ + +# 🏗️ 构建前端 +RUN npm run build + +# 🐳 主应用阶段 FROM node:18-alpine # 📋 设置标签 @@ -26,6 +44,9 @@ RUN npm ci --only=production && \ # 📋 复制应用代码 COPY . . +# 📦 从构建阶段复制前端产物 +COPY --from=frontend-builder /app/web/admin-spa/dist /app/web/admin-spa/dist + # 🔧 复制并设置启动脚本权限 COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh diff --git a/README.md b/README.md index ce7d7126..a376441a 100644 --- a/README.md +++ b/README.md @@ -269,7 +269,17 @@ module.exports = { } ``` -### 第四步:启动服务 +### 第四步:安装前端依赖并构建 + +```bash +# 安装前端依赖 +npm run install:web + +# 构建前端(生成 dist 目录) +npm run build:web +``` + +### 第五步:启动服务 ```bash # 初始化 @@ -526,10 +536,14 @@ git add package-lock.json # 3. 安装新的依赖(如果有) npm install -# 4. 重启服务 +# 4. 安装并构建前端 +npm run install:web +npm run build:web + +# 5. 重启服务 npm run service:restart:daemon -# 5. 检查服务状态 +# 6. 检查服务状态 npm run service:status ``` diff --git a/VERSION b/VERSION index c3e7007a..470abefa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.64 +1.1.67 diff --git a/scripts/manage.sh b/scripts/manage.sh index e0000a40..5a526887 100644 --- a/scripts/manage.sh +++ b/scripts/manage.sh @@ -458,6 +458,10 @@ EOF print_info "安装Web界面依赖..." npm run install:web + # 构建前端 + print_info "构建前端界面..." + npm run build:web + # 创建systemd服务文件(Linux) if [[ "$OS" == "debian" || "$OS" == "redhat" || "$OS" == "arch" ]]; then create_systemd_service @@ -547,6 +551,10 @@ update_service() { npm install npm run install:web + # 构建前端 + print_info "构建前端界面..." + npm run build:web + # 启动服务 start_service @@ -938,7 +946,14 @@ handle_menu_choice() { create_symlink() { # 获取脚本的绝对路径 local script_path="" - if command_exists realpath; then + + # 优先使用项目中的 manage.sh(在 app/scripts 目录下) + if [ -n "$APP_DIR" ] && [ -f "$APP_DIR/scripts/manage.sh" ]; then + script_path="$APP_DIR/scripts/manage.sh" + elif [ -f "/app/scripts/manage.sh" ] && [ "$(basename "$0")" = "manage.sh" ]; then + # Docker 容器中的路径 + script_path="/app/scripts/manage.sh" + elif command_exists realpath; then script_path="$(realpath "$0")" elif command_exists readlink && readlink -f "$0" >/dev/null 2>&1; then script_path="$(readlink -f "$0")" @@ -950,11 +965,22 @@ create_symlink() { local symlink_path="/usr/bin/crs" print_info "创建命令行快捷方式..." + print_info "APP_DIR: $APP_DIR" print_info "脚本路径: $script_path" # 检查脚本文件是否存在 if [ ! -f "$script_path" ]; then print_error "找不到脚本文件: $script_path" + print_info "当前目录: $(pwd)" + print_info "脚本参数 \$0: $0" + if [ -n "$APP_DIR" ]; then + print_info "检查项目目录结构:" + ls -la "$APP_DIR/" 2>/dev/null | head -5 + if [ -d "$APP_DIR/scripts" ]; then + print_info "scripts 目录内容:" + ls -la "$APP_DIR/scripts/" 2>/dev/null | grep manage.sh + fi + fi return 1 fi @@ -1004,7 +1030,15 @@ load_config() { fi if [ -n "$INSTALL_DIR" ]; then - APP_DIR="$INSTALL_DIR/app" + # 检查是否使用了标准的安装结构(项目在 app 子目录) + if [ -d "$INSTALL_DIR/app" ] && [ -f "$INSTALL_DIR/app/package.json" ]; then + APP_DIR="$INSTALL_DIR/app" + # 检查是否直接克隆了项目(项目在根目录) + elif [ -f "$INSTALL_DIR/package.json" ]; then + APP_DIR="$INSTALL_DIR" + else + APP_DIR="$INSTALL_DIR/app" + fi # 加载.env配置 if [ -f "$APP_DIR/.env" ]; then @@ -1077,6 +1111,12 @@ main() { ;; symlink) # 单独创建软链接 + # 确保 APP_DIR 已设置 + if [ -z "$APP_DIR" ]; then + print_error "请先安装项目后再创建软链接" + print_info "运行: $0 install" + exit 1 + fi create_symlink ;; help) diff --git a/src/routes/admin.js b/src/routes/admin.js index c0cba6e4..31fcfba7 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -1327,19 +1327,20 @@ router.post('/gemini-accounts/generate-auth-url', authenticateAdmin, async (req, try { const { state } = req.body; - // 使用固定的 localhost:45462 作为回调地址 - const redirectUri = 'http://localhost:45462'; + // 使用新的 codeassist.google.com 回调地址 + const redirectUri = 'https://codeassist.google.com/authcode'; logger.info(`Generating Gemini OAuth URL with redirect_uri: ${redirectUri}`); - const { authUrl, state: authState } = await geminiAccountService.generateAuthUrl(state, redirectUri); + const { authUrl, state: authState, codeVerifier, redirectUri: finalRedirectUri } = await geminiAccountService.generateAuthUrl(state, redirectUri); - // 创建 OAuth 会话 + // 创建 OAuth 会话,包含 codeVerifier const sessionId = authState; await redis.setOAuthSession(sessionId, { state: authState, type: 'gemini', - redirectUri: redirectUri, // 保存固定的 redirect_uri 用于 token 交换 + redirectUri: finalRedirectUri, + codeVerifier: codeVerifier, // 保存 PKCE code verifier createdAt: new Date().toISOString() }); @@ -1389,11 +1390,20 @@ router.post('/gemini-accounts/exchange-code', authenticateAdmin, async (req, res return res.status(400).json({ error: 'Authorization code is required' }); } - // 使用固定的 localhost:45462 作为 redirect_uri - const redirectUri = 'http://localhost:45462'; - logger.info(`Using fixed redirect_uri: ${redirectUri}`); + let redirectUri = 'https://codeassist.google.com/authcode'; + let codeVerifier = null; - const tokens = await geminiAccountService.exchangeCodeForTokens(code, redirectUri); + // 如果提供了 sessionId,从 OAuth 会话中获取信息 + if (sessionId) { + const sessionData = await redis.getOAuthSession(sessionId); + if (sessionData) { + redirectUri = sessionData.redirectUri || redirectUri; + codeVerifier = sessionData.codeVerifier; + logger.info(`Using session redirect_uri: ${redirectUri}, has codeVerifier: ${!!codeVerifier}`); + } + } + + const tokens = await geminiAccountService.exchangeCodeForTokens(code, redirectUri, codeVerifier); // 清理 OAuth 会话 if (sessionId) { @@ -1731,7 +1741,7 @@ router.get('/model-stats', authenticateAdmin, async (req, res) => { searchPatterns = [pattern]; } - logger.info(`📊 Searching patterns:`, searchPatterns); + logger.info('📊 Searching patterns:', searchPatterns); // 获取所有匹配的keys const allKeys = []; diff --git a/src/services/geminiAccountService.js b/src/services/geminiAccountService.js index 7ffe286b..07b25f48 100644 --- a/src/services/geminiAccountService.js +++ b/src/services/geminiAccountService.js @@ -77,19 +77,31 @@ function createOAuth2Client(redirectUri = null) { ); } -// 生成授权 URL +// 生成授权 URL (支持 PKCE) async function generateAuthUrl(state = null, redirectUri = null) { - const oAuth2Client = createOAuth2Client(redirectUri); + // 使用新的 redirect URI + const finalRedirectUri = redirectUri || 'https://codeassist.google.com/authcode'; + const oAuth2Client = createOAuth2Client(finalRedirectUri); + + // 生成 PKCE code verifier + const codeVerifier = await oAuth2Client.generateCodeVerifierAsync(); + const stateValue = state || crypto.randomBytes(32).toString('hex'); + const authUrl = oAuth2Client.generateAuthUrl({ + redirect_uri: finalRedirectUri, access_type: 'offline', scope: OAUTH_SCOPES, - prompt: 'select_account', - state: state || uuidv4() + code_challenge_method: 'S256', + code_challenge: codeVerifier.codeChallenge, + state: stateValue, + prompt: 'select_account' }); return { authUrl, - state: state || authUrl.split('state=')[1].split('&')[0] + state: stateValue, + codeVerifier: codeVerifier.codeVerifier, + redirectUri: finalRedirectUri }; } @@ -145,12 +157,22 @@ async function pollAuthorizationStatus(sessionId, maxAttempts = 60, interval = 2 }; } -// 交换授权码获取 tokens -async function exchangeCodeForTokens(code, redirectUri = null) { +// 交换授权码获取 tokens (支持 PKCE) +async function exchangeCodeForTokens(code, redirectUri = null, codeVerifier = null) { const oAuth2Client = createOAuth2Client(redirectUri); try { - const { tokens } = await oAuth2Client.getToken(code); + const tokenParams = { + code: code, + redirect_uri: redirectUri + }; + + // 如果提供了 codeVerifier,添加到参数中 + if (codeVerifier) { + tokenParams.codeVerifier = codeVerifier; + } + + const { tokens } = await oAuth2Client.getToken(tokenParams); // 转换为兼容格式 return { diff --git a/web/admin-spa/dist/assets/AccountsView-QM0EhO-E.css b/web/admin-spa/dist/assets/AccountsView-QM0EhO-E.css deleted file mode 100644 index b765e546..00000000 --- a/web/admin-spa/dist/assets/AccountsView-QM0EhO-E.css +++ /dev/null @@ -1 +0,0 @@ -.accounts-container[data-v-981f21d9]{min-height:calc(100vh - 300px)}.table-container[data-v-981f21d9]{overflow-x:auto;border-radius:12px;border:1px solid rgba(0,0,0,.05)}.table-row[data-v-981f21d9]{transition:all .2s ease}.table-row[data-v-981f21d9]:hover{background-color:#00000005} diff --git a/web/admin-spa/dist/assets/AccountsView-dkIreWzq.js b/web/admin-spa/dist/assets/AccountsView-dkIreWzq.js deleted file mode 100644 index 0465f7da..00000000 --- a/web/admin-spa/dist/assets/AccountsView-dkIreWzq.js +++ /dev/null @@ -1,9 +0,0 @@ -import{r as C,aR as Ue,o as z,V as Ve,x as u,y as i,z as e,L as $,K as g,al as ye,aY as se,aX as he,aq as V,aZ as Ie,C as L,O as b,c as le,P as I,I as oe,a5 as $e,R as ue,an as Y,Q as de,ac as pe,u as N,q as Se,Y as je,B as ge}from"./vue-vendor-CKToUHZx.js";import{s as S}from"./toast-BvwA7Mwb.js";import{a as P,_ as Me}from"./index-9AMT1Op2.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const ie=C(!1),be=C({title:"",message:"",confirmText:"继续",cancelText:"取消"}),X=C(null);function Ce(){return{showConfirmModal:ie,confirmOptions:be,showConfirm:(w,d,K="继续",j="取消")=>new Promise(T=>{be.value={title:w,message:d,confirmText:K,cancelText:j},X.value=T,ie.value=!0}),handleConfirm:()=>{ie.value=!1,X.value&&(X.value(!0),X.value=null)},handleCancel:()=>{ie.value=!1,X.value&&(X.value(!1),X.value=null)}}}const Te=Ue("accounts",()=>{const D=C([]),W=C([]),p=C([]),w=C(!1),d=C(null),K=C(""),j=C("asc"),T=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/claude-accounts");if(f.success)D.value=f.data||[];else throw new Error(f.message||"获取Claude账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}},A=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/claude-console-accounts");if(f.success)W.value=f.data||[];else throw new Error(f.message||"获取Claude Console账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}},y=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/gemini-accounts");if(f.success)p.value=f.data||[];else throw new Error(f.message||"获取Gemini账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}};return{claudeAccounts:D,claudeConsoleAccounts:W,geminiAccounts:p,loading:w,error:d,sortBy:K,sortOrder:j,fetchClaudeAccounts:T,fetchClaudeConsoleAccounts:A,fetchGeminiAccounts:y,fetchAllAccounts:async()=>{w.value=!0,d.value=null;try{await Promise.all([T(),A(),y()])}catch(f){throw d.value=f.message,f}finally{w.value=!1}},createClaudeAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/claude-accounts",f);if(m.success)return await T(),m.data;throw new Error(m.message||"创建Claude账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},createClaudeConsoleAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/claude-console-accounts",f);if(m.success)return await A(),m.data;throw new Error(m.message||"创建Claude Console账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},createGeminiAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/gemini-accounts",f);if(m.success)return await y(),m.data;throw new Error(m.message||"创建Gemini账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},updateClaudeAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/claude-accounts/${f}`,m);if(k.success)return await T(),k;throw new Error(k.message||"更新Claude账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},updateClaudeConsoleAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/claude-console-accounts/${f}`,m);if(k.success)return await A(),k;throw new Error(k.message||"更新Claude Console账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},updateGeminiAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/gemini-accounts/${f}`,m);if(k.success)return await y(),k;throw new Error(k.message||"更新Gemini账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},toggleAccount:async(f,m)=>{w.value=!0,d.value=null;try{let k;f==="claude"?k=`/admin/claude-accounts/${m}/toggle`:f==="claude-console"?k=`/admin/claude-console-accounts/${m}/toggle`:k=`/admin/gemini-accounts/${m}/toggle`;const H=await P.put(k);if(H.success)return f==="claude"?await T():f==="claude-console"?await A():await y(),H;throw new Error(H.message||"切换状态失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},deleteAccount:async(f,m)=>{w.value=!0,d.value=null;try{let k;f==="claude"?k=`/admin/claude-accounts/${m}`:f==="claude-console"?k=`/admin/claude-console-accounts/${m}`:k=`/admin/gemini-accounts/${m}`;const H=await P.delete(k);if(H.success)return f==="claude"?await T():f==="claude-console"?await A():await y(),H;throw new Error(H.message||"删除失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},refreshClaudeToken:async f=>{w.value=!0,d.value=null;try{const m=await P.post(`/admin/claude-accounts/${f}/refresh`);if(m.success)return await T(),m;throw new Error(m.message||"Token刷新失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},generateClaudeAuthUrl:async f=>{try{const m=await P.post("/admin/claude-accounts/generate-auth-url",f);if(m.success)return m.data;throw new Error(m.message||"生成授权URL失败")}catch(m){throw d.value=m.message,m}},exchangeClaudeCode:async f=>{try{const m=await P.post("/admin/claude-accounts/exchange-code",f);if(m.success)return m.data;throw new Error(m.message||"交换授权码失败")}catch(m){throw d.value=m.message,m}},generateGeminiAuthUrl:async f=>{try{const m=await P.post("/admin/gemini-accounts/generate-auth-url",f);if(m.success)return m.data;throw new Error(m.message||"生成授权URL失败")}catch(m){throw d.value=m.message,m}},exchangeGeminiCode:async f=>{try{const m=await P.post("/admin/gemini-accounts/exchange-code",f);if(m.success)return m.data;throw new Error(m.message||"交换授权码失败")}catch(m){throw d.value=m.message,m}},sortAccounts:f=>{K.value===f?j.value=j.value==="asc"?"desc":"asc":(K.value=f,j.value="asc")},reset:()=>{D.value=[],W.value=[],p.value=[],w.value=!1,d.value=null,K.value="",j.value="asc"}}}),Ke={class:"space-y-4"},Pe={class:"flex items-center justify-between"},Re={class:"flex items-center cursor-pointer"},Ge={key:0,class:"bg-gray-50 p-4 rounded-lg border border-gray-200 space-y-4"},Le={class:"grid grid-cols-2 gap-4"},De={class:"space-y-4"},Oe={class:"flex items-center"},Ee={key:0,class:"grid grid-cols-2 gap-4"},ze={class:"relative"},We=["type"],we={__name:"ProxyConfig",props:{modelValue:{type:Object,default:()=>({enabled:!1,type:"socks5",host:"",port:"",username:"",password:""})}},emits:["update:modelValue"],setup(D,{emit:W}){const p=D,w=W,d=C({...p.modelValue}),K=C(!!(d.value.username||d.value.password)),j=C(!1);z(()=>p.modelValue,y=>{JSON.stringify(y)!==JSON.stringify(d.value)&&(d.value={...y},K.value=!!(y.username||y.password))},{deep:!0}),z(()=>d.value.enabled,y=>{A()}),z(()=>d.value.type,y=>{A()}),z(()=>d.value.host,y=>{A()}),z(()=>d.value.port,y=>{A()}),z(()=>d.value.username,y=>{A()}),z(()=>d.value.password,y=>{A()}),z(K,y=>{y||(d.value.username="",d.value.password="",A())});let T=null;function A(){T&&clearTimeout(T),T=setTimeout(()=>{const y={...d.value};K.value||(y.username="",y.password=""),w("update:modelValue",y)},100)}return Ve(()=>{T&&clearTimeout(T)}),(y,x)=>(i(),u("div",Ke,[e("div",Pe,[x[9]||(x[9]=e("h4",{class:"text-sm font-semibold text-gray-700"}," 代理设置 (可选) ",-1)),e("label",Re,[g(e("input",{"onUpdate:modelValue":x[0]||(x[0]=M=>d.value.enabled=M),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[ye,d.value.enabled]]),x[8]||(x[8]=e("span",{class:"ml-2 text-sm text-gray-700"},"启用代理",-1))])]),d.value.enabled?(i(),u("div",Ge,[x[17]||(x[17]=se('

配置代理以访问受限的网络资源。支持 SOCKS5 和 HTTP 代理。

请确保代理服务器稳定可用,否则会影响账户的正常使用。

',1)),e("div",null,[x[11]||(x[11]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"代理类型",-1)),g(e("select",{"onUpdate:modelValue":x[1]||(x[1]=M=>d.value.type=M),class:"form-input w-full"},x[10]||(x[10]=[e("option",{value:"socks5"}," SOCKS5 ",-1),e("option",{value:"http"}," HTTP ",-1),e("option",{value:"https"}," HTTPS ",-1)]),512),[[he,d.value.type]])]),e("div",Le,[e("div",null,[x[12]||(x[12]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"主机地址",-1)),g(e("input",{"onUpdate:modelValue":x[2]||(x[2]=M=>d.value.host=M),type:"text",placeholder:"例如: 192.168.1.100",class:"form-input w-full"},null,512),[[V,d.value.host]])]),e("div",null,[x[13]||(x[13]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"端口",-1)),g(e("input",{"onUpdate:modelValue":x[3]||(x[3]=M=>d.value.port=M),type:"number",placeholder:"例如: 1080",class:"form-input w-full"},null,512),[[V,d.value.port]])])]),e("div",De,[e("div",Oe,[g(e("input",{id:"proxyAuth","onUpdate:modelValue":x[4]||(x[4]=M=>K.value=M),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[ye,K.value]]),x[14]||(x[14]=e("label",{for:"proxyAuth",class:"ml-2 text-sm text-gray-700 cursor-pointer"}," 需要身份验证 ",-1))]),K.value?(i(),u("div",Ee,[e("div",null,[x[15]||(x[15]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"用户名",-1)),g(e("input",{"onUpdate:modelValue":x[5]||(x[5]=M=>d.value.username=M),type:"text",placeholder:"代理用户名",class:"form-input w-full"},null,512),[[V,d.value.username]])]),e("div",null,[x[16]||(x[16]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"密码",-1)),e("div",ze,[g(e("input",{"onUpdate:modelValue":x[6]||(x[6]=M=>d.value.password=M),type:j.value?"text":"password",placeholder:"代理密码",class:"form-input w-full pr-10"},null,8,We),[[Ie,d.value.password]]),e("button",{type:"button",class:"absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600",onClick:x[7]||(x[7]=M=>j.value=!j.value)},[e("i",{class:L(j.value?"fas fa-eye-slash":"fas fa-eye")},null,2)])])])])):$("",!0)]),x[18]||(x[18]=e("div",{class:"bg-blue-50 p-3 rounded-lg border border-blue-200"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),e("strong",null,"提示:"),b("代理设置将用于所有与此账户相关的API请求。请确保代理服务器支持HTTPS流量转发。 ")])],-1))])):$("",!0)]))}},qe={class:"space-y-6"},Ne={key:0},Be={class:"bg-blue-50 p-6 rounded-lg border border-blue-200"},He={class:"flex items-start gap-4"},Fe={class:"flex-1"},_e={class:"space-y-4"},Je={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},Ye={class:"flex items-start gap-3"},Qe={class:"flex-1"},Xe=["disabled"],Ze={key:0,class:"fas fa-link mr-2"},et={key:1,class:"loading-spinner mr-2"},tt={key:1,class:"space-y-3"},st={class:"flex items-center gap-2"},lt=["value"],ot={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},at={class:"flex items-start gap-3"},nt={class:"flex-1"},rt={class:"space-y-3"},it={key:1},ut={class:"bg-green-50 p-6 rounded-lg border border-green-200"},dt={class:"flex items-start gap-4"},pt={class:"flex-1"},ct={class:"space-y-4"},mt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},ft={class:"flex items-start gap-3"},xt={class:"flex-1"},vt=["disabled"],yt={key:0,class:"fas fa-link mr-2"},gt={key:1,class:"loading-spinner mr-2"},bt={key:1,class:"space-y-3"},wt={class:"flex items-center gap-2"},kt=["value"],ht={class:"bg-white/80 rounded-lg p-4 border border-green-300"},$t={class:"flex items-start gap-3"},Ct={class:"flex-1"},Tt={class:"space-y-3"},At={class:"flex gap-3 pt-4"},Ut=["disabled"],Vt={key:0,class:"loading-spinner mr-2"},It={__name:"OAuthFlow",props:{platform:{type:String,required:!0},proxy:{type:Object,default:null}},emits:["success","back"],setup(D,{emit:W}){const p=D,w=W,d=Te(),K=C(!1),j=C(!1),T=C(""),A=C(""),y=C(!1),x=C(""),M=le(()=>T.value&&A.value.trim());z(A,U=>{if(!U||typeof U!="string")return;const r=U.trim();if(!r)return;if(r.startsWith("http://")||r.startsWith("https://"))if(r.startsWith("http://localhost:45462"))try{const _=new URL(r).searchParams.get("code");_?(A.value=_,S("成功提取授权码!","success"),console.log("Successfully extracted authorization code from URL")):S("URL 中未找到授权码参数,请检查链接是否正确","error")}catch(J){console.error("Failed to parse URL:",J),S("链接格式错误,请检查是否为完整的 URL","error")}else if(p.platform==="gemini")try{const _=new URL(r).searchParams.get("code");_&&(A.value=_,S("成功提取授权码!","success"))}catch{}else S("请粘贴以 http://localhost:45462 开头的链接","error")});const O=async()=>{var U;K.value=!0;try{const r=(U=p.proxy)!=null&&U.enabled?{proxy:{type:p.proxy.type,host:p.proxy.host,port:parseInt(p.proxy.port),username:p.proxy.username||null,password:p.proxy.password||null}}:{};if(p.platform==="claude"){const v=await d.generateClaudeAuthUrl(r);T.value=v.authUrl,x.value=v.sessionId}else if(p.platform==="gemini"){const v=await d.generateGeminiAuthUrl(r);T.value=v.authUrl,x.value=v.sessionId}}catch(r){S(r.message||"生成授权链接失败","error")}finally{K.value=!1}},R=()=>{T.value="",A.value="",O()},Q=async()=>{try{await navigator.clipboard.writeText(T.value),y.value=!0,S("链接已复制","success"),setTimeout(()=>{y.value=!1},2e3)}catch{const r=document.createElement("input");r.value=T.value,document.body.appendChild(r),r.select(),document.execCommand("copy"),document.body.removeChild(r),y.value=!0,S("链接已复制","success"),setTimeout(()=>{y.value=!1},2e3)}},s=async()=>{var U;if(M.value){j.value=!0;try{let r={};p.platform==="claude"?r={sessionId:x.value,callbackUrl:A.value.trim()}:p.platform==="gemini"&&(r={code:A.value.trim(),sessionId:x.value}),(U=p.proxy)!=null&&U.enabled&&(r.proxy={type:p.proxy.type,host:p.proxy.host,port:parseInt(p.proxy.port),username:p.proxy.username||null,password:p.proxy.password||null});let v;p.platform==="claude"?v=await d.exchangeClaudeCode(r):p.platform==="gemini"&&(v=await d.exchangeGeminiCode(r)),w("success",v)}catch(r){S(r.message||"授权失败,请检查授权码是否正确","error")}finally{j.value=!1}}};return(U,r)=>(i(),u("div",qe,[D.platform==="claude"?(i(),u("div",Ne,[e("div",Be,[e("div",He,[r[14]||(r[14]=e("div",{class:"w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-link text-white"})],-1)),e("div",Fe,[r[12]||(r[12]=e("h4",{class:"font-semibold text-blue-900 mb-3"}," Claude 账户授权 ",-1)),r[13]||(r[13]=e("p",{class:"text-sm text-blue-800 mb-4"}," 请按照以下步骤完成 Claude 账户的授权: ",-1)),e("div",_e,[e("div",Je,[e("div",Ye,[r[5]||(r[5]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",Qe,[r[4]||(r[4]=e("p",{class:"font-medium text-blue-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(i(),u("div",tt,[e("div",st,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,lt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:Q},[e("i",{class:L(y.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-blue-600 hover:text-blue-700",onClick:R},r[3]||(r[3]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),b("重新生成 ",-1)]))])):(i(),u("button",{key:0,disabled:K.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:O},[K.value?(i(),u("div",et)):(i(),u("i",Ze)),b(" "+I(K.value?"生成中...":"生成授权链接"),1)],8,Xe))])])]),r[11]||(r[11]=se('
2

在浏览器中打开链接并完成授权

请在新标签页中打开授权链接,登录您的 Claude 账户并授权。

注意:如果您设置了代理,请确保浏览器也使用相同的代理访问授权页面。

',1)),e("div",ot,[e("div",at,[r[10]||(r[10]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",nt,[r[8]||(r[8]=e("p",{class:"font-medium text-blue-900 mb-2"}," 输入 Authorization Code ",-1)),r[9]||(r[9]=e("p",{class:"text-sm text-blue-700 mb-3"},[b(" 授权完成后,页面会显示一个 "),e("strong",null,"Authorization Code"),b(",请将其复制并粘贴到下方输入框: ")],-1)),e("div",rt,[e("div",null,[r[6]||(r[6]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-blue-500 mr-2"}),b("Authorization Code ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[0]||(r[0]=v=>A.value=v),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴从Claude页面获取的Authorization Code..."},null,512),[[V,A.value]])]),r[7]||(r[7]=e("p",{class:"text-xs text-gray-500 mt-2"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 请粘贴从Claude页面复制的Authorization Code ")],-1))])])])])])])])])])):D.platform==="gemini"?(i(),u("div",it,[e("div",ut,[e("div",dt,[r[26]||(r[26]=e("div",{class:"w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-robot text-white"})],-1)),e("div",pt,[r[24]||(r[24]=e("h4",{class:"font-semibold text-green-900 mb-3"}," Gemini 账户授权 ",-1)),r[25]||(r[25]=e("p",{class:"text-sm text-green-800 mb-4"}," 请按照以下步骤完成 Gemini 账户的授权: ",-1)),e("div",ct,[e("div",mt,[e("div",ft,[r[17]||(r[17]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",xt,[r[16]||(r[16]=e("p",{class:"font-medium text-green-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(i(),u("div",bt,[e("div",wt,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,kt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:Q},[e("i",{class:L(y.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-green-600 hover:text-green-700",onClick:R},r[15]||(r[15]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),b("重新生成 ",-1)]))])):(i(),u("button",{key:0,disabled:K.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:O},[K.value?(i(),u("div",gt)):(i(),u("i",yt)),b(" "+I(K.value?"生成中...":"生成授权链接"),1)],8,vt))])])]),r[23]||(r[23]=se('
2

在浏览器中打开链接并完成授权

  1. 点击上方的授权链接,在新页面中完成Google账号登录
  2. 点击“登录”按钮后可能会加载很慢(这是正常的)
  3. 如果超过1分钟还在加载,请按 F5 刷新页面
  4. 授权完成后会跳转到 http://localhost:45462 (可能显示无法访问)

提示:如果页面一直无法跳转,可以打开浏览器开发者工具(F12),F5刷新一下授权页再点击页面的登录按钮,在“网络”标签中找到以 localhost:45462 开头的请求,复制其完整URL。

',1)),e("div",ht,[e("div",$t,[r[22]||(r[22]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",Ct,[r[20]||(r[20]=e("p",{class:"font-medium text-green-900 mb-2"}," 复制oauth后的链接 ",-1)),r[21]||(r[21]=e("p",{class:"text-sm text-green-700 mb-3"}," 复制浏览器地址栏的完整链接并粘贴到下方输入框: ",-1)),e("div",Tt,[e("div",null,[r[18]||(r[18]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-green-500 mr-2"}),b("复制oauth后的链接 ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[1]||(r[1]=v=>A.value=v),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴以 http://localhost:45462 开头的完整链接..."},null,512),[[V,A.value]])]),r[19]||(r[19]=se('

支持粘贴完整链接,系统会自动提取授权码

也可以直接粘贴授权码(code参数的值)

',1))])])])])])])])])])):$("",!0),e("div",At,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:r[2]||(r[2]=v=>U.$emit("back"))}," 上一步 "),e("button",{type:"button",disabled:!M.value||j.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:s},[j.value?(i(),u("div",Vt)):$("",!0),b(" "+I(j.value?"验证中...":"完成授权"),1)],8,Ut)])]))}},St={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},jt={class:"modal-content w-full max-w-md p-6 mx-auto"},Mt={class:"flex items-start gap-4 mb-6"},Kt={class:"flex-1"},Pt={class:"text-lg font-bold text-gray-900 mb-2"},Rt={class:"text-gray-600 text-sm leading-relaxed whitespace-pre-line"},Gt={class:"flex gap-3"},Ae={__name:"ConfirmModal",props:{show:{type:Boolean,required:!0},title:{type:String,default:""},message:{type:String,default:""},confirmText:{type:String,default:"继续"},cancelText:{type:String,default:"取消"}},emits:["confirm","cancel"],setup(D){return(W,p)=>(i(),oe($e,{to:"body"},[D.show?(i(),u("div",St,[e("div",jt,[e("div",Mt,[p[2]||(p[2]=e("div",{class:"w-12 h-12 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-full flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-exclamation text-white text-xl"})],-1)),e("div",Kt,[e("h3",Pt,I(D.title),1),e("p",Rt,I(D.message),1)])]),e("div",Gt,[e("button",{class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-xl font-medium hover:bg-gray-200 transition-colors",onClick:p[0]||(p[0]=w=>W.$emit("cancel"))},I(D.cancelText),1),e("button",{class:"flex-1 px-4 py-2.5 bg-gradient-to-r from-yellow-500 to-orange-500 text-white rounded-xl font-medium hover:from-yellow-600 hover:to-orange-600 transition-colors shadow-sm",onClick:p[1]||(p[1]=w=>W.$emit("confirm"))},I(D.confirmText),1)])])])):$("",!0)]))}},Lt={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Dt={class:"modal-content w-full max-w-2xl p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Ot={class:"flex items-center justify-between mb-6"},Et={class:"flex items-center gap-3"},zt={class:"text-xl font-bold text-gray-900"},Wt={key:0,class:"flex items-center justify-center mb-8"},qt={class:"flex items-center space-x-4"},Nt={class:"flex items-center"},Bt={class:"flex items-center"},Ht={key:1},Ft={class:"space-y-6"},_t={key:0},Jt={class:"flex gap-4"},Yt={class:"flex items-center cursor-pointer"},Qt={class:"flex items-center cursor-pointer"},Xt={class:"flex items-center cursor-pointer"},Zt={key:1},es={class:"flex gap-4"},ts={class:"flex items-center cursor-pointer"},ss={class:"flex items-center cursor-pointer"},ls={key:0,class:"text-red-500 text-xs mt-1"},os={class:"flex gap-4"},as={class:"flex items-center cursor-pointer"},ns={class:"flex items-center cursor-pointer"},rs={key:2},is={key:3,class:"space-y-4"},us={key:0,class:"text-red-500 text-xs mt-1"},ds={key:0,class:"text-red-500 text-xs mt-1"},ps={class:"space-y-2 mb-3"},cs=["onUpdate:modelValue"],ms=["onUpdate:modelValue"],fs=["onClick"],xs={class:"mt-3 flex flex-wrap gap-2"},vs={key:4},ys={key:5,class:"space-y-4 bg-blue-50 p-4 rounded-lg border border-blue-200"},gs={class:"flex items-start gap-3 mb-4"},bs={key:0,class:"text-sm text-blue-800 mb-2"},ws={key:1,class:"text-sm text-blue-800 mb-2"},ks={class:"bg-white/80 rounded-lg p-3 mt-2 mb-2 border border-blue-300"},hs={key:0,class:"text-xs text-blue-800"},$s={key:1,class:"text-xs text-blue-800"},Cs={key:0,class:"text-red-500 text-xs mt-1"},Ts={class:"flex gap-3 pt-4"},As=["disabled"],Us=["disabled"],Vs={key:0,class:"loading-spinner mr-2"},Is={key:3,class:"space-y-6"},Ss={class:"flex gap-4"},js={class:"flex items-center cursor-pointer"},Ms={class:"flex items-center cursor-pointer"},Ks={key:0},Ps={key:1},Rs={key:2,class:"space-y-4"},Gs={class:"space-y-2 mb-3"},Ls=["onUpdate:modelValue"],Ds=["onUpdate:modelValue"],Os=["onClick"],Es={class:"mt-3 flex flex-wrap gap-2"},zs={key:3,class:"bg-amber-50 p-4 rounded-lg border border-amber-200"},Ws={class:"space-y-4"},qs={class:"flex gap-3 pt-4"},Ns=["disabled"],Bs={key:0,class:"loading-spinner mr-2"},ke={__name:"AccountForm",props:{account:{type:Object,default:null}},emits:["close","success"],setup(D,{emit:W}){var k,H,re,c,l,o,h,G,B,E;const p=D,w=W,d=Te(),{showConfirmModal:K,confirmOptions:j,showConfirm:T,handleConfirm:A,handleCancel:y}=Ce(),x=le(()=>!!p.account),M=C(!0),O=C(1),R=C(!1),Q=()=>{var n;return(n=p.account)!=null&&n.proxy&&p.account.proxy.host&&p.account.proxy.port?{enabled:!0,type:p.account.proxy.type||"socks5",host:p.account.proxy.host,port:p.account.proxy.port,username:p.account.proxy.username||"",password:p.account.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""}},s=C({platform:((k=p.account)==null?void 0:k.platform)||"claude",addType:"oauth",name:((H=p.account)==null?void 0:H.name)||"",description:((re=p.account)==null?void 0:re.description)||"",accountType:((c=p.account)==null?void 0:c.accountType)||"shared",projectId:((l=p.account)==null?void 0:l.projectId)||"",accessToken:"",refreshToken:"",proxy:Q(),apiUrl:((o=p.account)==null?void 0:o.apiUrl)||"",apiKey:((h=p.account)==null?void 0:h.apiKey)||"",priority:((G=p.account)==null?void 0:G.priority)||50,userAgent:((B=p.account)==null?void 0:B.userAgent)||"",rateLimitDuration:((E=p.account)==null?void 0:E.rateLimitDuration)||60}),U=C([]),r=()=>{var n;(n=p.account)!=null&&n.supportedModels&&(typeof p.account.supportedModels=="object"&&!Array.isArray(p.account.supportedModels)?U.value=Object.entries(p.account.supportedModels).map(([t,a])=>({from:t,to:a})):Array.isArray(p.account.supportedModels)&&(U.value=p.account.supportedModels.map(t=>({from:t,to:t}))))},v=C({name:"",accessToken:"",apiUrl:"",apiKey:""}),J=le(()=>{var n;return((n=s.value.name)==null?void 0:n.trim())&&s.value.platform});le(()=>{var n,t,a;return s.value.addType==="manual"?((n=s.value.name)==null?void 0:n.trim())&&((t=s.value.accessToken)==null?void 0:t.trim()):(a=s.value.name)==null?void 0:a.trim()});const _=async()=>{if(v.value.name="",!J.value){(!s.value.name||s.value.name.trim()==="")&&(v.value.name="请填写账户名称");return}s.value.platform==="gemini"&&O.value===1&&s.value.addType==="oauth"&&(!s.value.projectId||s.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。 - -如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。 -如果您使用的是普通个人账号,可以继续不填写。`,"继续","返回填写")||(O.value=2)},Z=async n=>{R.value=!0;try{const t={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};s.value.platform==="claude"?(t.claudeAiOauth=n.claudeAiOauth||n,t.priority=s.value.priority||50):s.value.platform==="gemini"&&(t.geminiOauth=n.tokens||n,s.value.projectId&&(t.projectId=s.value.projectId));let a;s.value.platform==="claude"?a=await d.createClaudeAccount(t):a=await d.createGeminiAccount(t),w("success",a)}catch(t){S(t.message||"账户创建失败","error")}finally{R.value=!1}},ae=async()=>{v.value.name="",v.value.accessToken="",v.value.apiUrl="",v.value.apiKey="";let n=!1;if((!s.value.name||s.value.name.trim()==="")&&(v.value.name="请填写账户名称",n=!0),s.value.platform==="claude-console"?((!s.value.apiUrl||s.value.apiUrl.trim()==="")&&(v.value.apiUrl="请填写 API URL",n=!0),(!s.value.apiKey||s.value.apiKey.trim()==="")&&(v.value.apiKey="请填写 API Key",n=!0)):s.value.addType==="manual"&&(!s.value.accessToken||s.value.accessToken.trim()==="")&&(v.value.accessToken="请填写 Access Token",n=!0),!n){R.value=!0;try{const t={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};if(s.value.platform==="claude"){const q=s.value.refreshToken?6e5:31536e6;t.claudeAiOauth={accessToken:s.value.accessToken,refreshToken:s.value.refreshToken||"",expiresAt:Date.now()+q,scopes:["user:inference"]},t.priority=s.value.priority||50}else if(s.value.platform==="gemini"){const q=s.value.refreshToken?6e5:31536e6;t.geminiOauth={access_token:s.value.accessToken,refresh_token:s.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+q},s.value.projectId&&(t.projectId=s.value.projectId)}else s.value.platform==="claude-console"&&(t.apiUrl=s.value.apiUrl,t.apiKey=s.value.apiKey,t.priority=s.value.priority||50,t.supportedModels=m()||{},t.userAgent=s.value.userAgent||null,t.rateLimitDuration=s.value.rateLimitDuration||60);let a;s.value.platform==="claude"?a=await d.createClaudeAccount(t):s.value.platform==="claude-console"?a=await d.createClaudeConsoleAccount(t):a=await d.createGeminiAccount(t),w("success",a)}catch(t){S(t.message||"账户创建失败","error")}finally{R.value=!1}}},ne=async()=>{if(v.value.name="",!s.value.name||s.value.name.trim()===""){v.value.name="请填写账户名称";return}if(!(s.value.platform==="gemini"&&(!s.value.projectId||s.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。 - -如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。 -如果您使用的是普通个人账号,可以继续不填写。`,"继续保存","返回填写"))){R.value=!0;try{const n={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};if(s.value.accessToken||s.value.refreshToken){if(p.account.platform==="claude"){const t=s.value.refreshToken?6e5:31536e6;n.claudeAiOauth={accessToken:s.value.accessToken||"",refreshToken:s.value.refreshToken||"",expiresAt:Date.now()+t,scopes:["user:inference"]}}else if(p.account.platform==="gemini"){const t=s.value.refreshToken?6e5:31536e6;n.geminiOauth={access_token:s.value.accessToken||"",refresh_token:s.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+t}}}p.account.platform==="gemini"&&s.value.projectId&&(n.projectId=s.value.projectId),p.account.platform==="claude"&&(n.priority=s.value.priority||50),p.account.platform==="claude-console"&&(n.apiUrl=s.value.apiUrl,s.value.apiKey&&(n.apiKey=s.value.apiKey),n.priority=s.value.priority||50,n.supportedModels=m()||{},n.userAgent=s.value.userAgent||null,n.rateLimitDuration=s.value.rateLimitDuration||60),p.account.platform==="claude"?await d.updateClaudeAccount(p.account.id,n):p.account.platform==="claude-console"?await d.updateClaudeConsoleAccount(p.account.id,n):await d.updateGeminiAccount(p.account.id,n),w("success")}catch(n){S(n.message||"账户更新失败","error")}finally{R.value=!1}}};z(()=>s.value.name,()=>{var n;v.value.name&&((n=s.value.name)!=null&&n.trim())&&(v.value.name="")}),z(()=>s.value.accessToken,()=>{var n;v.value.accessToken&&((n=s.value.accessToken)!=null&&n.trim())&&(v.value.accessToken="")}),z(()=>s.value.apiUrl,()=>{var n;v.value.apiUrl&&((n=s.value.apiUrl)!=null&&n.trim())&&(v.value.apiUrl="")}),z(()=>s.value.apiKey,()=>{var n;v.value.apiKey&&((n=s.value.apiKey)!=null&&n.trim())&&(v.value.apiKey="")}),z(()=>s.value.platform,n=>{n==="claude-console"&&(s.value.addType="manual")});const ee=()=>{U.value.push({from:"",to:""})},te=n=>{U.value.splice(n,1)},f=(n,t)=>{if(U.value.some(q=>q.from===n)){S(`模型 ${n} 的映射已存在`,"info");return}U.value.push({from:n,to:t}),S(`已添加映射: ${n} → ${t}`,"success")},m=()=>{const n={};return U.value.forEach(t=>{t.from&&t.to&&(n[t.from]=t.to)}),Object.keys(n).length>0?n:null};return z(()=>p.account,n=>{if(n){r();const t=n.proxy&&n.proxy.host&&n.proxy.port?{enabled:!0,type:n.proxy.type||"socks5",host:n.proxy.host,port:n.proxy.port,username:n.proxy.username||"",password:n.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""};s.value={platform:n.platform,addType:"oauth",name:n.name,description:n.description||"",accountType:n.accountType||"shared",projectId:n.projectId||"",accessToken:"",refreshToken:"",proxy:t,apiUrl:n.apiUrl||"",apiKey:"",priority:n.priority||50,userAgent:n.userAgent||"",rateLimitDuration:n.rateLimitDuration||60}}},{immediate:!0}),r(),(n,t)=>(i(),oe($e,{to:"body"},[M.value?(i(),u("div",Lt,[e("div",Dt,[e("div",Ot,[e("div",Et,[t[45]||(t[45]=e("div",{class:"w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-white"})],-1)),e("h3",zt,I(x.value?"编辑账户":"添加账户"),1)]),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:t[0]||(t[0]=a=>n.$emit("close"))},t[46]||(t[46]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),!x.value&&s.value.addType==="oauth"?(i(),u("div",Wt,[e("div",qt,[e("div",Nt,[e("div",{class:L(["w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",O.value>=1?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 1 ",2),t[47]||(t[47]=e("span",{class:"ml-2 text-sm font-medium text-gray-700"},"基本信息",-1))]),t[49]||(t[49]=e("div",{class:"w-8 h-0.5 bg-gray-300"},null,-1)),e("div",Bt,[e("div",{class:L(["w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",O.value>=2?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 2 ",2),t[48]||(t[48]=e("span",{class:"ml-2 text-sm font-medium text-gray-700"},"授权认证",-1))])])])):$("",!0),O.value===1&&!x.value?(i(),u("div",Ht,[e("div",Ft,[x.value?$("",!0):(i(),u("div",_t,[t[53]||(t[53]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"平台",-1)),e("div",Jt,[e("label",Yt,[g(e("input",{"onUpdate:modelValue":t[1]||(t[1]=a=>s.value.platform=a),type:"radio",value:"claude",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[50]||(t[50]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",Qt,[g(e("input",{"onUpdate:modelValue":t[2]||(t[2]=a=>s.value.platform=a),type:"radio",value:"claude-console",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[51]||(t[51]=e("span",{class:"text-sm text-gray-700"},"Claude Console",-1))]),e("label",Xt,[g(e("input",{"onUpdate:modelValue":t[3]||(t[3]=a=>s.value.platform=a),type:"radio",value:"gemini",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[52]||(t[52]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])])),!x.value&&s.value.platform!=="claude-console"?(i(),u("div",Zt,[t[56]||(t[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"添加方式",-1)),e("div",es,[e("label",ts,[g(e("input",{"onUpdate:modelValue":t[4]||(t[4]=a=>s.value.addType=a),type:"radio",value:"oauth",class:"mr-2"},null,512),[[Y,s.value.addType]]),t[54]||(t[54]=e("span",{class:"text-sm text-gray-700"},"OAuth 授权 (推荐)",-1))]),e("label",ss,[g(e("input",{"onUpdate:modelValue":t[5]||(t[5]=a=>s.value.addType=a),type:"radio",value:"manual",class:"mr-2"},null,512),[[Y,s.value.addType]]),t[55]||(t[55]=e("span",{class:"text-sm text-gray-700"},"手动输入 Access Token",-1))])])])):$("",!0),e("div",null,[t[57]||(t[57]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[6]||(t[6]=a=>s.value.name=a),type:"text",required:"",class:L(["form-input w-full",{"border-red-500":v.value.name}]),placeholder:"为账户设置一个易识别的名称"},null,2),[[V,s.value.name]]),v.value.name?(i(),u("p",ls,I(v.value.name),1)):$("",!0)]),e("div",null,[t[58]||(t[58]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[7]||(t[7]=a=>s.value.description=a),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[V,s.value.description]])]),e("div",null,[t[61]||(t[61]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",os,[e("label",as,[g(e("input",{"onUpdate:modelValue":t[8]||(t[8]=a=>s.value.accountType=a),type:"radio",value:"shared",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[59]||(t[59]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",ns,[g(e("input",{"onUpdate:modelValue":t[9]||(t[9]=a=>s.value.accountType=a),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[60]||(t[60]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))])]),t[62]||(t[62]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用 ",-1))]),s.value.platform==="gemini"?(i(),u("div",rs,[t[63]||(t[63]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[10]||(t[10]=a=>s.value.projectId=a),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[V,s.value.projectId]]),t[64]||(t[64]=e("div",{class:"mt-2 p-3 bg-yellow-50 border border-yellow-200 rounded-lg"},[e("div",{class:"flex items-start gap-2"},[e("i",{class:"fas fa-info-circle text-yellow-600 mt-0.5"}),e("div",{class:"text-xs text-yellow-700"},[e("p",{class:"font-medium mb-1"}," Google Cloud/Workspace 账号需要提供项目编号 "),e("p",null,"某些 Google 账号(特别是绑定了 Google Cloud 的账号)会被识别为 Workspace 账号,需要提供额外的项目编号。"),e("div",{class:"mt-2 p-2 bg-white rounded border border-yellow-300"},[e("p",{class:"font-medium mb-1"}," 如何获取项目编号: "),e("ol",{class:"list-decimal list-inside space-y-1 ml-2"},[e("li",null,[b(" 访问 "),e("a",{href:"https://console.cloud.google.com/welcome",target:"_blank",class:"text-blue-600 hover:underline font-medium"},"Google Cloud Console")]),e("li",null,[b("复制"),e("span",{class:"font-semibold text-red-600"},"项目编号(Project Number)"),b(",通常是12位纯数字")]),e("li",{class:"text-red-600"}," ⚠️ 注意:不要复制项目ID(Project ID),要复制项目编号! ")])]),e("p",{class:"mt-2"},[e("strong",null,"提示:"),b("如果您的账号是普通个人账号(未绑定 Google Cloud),请留空此字段。 ")])])])],-1))])):$("",!0),s.value.platform==="claude-console"&&!x.value?(i(),u("div",is,[e("div",null,[t[65]||(t[65]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL *",-1)),g(e("input",{"onUpdate:modelValue":t[11]||(t[11]=a=>s.value.apiUrl=a),type:"text",required:"",class:L(["form-input w-full",{"border-red-500":v.value.apiUrl}]),placeholder:"例如:https://api.example.com"},null,2),[[V,s.value.apiUrl]]),v.value.apiUrl?(i(),u("p",us,I(v.value.apiUrl),1)):$("",!0)]),e("div",null,[t[66]||(t[66]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key *",-1)),g(e("input",{"onUpdate:modelValue":t[12]||(t[12]=a=>s.value.apiKey=a),type:"password",required:"",class:L(["form-input w-full",{"border-red-500":v.value.apiKey}]),placeholder:"请输入API Key"},null,2),[[V,s.value.apiKey]]),v.value.apiKey?(i(),u("p",ds,I(v.value.apiKey),1)):$("",!0)]),e("div",null,[t[70]||(t[70]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"模型映射表 (可选)",-1)),t[71]||(t[71]=e("div",{class:"bg-blue-50 p-3 rounded-lg mb-3"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 ")])],-1)),e("div",ps,[(i(!0),u(de,null,pe(U.value,(a,q)=>(i(),u("div",{key:q,class:"flex items-center gap-2"},[g(e("input",{"onUpdate:modelValue":F=>a.from=F,type:"text",class:"form-input flex-1",placeholder:"原始模型名称"},null,8,cs),[[V,a.from]]),t[68]||(t[68]=e("i",{class:"fas fa-arrow-right text-gray-400"},null,-1)),g(e("input",{"onUpdate:modelValue":F=>a.to=F,type:"text",class:"form-input flex-1",placeholder:"映射后的模型名称"},null,8,ms),[[V,a.to]]),e("button",{type:"button",class:"p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors",onClick:F=>te(q)},t[67]||(t[67]=[e("i",{class:"fas fa-trash"},null,-1)]),8,fs)]))),128))]),e("button",{type:"button",class:"w-full px-4 py-2 border-2 border-dashed border-gray-300 text-gray-600 rounded-lg hover:border-gray-400 hover:text-gray-700 transition-colors",onClick:ee},t[69]||(t[69]=[e("i",{class:"fas fa-plus mr-2"},null,-1),b(" 添加模型映射 ",-1)])),e("div",xs,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[13]||(t[13]=a=>f("claude-3-5-sonnet-20241022","claude-3-5-sonnet-20241022"))}," + Sonnet 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[14]||(t[14]=a=>f("claude-3-opus-20240229","claude-3-opus-20240229"))}," + Opus 3 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition-colors",onClick:t[15]||(t[15]=a=>f("claude-3-5-haiku-20241022","claude-3-5-haiku-20241022"))}," + Haiku 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-orange-100 text-orange-700 rounded-lg hover:bg-orange-200 transition-colors",onClick:t[16]||(t[16]=a=>f("claude-sonnet-4-20250514","claude-3-5-sonnet-20241022"))}," + Sonnet 4 → 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors",onClick:t[17]||(t[17]=a=>f("claude-opus-4-20250514","claude-3-opus-20240229"))}," + Opus 4 → 3 ")]),t[72]||(t[72]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 ",-1))]),e("div",null,[t[73]||(t[73]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[18]||(t[18]=a=>s.value.userAgent=a),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[V,s.value.userAgent]])]),e("div",null,[t[74]||(t[74]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[19]||(t[19]=a=>s.value.rateLimitDuration=a),type:"number",min:"1",class:"form-input w-full",placeholder:"默认60分钟"},null,512),[[V,s.value.rateLimitDuration,void 0,{number:!0}]]),t[75]||(t[75]=e("p",{class:"text-xs text-gray-500 mt-1"}," 当账号返回429错误时,暂停调度的时间(分钟) ",-1))])])):$("",!0),s.value.platform==="claude"||s.value.platform==="claude-console"?(i(),u("div",vs,[t[76]||(t[76]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[20]||(t[20]=a=>s.value.priority=a),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高,默认50"},null,512),[[V,s.value.priority,void 0,{number:!0}]]),t[77]||(t[77]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):$("",!0),s.value.addType==="manual"&&s.value.platform!=="claude-console"?(i(),u("div",ys,[e("div",gs,[t[83]||(t[83]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[t[81]||(t[81]=e("h5",{class:"font-semibold text-blue-900 mb-2"}," 手动输入 Token ",-1)),s.value.platform==="claude"?(i(),u("p",bs," 请输入有效的 Claude Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):s.value.platform==="gemini"?(i(),u("p",ws," 请输入有效的 Gemini Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):$("",!0),e("div",ks,[t[80]||(t[80]=e("p",{class:"text-sm text-blue-900 font-medium mb-1"},[e("i",{class:"fas fa-folder-open mr-1"}),b(" 获取 Access Token 的方法: ")],-1)),s.value.platform==="claude"?(i(),u("p",hs,t[78]||(t[78]=[b(" 请从已登录 Claude Code 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.claude/.credentials.json",-1),b(" 文件中的凭证, 请勿使用 Claude 官网 API Keys 页面的密钥。 ",-1)]))):s.value.platform==="gemini"?(i(),u("p",$s,t[79]||(t[79]=[b(" 请从已登录 Gemini CLI 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.config/gemini/credentials.json",-1),b(" 文件中的凭证。 ",-1)]))):$("",!0)]),t[82]||(t[82]=e("p",{class:"text-xs text-blue-600"}," 💡 如果未填写 Refresh Token,Token 过期后需要手动更新。 ",-1))])]),e("div",null,[t[84]||(t[84]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Access Token *",-1)),g(e("textarea",{"onUpdate:modelValue":t[21]||(t[21]=a=>s.value.accessToken=a),rows:"4",required:"",class:L(["form-input w-full resize-none font-mono text-xs",{"border-red-500":v.value.accessToken}]),placeholder:"请输入 Access Token..."},null,2),[[V,s.value.accessToken]]),v.value.accessToken?(i(),u("p",Cs,I(v.value.accessToken),1)):$("",!0)]),e("div",null,[t[85]||(t[85]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Refresh Token (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[22]||(t[22]=a=>s.value.refreshToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"请输入 Refresh Token..."},null,512),[[V,s.value.refreshToken]])])])):$("",!0),ue(we,{modelValue:s.value.proxy,"onUpdate:modelValue":t[23]||(t[23]=a=>s.value.proxy=a)},null,8,["modelValue"]),e("div",Ts,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[24]||(t[24]=a=>n.$emit("close"))}," 取消 "),s.value.addType==="oauth"&&s.value.platform!=="claude-console"?(i(),u("button",{key:0,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:_}," 下一步 ",8,As)):(i(),u("button",{key:1,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:ae},[R.value?(i(),u("div",Vs)):$("",!0),b(" "+I(R.value?"创建中...":"创建"),1)],8,Us))])])])):$("",!0),O.value===2&&s.value.addType==="oauth"?(i(),oe(It,{key:2,platform:s.value.platform,proxy:s.value.proxy,onSuccess:Z,onBack:t[25]||(t[25]=a=>O.value=1)},null,8,["platform","proxy"])):$("",!0),x.value?(i(),u("div",Is,[e("div",null,[t[86]||(t[86]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[26]||(t[26]=a=>s.value.name=a),type:"text",required:"",class:"form-input w-full",placeholder:"为账户设置一个易识别的名称"},null,512),[[V,s.value.name]])]),e("div",null,[t[87]||(t[87]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[27]||(t[27]=a=>s.value.description=a),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[V,s.value.description]])]),e("div",null,[t[90]||(t[90]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",Ss,[e("label",js,[g(e("input",{"onUpdate:modelValue":t[28]||(t[28]=a=>s.value.accountType=a),type:"radio",value:"shared",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[88]||(t[88]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Ms,[g(e("input",{"onUpdate:modelValue":t[29]||(t[29]=a=>s.value.accountType=a),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[89]||(t[89]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))])]),t[91]||(t[91]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用 ",-1))]),s.value.platform==="gemini"?(i(),u("div",Ks,[t[92]||(t[92]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[30]||(t[30]=a=>s.value.projectId=a),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[V,s.value.projectId]]),t[93]||(t[93]=e("p",{class:"text-xs text-gray-500 mt-2"}," Google Cloud/Workspace 账号可能需要提供项目编号 ",-1))])):$("",!0),s.value.platform==="claude"||s.value.platform==="claude-console"?(i(),u("div",Ps,[t[94]||(t[94]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[31]||(t[31]=a=>s.value.priority=a),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高"},null,512),[[V,s.value.priority,void 0,{number:!0}]]),t[95]||(t[95]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):$("",!0),s.value.platform==="claude-console"?(i(),u("div",Rs,[e("div",null,[t[96]||(t[96]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL",-1)),g(e("input",{"onUpdate:modelValue":t[32]||(t[32]=a=>s.value.apiUrl=a),type:"text",required:"",class:"form-input w-full",placeholder:"例如:https://api.example.com"},null,512),[[V,s.value.apiUrl]])]),e("div",null,[t[97]||(t[97]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key",-1)),g(e("input",{"onUpdate:modelValue":t[33]||(t[33]=a=>s.value.apiKey=a),type:"password",class:"form-input w-full",placeholder:"留空表示不更新"},null,512),[[V,s.value.apiKey]]),t[98]||(t[98]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示不更新 API Key ",-1))]),e("div",null,[t[102]||(t[102]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"模型映射表 (可选)",-1)),t[103]||(t[103]=e("div",{class:"bg-blue-50 p-3 rounded-lg mb-3"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 ")])],-1)),e("div",Gs,[(i(!0),u(de,null,pe(U.value,(a,q)=>(i(),u("div",{key:q,class:"flex items-center gap-2"},[g(e("input",{"onUpdate:modelValue":F=>a.from=F,type:"text",class:"form-input flex-1",placeholder:"原始模型名称"},null,8,Ls),[[V,a.from]]),t[100]||(t[100]=e("i",{class:"fas fa-arrow-right text-gray-400"},null,-1)),g(e("input",{"onUpdate:modelValue":F=>a.to=F,type:"text",class:"form-input flex-1",placeholder:"映射后的模型名称"},null,8,Ds),[[V,a.to]]),e("button",{type:"button",class:"p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors",onClick:F=>te(q)},t[99]||(t[99]=[e("i",{class:"fas fa-trash"},null,-1)]),8,Os)]))),128))]),e("button",{type:"button",class:"w-full px-4 py-2 border-2 border-dashed border-gray-300 text-gray-600 rounded-lg hover:border-gray-400 hover:text-gray-700 transition-colors",onClick:ee},t[101]||(t[101]=[e("i",{class:"fas fa-plus mr-2"},null,-1),b(" 添加模型映射 ",-1)])),e("div",Es,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[34]||(t[34]=a=>f("claude-3-5-sonnet-20241022","claude-3-5-sonnet-20241022"))}," + Sonnet 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[35]||(t[35]=a=>f("claude-3-opus-20240229","claude-3-opus-20240229"))}," + Opus 3 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition-colors",onClick:t[36]||(t[36]=a=>f("claude-3-5-haiku-20241022","claude-3-5-haiku-20241022"))}," + Haiku 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-orange-100 text-orange-700 rounded-lg hover:bg-orange-200 transition-colors",onClick:t[37]||(t[37]=a=>f("claude-sonnet-4-20250514","claude-3-5-sonnet-20241022"))}," + Sonnet 4 → 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors",onClick:t[38]||(t[38]=a=>f("claude-opus-4-20250514","claude-3-opus-20240229"))}," + Opus 4 → 3 ")])]),e("div",null,[t[104]||(t[104]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[39]||(t[39]=a=>s.value.userAgent=a),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[V,s.value.userAgent]])]),e("div",null,[t[105]||(t[105]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[40]||(t[40]=a=>s.value.rateLimitDuration=a),type:"number",min:"1",class:"form-input w-full"},null,512),[[V,s.value.rateLimitDuration,void 0,{number:!0}]])])])):$("",!0),s.value.platform!=="claude-console"?(i(),u("div",zs,[t[108]||(t[108]=e("div",{class:"flex items-start gap-3 mb-4"},[e("div",{class:"w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-key text-white text-sm"})]),e("div",null,[e("h5",{class:"font-semibold text-amber-900 mb-2"}," 更新 Token "),e("p",{class:"text-sm text-amber-800 mb-2"}," 可以更新 Access Token 和 Refresh Token。为了安全起见,不会显示当前的 Token 值。 "),e("p",{class:"text-xs text-amber-600"}," 💡 留空表示不更新该字段。 ")])],-1)),e("div",Ws,[e("div",null,[t[106]||(t[106]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Access Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[41]||(t[41]=a=>s.value.accessToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[V,s.value.accessToken]])]),e("div",null,[t[107]||(t[107]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Refresh Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[42]||(t[42]=a=>s.value.refreshToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[V,s.value.refreshToken]])])])])):$("",!0),ue(we,{modelValue:s.value.proxy,"onUpdate:modelValue":t[43]||(t[43]=a=>s.value.proxy=a)},null,8,["modelValue"]),e("div",qs,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[44]||(t[44]=a=>n.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:ne},[R.value?(i(),u("div",Bs)):$("",!0),b(" "+I(R.value?"更新中...":"更新"),1)],8,Ns)])])):$("",!0)])])):$("",!0),ue(Ae,{show:N(K),title:N(j).title,message:N(j).message,"confirm-text":N(j).confirmText,"cancel-text":N(j).cancelText,onConfirm:N(A),onCancel:N(y)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},Hs={class:"accounts-container"},Fs={class:"card p-6"},_s={class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},Js={class:"flex gap-2"},Ys={key:0,class:"text-center py-12"},Qs={key:1,class:"text-center py-12"},Xs={key:2,class:"table-container"},Zs={class:"min-w-full"},el={class:"bg-gray-50/80 backdrop-blur-sm"},tl={key:1,class:"fas fa-sort ml-1 text-gray-400"},sl={key:1,class:"fas fa-sort ml-1 text-gray-400"},ll={key:1,class:"fas fa-sort ml-1 text-gray-400"},ol={key:1,class:"fas fa-sort ml-1 text-gray-400"},al={key:1,class:"fas fa-sort ml-1 text-gray-400"},nl={class:"divide-y divide-gray-200/50"},rl={class:"px-6 py-4 whitespace-nowrap"},il={class:"flex items-center"},ul={class:"flex items-center gap-2"},dl={class:"text-sm font-semibold text-gray-900"},pl={key:0,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800"},cl={key:1,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"},ml={class:"text-xs text-gray-500"},fl={class:"px-6 py-4 whitespace-nowrap"},xl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},vl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-purple-100 text-purple-800"},yl={key:2,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-indigo-100 text-indigo-800"},gl={class:"px-6 py-4 whitespace-nowrap"},bl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800"},wl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-800"},kl={key:2,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-orange-100 text-orange-800"},hl={class:"px-6 py-4 whitespace-nowrap"},$l={class:"flex flex-col gap-1"},Cl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},Tl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-gray-100 text-gray-700"},Al=["title"],Ul={key:3,class:"text-xs text-gray-500"},Vl={class:"px-6 py-4 whitespace-nowrap"},Il={key:0,class:"flex items-center gap-2"},Sl={class:"w-16 bg-gray-200 rounded-full h-2"},jl={class:"text-xs text-gray-700 font-medium min-w-[20px]"},Ml={key:1,class:"text-gray-400 text-sm"},Kl={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-600"},Pl={key:0,class:"text-xs bg-blue-50 px-2 py-1 rounded font-mono"},Rl={key:1,class:"text-gray-400"},Gl={class:"px-6 py-4 whitespace-nowrap text-sm"},Ll={key:0,class:"space-y-1"},Dl={class:"flex items-center gap-2"},Ol={class:"text-sm font-medium text-gray-900"},El={class:"flex items-center gap-2"},zl={class:"text-xs text-gray-600"},Wl={key:0,class:"text-xs text-gray-500"},ql={key:1,class:"text-gray-400 text-xs"},Nl={class:"px-6 py-4 whitespace-nowrap"},Bl={key:0,class:"space-y-2"},Hl={class:"flex items-center gap-2"},Fl={class:"w-24 bg-gray-200 rounded-full h-2"},_l={class:"text-xs text-gray-700 font-medium min-w-[32px]"},Jl={class:"text-xs text-gray-600"},Yl={key:0,class:"text-indigo-600 font-medium"},Ql={key:1,class:"text-gray-400 text-sm"},Xl={key:2,class:"text-gray-400 text-sm"},Zl={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-600"},eo={class:"px-6 py-4 whitespace-nowrap text-sm font-medium"},to={class:"flex items-center gap-2"},so=["disabled","title","onClick"],lo=["disabled","title","onClick"],oo=["onClick"],ao=["onClick"],no={__name:"AccountsView",setup(D){const{showConfirmModal:W,confirmOptions:p,showConfirm:w,handleConfirm:d,handleCancel:K}=Ce(),j=C([]),T=C(!1),A=C("name"),y=C(""),x=C("asc"),M=C([]),O=C(!1),R=C(!1),Q=C(null),s=le(()=>y.value?[...j.value].sort((l,o)=>{var B,E,n,t,a,q,F,ce,me,fe,xe,ve;let h=l[y.value],G=o[y.value];return y.value==="dailyTokens"?(h=((E=(B=l.usage)==null?void 0:B.daily)==null?void 0:E.allTokens)||0,G=((t=(n=o.usage)==null?void 0:n.daily)==null?void 0:t.allTokens)||0):y.value==="dailyRequests"?(h=((q=(a=l.usage)==null?void 0:a.daily)==null?void 0:q.requests)||0,G=((ce=(F=o.usage)==null?void 0:F.daily)==null?void 0:ce.requests)||0):y.value==="totalTokens"&&(h=((fe=(me=l.usage)==null?void 0:me.total)==null?void 0:fe.allTokens)||0,G=((ve=(xe=o.usage)==null?void 0:xe.total)==null?void 0:ve.allTokens)||0),y.value==="lastUsed"&&(h=l.lastUsedAt?new Date(l.lastUsedAt).getTime():0,G=o.lastUsedAt?new Date(o.lastUsedAt).getTime():0),y.value==="status"&&(h=l.isActive?1:0,G=o.isActive?1:0),hG?x.value==="asc"?1:-1:0}):j.value),U=async()=>{T.value=!0;try{const[c,l,o,h]=await Promise.all([P.get("/admin/claude-accounts"),P.get("/admin/claude-console-accounts"),P.get("/admin/gemini-accounts"),P.get("/admin/api-keys")]);h.success&&(M.value=h.data||[]);const G=[];if(c.success){const B=(c.data||[]).map(E=>{const n=M.value.filter(t=>t.claudeAccountId===E.id).length;return{...E,platform:"claude",boundApiKeysCount:n}});G.push(...B)}if(l.success){const B=(l.data||[]).map(E=>{const n=M.value.filter(t=>t.claudeConsoleAccountId===E.id).length;return{...E,platform:"claude-console",boundApiKeysCount:n}});G.push(...B)}if(o.success){const B=(o.data||[]).map(E=>{const n=M.value.filter(t=>t.geminiAccountId===E.id).length;return{...E,platform:"gemini",boundApiKeysCount:n}});G.push(...B)}j.value=G}catch{S("加载账户失败","error")}finally{T.value=!1}},r=c=>{c&&(y.value===c?x.value=x.value==="asc"?"desc":"asc":(y.value=c,x.value="asc"))},v=c=>{if(c==null)return"0";const l=Number(c);return l>=1e6?Math.floor(l/1e6).toLocaleString()+"M":l.toLocaleString()},J=c=>{if(!c)return"从未使用";const l=new Date(c),h=new Date-l;return h<6e4?"刚刚":h<36e5?`${Math.floor(h/6e4)} 分钟前`:h<864e5?`${Math.floor(h/36e5)} 小时前`:h<6048e5?`${Math.floor(h/864e5)} 天前`:l.toLocaleDateString("zh-CN")},_=async()=>{try{const c=await P.get("/admin/api-keys");c.success&&(M.value=c.data)}catch(c){console.error("Failed to load API keys:",c)}},Z=c=>{if(!c||!c.host||!c.port)return null;let l=`${c.type}://${c.host}:${c.port}`;if(c.username){const o=c.username.length>2?c.username[0]+"***"+c.username[c.username.length-1]:"***",h=c.password?"****":"";l=`${c.type}://${o}:${h}@${c.host}:${c.port}`}return l},ae=(c,l)=>{if(!c||!l)return"--";const o=new Date(c),h=new Date(l),G=o.getHours().toString().padStart(2,"0"),B=o.getMinutes().toString().padStart(2,"0"),E=h.getHours().toString().padStart(2,"0"),n=h.getMinutes().toString().padStart(2,"0");return`${G}:${B} - ${E}:${n}`},ne=c=>{if(!c||c<=0)return"已结束";const l=Math.floor(c/60),o=c%60;return l>0?`${l}小时${o}分钟`:`${o}分钟`},ee=()=>{O.value=!0},te=c=>{Q.value=c,R.value=!0},f=async c=>{const l=M.value.filter(h=>h.claudeAccountId===c.id||h.geminiAccountId===c.id).length;if(l>0){S(`无法删除此账号,有 ${l} 个API Key绑定到此账号,请先解绑所有API Key`,"error");return}if(await w("删除账户",`确定要删除账户 "${c.name}" 吗? - -此操作不可恢复。`,"删除","取消"))try{let h;c.platform==="claude"?h=`/admin/claude-accounts/${c.id}`:c.platform==="claude-console"?h=`/admin/claude-console-accounts/${c.id}`:h=`/admin/gemini-accounts/${c.id}`;const G=await P.delete(h);G.success?(S("账户已删除","success"),U()):S(G.message||"删除失败","error")}catch{S("删除失败","error")}},m=async c=>{if(!c.isRefreshing)try{c.isRefreshing=!0;const l=await P.post(`/admin/claude-accounts/${c.id}/refresh`);l.success?(S("Token刷新成功","success"),U()):S(l.message||"Token刷新失败","error")}catch{S("Token刷新失败","error")}finally{c.isRefreshing=!1}},k=async c=>{if(!c.isTogglingSchedulable)try{c.isTogglingSchedulable=!0;let l;if(c.platform==="claude")l=`/admin/claude-accounts/${c.id}/toggle-schedulable`;else if(c.platform==="claude-console")l=`/admin/claude-console-accounts/${c.id}/toggle-schedulable`;else{S("Gemini账户暂不支持调度控制","warning");return}const o=await P.put(l);o.success?(c.schedulable=o.schedulable,S(o.schedulable?"已启用调度":"已禁用调度","success")):S(o.message||"操作失败","error")}catch{S("切换调度状态失败","error")}finally{c.isTogglingSchedulable=!1}},H=()=>{O.value=!1,S("账户创建成功","success"),U()},re=()=>{R.value=!1,S("账户更新成功","success"),U()};return z(A,c=>{const l={name:"name",dailyTokens:"dailyTokens",dailyRequests:"dailyRequests",totalTokens:"totalTokens",lastUsed:"lastUsed"};l[c]&&r(l[c])}),Se(()=>{U(),_()}),(c,l)=>(i(),u("div",Hs,[e("div",Fs,[e("div",_s,[l[11]||(l[11]=e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900 mb-2"}," 账户管理 "),e("p",{class:"text-gray-600"}," 管理您的 Claude 和 Gemini 账户及代理配置 ")],-1)),e("div",Js,[g(e("select",{"onUpdate:modelValue":l[0]||(l[0]=o=>A.value=o),class:"form-input px-3 py-2 text-sm",onChange:l[1]||(l[1]=o=>r())},l[9]||(l[9]=[se('',5)]),544),[[he,A.value]]),e("button",{class:"btn btn-success px-6 py-3 flex items-center gap-2",onClick:je(ee,["stop"])},l[10]||(l[10]=[e("i",{class:"fas fa-plus"},null,-1),b("添加账户 ",-1)]))])]),T.value?(i(),u("div",Ys,l[12]||(l[12]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载账户... ",-1)]))):s.value.length===0?(i(),u("div",Qs,l[13]||(l[13]=[e("div",{class:"w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-gray-400 text-xl"})],-1),e("p",{class:"text-gray-500 text-lg"}," 暂无账户 ",-1),e("p",{class:"text-gray-400 text-sm mt-2"}," 点击上方按钮添加您的第一个账户 ",-1)]))):(i(),u("div",Xs,[e("table",Zs,[e("thead",el,[e("tr",null,[e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[2]||(l[2]=o=>r("name"))},[l[14]||(l[14]=b(" 名称 ",-1)),y.value==="name"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",tl))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[3]||(l[3]=o=>r("platform"))},[l[15]||(l[15]=b(" 平台 ",-1)),y.value==="platform"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",sl))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[4]||(l[4]=o=>r("accountType"))},[l[16]||(l[16]=b(" 类型 ",-1)),y.value==="accountType"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",ll))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[5]||(l[5]=o=>r("status"))},[l[17]||(l[17]=b(" 状态 ",-1)),y.value==="status"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",ol))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[6]||(l[6]=o=>r("priority"))},[l[18]||(l[18]=b(" 优先级 ",-1)),y.value==="priority"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",al))]),l[19]||(l[19]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 代理 ",-1)),l[20]||(l[20]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 今日使用 ",-1)),l[21]||(l[21]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 会话窗口 ",-1)),l[22]||(l[22]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 最后使用 ",-1)),l[23]||(l[23]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 操作 ",-1))])]),e("tbody",nl,[(i(!0),u(de,null,pe(s.value,o=>(i(),u("tr",{key:o.id,class:"table-row"},[e("td",rl,[e("div",il,[l[26]||(l[26]=e("div",{class:"w-8 h-8 bg-gradient-to-br from-green-500 to-green-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-user-circle text-white text-xs"})],-1)),e("div",null,[e("div",ul,[e("div",dl,I(o.name),1),o.accountType==="dedicated"?(i(),u("span",pl,l[24]||(l[24]=[e("i",{class:"fas fa-lock mr-1"},null,-1),b("专属 ",-1)]))):(i(),u("span",cl,l[25]||(l[25]=[e("i",{class:"fas fa-share-alt mr-1"},null,-1),b("共享 ",-1)])))]),e("div",ml,I(o.id),1)])])]),e("td",fl,[o.platform==="gemini"?(i(),u("span",xl,l[27]||(l[27]=[e("i",{class:"fas fa-robot mr-1"},null,-1),b("Gemini ",-1)]))):o.platform==="claude-console"?(i(),u("span",vl,l[28]||(l[28]=[e("i",{class:"fas fa-terminal mr-1"},null,-1),b("Claude Console ",-1)]))):(i(),u("span",yl,l[29]||(l[29]=[e("i",{class:"fas fa-brain mr-1"},null,-1),b("Claude ",-1)])))]),e("td",gl,[o.platform==="claude-console"?(i(),u("span",bl,l[30]||(l[30]=[e("i",{class:"fas fa-key mr-1"},null,-1),b("API Key ",-1)]))):o.scopes&&o.scopes.length>0?(i(),u("span",wl,l[31]||(l[31]=[e("i",{class:"fas fa-lock mr-1"},null,-1),b("OAuth ",-1)]))):(i(),u("span",kl,l[32]||(l[32]=[e("i",{class:"fas fa-key mr-1"},null,-1),b("传统 ",-1)])))]),e("td",hl,[e("div",$l,[e("span",{class:L(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",o.status==="blocked"?"bg-orange-100 text-orange-800":o.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[e("div",{class:L(["w-2 h-2 rounded-full mr-2",o.status==="blocked"?"bg-orange-500":o.isActive?"bg-green-500":"bg-red-500"])},null,2),b(" "+I(o.status==="blocked"?"已封锁":o.isActive?"正常":"异常"),1)],2),o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?(i(),u("span",Cl,[l[33]||(l[33]=e("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),b(" 限流中 ("+I(o.rateLimitStatus.minutesRemaining)+"分钟) ",1)])):$("",!0),o.schedulable===!1?(i(),u("span",Tl,l[34]||(l[34]=[e("i",{class:"fas fa-pause-circle mr-1"},null,-1),b(" 不可调度 ",-1)]))):$("",!0),o.status==="blocked"&&o.errorMessage?(i(),u("span",{key:2,class:"text-xs text-gray-500 mt-1 max-w-xs truncate",title:o.errorMessage},I(o.errorMessage),9,Al)):$("",!0),o.accountType==="dedicated"?(i(),u("span",Ul," 绑定: "+I(o.boundApiKeysCount||0)+" 个API Key ",1)):$("",!0)])]),e("td",Vl,[o.platform==="claude"||o.platform==="claude-console"?(i(),u("div",Il,[e("div",Sl,[e("div",{class:"bg-gradient-to-r from-green-500 to-blue-600 h-2 rounded-full transition-all duration-300",style:ge({width:101-(o.priority||50)+"%"})},null,4)]),e("span",jl,I(o.priority||50),1)])):(i(),u("div",Ml,l[35]||(l[35]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Kl,[Z(o.proxy)?(i(),u("div",Pl,I(Z(o.proxy)),1)):(i(),u("div",Rl," 无代理 "))]),e("td",Gl,[o.usage&&o.usage.daily?(i(),u("div",Ll,[e("div",Dl,[l[36]||(l[36]=e("div",{class:"w-2 h-2 bg-green-500 rounded-full"},null,-1)),e("span",Ol,I(o.usage.daily.requests||0)+" 次",1)]),e("div",El,[l[37]||(l[37]=e("div",{class:"w-2 h-2 bg-blue-500 rounded-full"},null,-1)),e("span",zl,I(v(o.usage.daily.allTokens||0))+" tokens",1)]),o.usage.averages&&o.usage.averages.rpm>0?(i(),u("div",Wl," 平均 "+I(o.usage.averages.rpm.toFixed(2))+" RPM ",1)):$("",!0)])):(i(),u("div",ql," 暂无数据 "))]),e("td",Nl,[o.platform==="claude"&&o.sessionWindow&&o.sessionWindow.hasActiveWindow?(i(),u("div",Bl,[e("div",Hl,[e("div",Fl,[e("div",{class:"bg-gradient-to-r from-blue-500 to-indigo-600 h-2 rounded-full transition-all duration-300",style:ge({width:o.sessionWindow.progress+"%"})},null,4)]),e("span",_l,I(o.sessionWindow.progress)+"% ",1)]),e("div",Jl,[e("div",null,I(ae(o.sessionWindow.windowStart,o.sessionWindow.windowEnd)),1),o.sessionWindow.remainingTime>0?(i(),u("div",Yl," 剩余 "+I(ne(o.sessionWindow.remainingTime)),1)):$("",!0)])])):o.platform==="claude"?(i(),u("div",Ql,l[38]||(l[38]=[e("i",{class:"fas fa-minus"},null,-1)]))):(i(),u("div",Xl,l[39]||(l[39]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Zl,I(J(o.lastUsedAt)),1),e("td",eo,[e("div",to,[o.platform==="claude"&&o.scopes?(i(),u("button",{key:0,disabled:o.isRefreshing,class:L(["px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",o.isRefreshing?"bg-gray-100 text-gray-400 cursor-not-allowed":"bg-blue-100 text-blue-700 hover:bg-blue-200"]),title:o.isRefreshing?"刷新中...":"刷新Token",onClick:h=>m(o)},[e("i",{class:L(["fas fa-sync-alt",o.isRefreshing?"animate-spin":""])},null,2)],10,so)):$("",!0),e("button",{disabled:o.isTogglingSchedulable,class:L(["px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",o.isTogglingSchedulable?"bg-gray-100 text-gray-400 cursor-not-allowed":o.schedulable?"bg-green-100 text-green-700 hover:bg-green-200":"bg-gray-100 text-gray-700 hover:bg-gray-200"]),title:o.schedulable?"点击禁用调度":"点击启用调度",onClick:h=>k(o)},[e("i",{class:L(["fas",o.schedulable?"fa-toggle-on":"fa-toggle-off"])},null,2)],10,lo),e("button",{class:"px-3 py-1.5 bg-blue-100 text-blue-700 rounded-lg text-xs font-medium hover:bg-blue-200 transition-colors",onClick:h=>te(o)},l[40]||(l[40]=[e("i",{class:"fas fa-edit"},null,-1)]),8,oo),e("button",{class:"px-3 py-1.5 bg-red-100 text-red-700 rounded-lg text-xs font-medium hover:bg-red-200 transition-colors",onClick:h=>f(o)},l[41]||(l[41]=[e("i",{class:"fas fa-trash"},null,-1)]),8,ao)])])]))),128))])])]))]),O.value?(i(),oe(ke,{key:0,onClose:l[7]||(l[7]=o=>O.value=!1),onSuccess:H})):$("",!0),R.value?(i(),oe(ke,{key:1,account:Q.value,onClose:l[8]||(l[8]=o=>R.value=!1),onSuccess:re},null,8,["account"])):$("",!0),ue(Ae,{show:N(W),title:N(p).title,message:N(p).message,"confirm-text":N(p).confirmText,"cancel-text":N(p).cancelText,onConfirm:N(d),onCancel:N(K)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},mo=Me(no,[["__scopeId","data-v-981f21d9"]]);export{mo as default}; diff --git a/web/admin-spa/dist/assets/ApiKeysView-DUk0IljI.js b/web/admin-spa/dist/assets/ApiKeysView-DUk0IljI.js deleted file mode 100644 index 69576817..00000000 --- a/web/admin-spa/dist/assets/ApiKeysView-DUk0IljI.js +++ /dev/null @@ -1,9 +0,0 @@ -import{E as je}from"./element-plus-B8Fs_0jW.js";import{aR as we,r as C,c as Q,_ as me,q as pe,I as X,y as i,z as e,Y as J,K as A,x as a,L as w,O as b,aq as U,C as W,P as c,Q as T,ac as _,aa as ae,aX as H,an as te,al as se,a5 as re,R as Ue,B as qe}from"./vue-vendor-CKToUHZx.js";import{s as R}from"./toast-BvwA7Mwb.js";import{a as q,_ as ne,u as $e}from"./index-9AMT1Op2.js";import"./vendor-BDiMbLwQ.js";const xe=we("clients",{state:()=>({supportedClients:[],loading:!1,error:null}),actions:{async loadSupportedClients(){if(this.supportedClients.length>0)return this.supportedClients;this.loading=!0,this.error=null;try{const h=await q.get("/admin/supported-clients");return h.success?this.supportedClients=h.data||[]:(this.error=h.message||"加载支持的客户端失败",console.error("Failed to load supported clients:",this.error)),this.supportedClients}catch(h){return this.error=h.message||"加载支持的客户端失败",console.error("Error loading supported clients:",h),[]}finally{this.loading=!1}}}}),Ae=we("apiKeys",()=>{const h=C([]),L=C(!1),g=C(null),V=C("all"),M=C(""),f=C("asc"),I=async()=>{L.value=!0,g.value=null;try{const $=await q.get("/admin/api-keys");if($.success)h.value=$.data||[];else throw new Error($.message||"获取API Keys失败")}catch($){throw g.value=$.message,$}finally{L.value=!1}};return{apiKeys:h,loading:L,error:g,statsTimeRange:V,sortBy:M,sortOrder:f,fetchApiKeys:I,createApiKey:async $=>{L.value=!0,g.value=null;try{const K=await q.post("/admin/api-keys",$);if(K.success)return await I(),K.data;throw new Error(K.message||"创建API Key失败")}catch(K){throw g.value=K.message,K}finally{L.value=!1}},updateApiKey:async($,K)=>{L.value=!0,g.value=null;try{const x=await q.put(`/admin/api-keys/${$}`,K);if(x.success)return await I(),x;throw new Error(x.message||"更新API Key失败")}catch(x){throw g.value=x.message,x}finally{L.value=!1}},toggleApiKey:async $=>{L.value=!0,g.value=null;try{const K=await q.put(`/admin/api-keys/${$}/toggle`);if(K.success)return await I(),K;throw new Error(K.message||"切换状态失败")}catch(K){throw g.value=K.message,K}finally{L.value=!1}},renewApiKey:async($,K)=>{L.value=!0,g.value=null;try{const x=await q.put(`/admin/api-keys/${$}/renew`,K);if(x.success)return await I(),x;throw new Error(x.message||"续期失败")}catch(x){throw g.value=x.message,x}finally{L.value=!1}},deleteApiKey:async $=>{L.value=!0,g.value=null;try{const K=await q.delete(`/admin/api-keys/${$}`);if(K.success)return await I(),K;throw new Error(K.message||"删除失败")}catch(K){throw g.value=K.message,K}finally{L.value=!1}},fetchApiKeyStats:async($,K="all")=>{try{const x=await q.get(`/admin/api-keys/${$}/stats`,{params:{timeRange:K}});if(x.success)return x.stats;throw new Error(x.message||"获取统计失败")}catch(x){return console.error("获取API Key统计失败:",x),null}},fetchTags:async()=>{try{const $=await q.get("/admin/api-keys/tags");if($.success)return $.data||[];throw new Error($.message||"获取标签失败")}catch($){return console.error("获取标签失败:",$),[]}},sortApiKeys:$=>{M.value===$?f.value=f.value==="asc"?"desc":"asc":(M.value=$,f.value="asc")},reset:()=>{h.value=[],L.value=!1,g.value=null,V.value="all",M.value="",f.value="asc"}}}),Oe={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Fe={class:"modal-content w-full max-w-4xl p-6 mx-auto max-h-[90vh] flex flex-col"},We={class:"flex items-center justify-between mb-4"},Ne={key:0,class:"text-red-500 text-xs mt-1"},Ye={class:"space-y-4"},ze={key:0},Be={class:"flex flex-wrap gap-2"},He=["onClick"],Ge={key:1},Qe={class:"flex flex-wrap gap-2"},Xe=["onClick"],Je={class:"flex gap-2"},Ze=["onKeypress"],et={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},tt={class:"space-y-2"},st={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},lt={class:"space-y-2"},ot={class:"flex gap-2"},nt={key:0,class:"mt-3"},it=["min"],at={key:1,class:"text-xs text-gray-500 mt-2"},rt={class:"flex gap-4"},dt={class:"flex items-center cursor-pointer"},ut={class:"flex items-center cursor-pointer"},ct={class:"flex items-center cursor-pointer"},mt={class:"grid grid-cols-1 gap-3"},pt=["disabled"],xt={key:0,label:"Claude OAuth 账号"},gt=["value"],yt={key:1,label:"Claude Console 账号"},ft=["value"],bt=["disabled"],vt=["value"],wt={class:"flex items-center mb-2"},$t={key:0,class:"space-y-2 bg-red-50 border border-red-200 rounded-lg p-3"},At={class:"flex flex-wrap gap-1 mb-2 min-h-[24px]"},Ct=["onClick"],kt={key:0,class:"text-gray-400 text-xs"},Kt={class:"flex gap-2"},ht=["onKeydown"],It={class:"flex items-center mb-2"},Dt={key:0,class:"bg-green-50 border border-green-200 rounded-lg p-3"},Lt={class:"space-y-1"},Mt=["id","value"],St=["for"],Rt={class:"text-sm font-medium text-gray-700"},Tt={class:"text-xs text-gray-500 block"},Pt={class:"flex gap-3 pt-2"},_t=["disabled"],Et={key:0,class:"loading-spinner mr-2"},Vt={key:1,class:"fas fa-plus mr-2"},jt={__name:"CreateApiKeyModal",props:{accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(h,{emit:L}){const g=L;$e();const V=xe(),M=Ae(),f=C(!1),I=C({name:""}),P=C(""),k=C([]),O=Q(()=>k.value.filter(v=>!t.tags.includes(v))),D=C([]),t=me({name:"",description:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",expireDuration:"",customExpireDate:"",expiresAt:null,permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]});pe(async()=>{D.value=await V.loadSupportedClients(),k.value=await M.fetchTags()});const y=Q(()=>{const v=new Date;return v.setMinutes(v.getMinutes()+1),v.toISOString().slice(0,16)}),E=()=>{if(!t.expireDuration){t.expiresAt=null;return}if(t.expireDuration==="custom")return;const v=new Date,r=t.expireDuration.match(/(\d+)([dhmy])/);if(r){const[,j,le]=r,Z=parseInt(j);switch(le){case"d":v.setDate(v.getDate()+Z);break;case"h":v.setHours(v.getHours()+Z);break;case"m":v.setMonth(v.getMonth()+Z);break;case"y":v.setFullYear(v.getFullYear()+Z);break}t.expiresAt=v.toISOString()}},B=()=>{t.customExpireDate&&(t.expiresAt=new Date(t.customExpireDate).toISOString())},z=v=>new Date(v).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),$=()=>{t.modelInput&&!t.restrictedModels.includes(t.modelInput)&&(t.restrictedModels.push(t.modelInput),t.modelInput="")},K=v=>{t.restrictedModels.splice(v,1)},x=()=>{if(P.value&&P.value.trim()){const v=P.value.trim();t.tags.includes(v)||t.tags.push(v),P.value=""}},n=v=>{t.tags.includes(v)||t.tags.push(v)},u=v=>{t.tags.splice(v,1)},N=async()=>{if(I.value.name="",!t.name||!t.name.trim()){I.value.name="请输入API Key名称";return}f.value=!0;try{const v={name:t.name,description:t.description||void 0,tokenLimit:t.tokenLimit!==""&&t.tokenLimit!==null?parseInt(t.tokenLimit):null,rateLimitWindow:t.rateLimitWindow!==""&&t.rateLimitWindow!==null?parseInt(t.rateLimitWindow):null,rateLimitRequests:t.rateLimitRequests!==""&&t.rateLimitRequests!==null?parseInt(t.rateLimitRequests):null,concurrencyLimit:t.concurrencyLimit!==""&&t.concurrencyLimit!==null?parseInt(t.concurrencyLimit):0,dailyCostLimit:t.dailyCostLimit!==""&&t.dailyCostLimit!==null?parseFloat(t.dailyCostLimit):0,expiresAt:t.expiresAt||void 0,permissions:t.permissions,tags:t.tags.length>0?t.tags:void 0};t.claudeAccountId&&(t.claudeAccountId.startsWith("console:")?v.claudeConsoleAccountId=t.claudeAccountId.substring(8):v.claudeAccountId=t.claudeAccountId),t.geminiAccountId&&(v.geminiAccountId=t.geminiAccountId),v.enableModelRestriction=t.enableModelRestriction,v.restrictedModels=t.restrictedModels,v.enableClientRestriction=t.enableClientRestriction,v.allowedClients=t.allowedClients;const o=await q.post("/admin/api-keys",v);o.success?(R("API Key 创建成功","success"),g("success",o.data),g("close")):R(o.message||"创建失败","error")}catch{R("创建失败","error")}finally{f.value=!1}};return(v,o)=>(i(),X(re,{to:"body"},[e("div",Oe,[e("div",Fe,[e("div",We,[o[27]||(o[27]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-key text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 创建新的 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:o[0]||(o[0]=r=>v.$emit("close"))},o[26]||(o[26]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("form",{class:"space-y-4 modal-scroll-content custom-scrollbar flex-1",onSubmit:J(N,["prevent"])},[e("div",null,[o[28]||(o[28]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[b("名称 "),e("span",{class:"text-red-500"},"*")],-1)),A(e("input",{"onUpdate:modelValue":o[1]||(o[1]=r=>t.name=r),type:"text",required:"",class:W(["form-input w-full",{"border-red-500":I.value.name}]),placeholder:"为您的 API Key 取一个名称",onInput:o[2]||(o[2]=r=>I.value.name="")},null,34),[[U,t.name]]),I.value.name?(i(),a("p",Ne,c(I.value.name),1)):w("",!0)]),e("div",null,[o[36]||(o[36]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"标签",-1)),e("div",Ye,[t.tags.length>0?(i(),a("div",ze,[o[30]||(o[30]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",Be,[(i(!0),a(T,null,_(t.tags,(r,j)=>(i(),a("span",{key:"selected-"+j,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[b(c(r)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:le=>u(j)},o[29]||(o[29]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,He)]))),128))])])):w("",!0),O.value.length>0?(i(),a("div",Ge,[o[32]||(o[32]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",Qe,[(i(!0),a(T,null,_(O.value,r=>(i(),a("button",{key:"available-"+r,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:j=>n(r)},[o[31]||(o[31]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),b(" "+c(r),1)],8,Xe))),128))])])):w("",!0),e("div",null,[o[34]||(o[34]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",Je,[A(e("input",{"onUpdate:modelValue":o[3]||(o[3]=r=>P.value=r),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ae(J(x,["prevent"]),["enter"])},null,40,Ze),[[U,P.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:x},o[33]||(o[33]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),o[35]||(o[35]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",et,[o[44]||(o[44]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",tt,[e("div",st,[e("div",null,[o[37]||(o[37]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),A(e("input",{"onUpdate:modelValue":o[4]||(o[4]=r=>t.rateLimitWindow=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.rateLimitWindow]]),o[38]||(o[38]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[o[39]||(o[39]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),A(e("input",{"onUpdate:modelValue":o[5]||(o[5]=r=>t.rateLimitRequests=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.rateLimitRequests]]),o[40]||(o[40]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[o[41]||(o[41]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),A(e("input",{"onUpdate:modelValue":o[6]||(o[6]=r=>t.tokenLimit=r),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.tokenLimit]]),o[42]||(o[42]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),o[43]||(o[43]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),b(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),b(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),b(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[o[46]||(o[46]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"每日费用限制 (美元)",-1)),e("div",lt,[e("div",ot,[e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[7]||(o[7]=r=>t.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[8]||(o[8]=r=>t.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[9]||(o[9]=r=>t.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[10]||(o[10]=r=>t.dailyCostLimit="")}," 自定义 ")]),A(e("input",{"onUpdate:modelValue":o[11]||(o[11]=r=>t.dailyCostLimit=r),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[U,t.dailyCostLimit]]),o[45]||(o[45]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[o[47]||(o[47]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"并发限制 (可选)",-1)),A(e("input",{"onUpdate:modelValue":o[12]||(o[12]=r=>t.concurrencyLimit=r),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[U,t.concurrencyLimit]]),o[48]||(o[48]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数,0 或留空表示无限制 ",-1))]),e("div",null,[o[49]||(o[49]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"备注 (可选)",-1)),A(e("textarea",{"onUpdate:modelValue":o[13]||(o[13]=r=>t.description=r),rows:"2",class:"form-input w-full resize-none text-sm",placeholder:"描述此 API Key 的用途..."},null,512),[[U,t.description]])]),e("div",null,[o[51]||(o[51]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"有效期限",-1)),A(e("select",{"onUpdate:modelValue":o[14]||(o[14]=r=>t.expireDuration=r),class:"form-input w-full",onChange:E},o[50]||(o[50]=[e("option",{value:""}," 永不过期 ",-1),e("option",{value:"1d"}," 1 天 ",-1),e("option",{value:"7d"}," 7 天 ",-1),e("option",{value:"30d"}," 30 天 ",-1),e("option",{value:"90d"}," 90 天 ",-1),e("option",{value:"180d"}," 180 天 ",-1),e("option",{value:"365d"}," 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1)]),544),[[H,t.expireDuration]]),t.expireDuration==="custom"?(i(),a("div",nt,[A(e("input",{"onUpdate:modelValue":o[15]||(o[15]=r=>t.customExpireDate=r),type:"datetime-local",class:"form-input w-full",min:y.value,onChange:B},null,40,it),[[U,t.customExpireDate]])])):w("",!0),t.expiresAt?(i(),a("p",at," 将于 "+c(z(t.expiresAt))+" 过期 ",1)):w("",!0)]),e("div",null,[o[55]||(o[55]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"服务权限",-1)),e("div",rt,[e("label",dt,[A(e("input",{"onUpdate:modelValue":o[16]||(o[16]=r=>t.permissions=r),type:"radio",value:"all",class:"mr-2"},null,512),[[te,t.permissions]]),o[52]||(o[52]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",ut,[A(e("input",{"onUpdate:modelValue":o[17]||(o[17]=r=>t.permissions=r),type:"radio",value:"claude",class:"mr-2"},null,512),[[te,t.permissions]]),o[53]||(o[53]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",ct,[A(e("input",{"onUpdate:modelValue":o[18]||(o[18]=r=>t.permissions=r),type:"radio",value:"gemini",class:"mr-2"},null,512),[[te,t.permissions]]),o[54]||(o[54]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),o[56]||(o[56]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[o[61]||(o[61]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"专属账号绑定 (可选)",-1)),e("div",mt,[e("div",null,[o[58]||(o[58]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),A(e("select",{"onUpdate:modelValue":o[19]||(o[19]=r=>t.claudeAccountId=r),class:"form-input w-full",disabled:t.permissions==="gemini"},[o[57]||(o[57]=e("option",{value:""}," 使用共享账号池 ",-1)),h.accounts.claude.filter(r=>r.isDedicated&&r.platform==="claude-oauth").length>0?(i(),a("optgroup",xt,[(i(!0),a(T,null,_(h.accounts.claude.filter(r=>r.isDedicated&&r.platform==="claude-oauth"),r=>(i(),a("option",{key:r.id,value:r.id},c(r.name)+" ("+c(r.status==="active"?"正常":"异常")+") ",9,gt))),128))])):w("",!0),h.accounts.claude.filter(r=>r.isDedicated&&r.platform==="claude-console").length>0?(i(),a("optgroup",yt,[(i(!0),a(T,null,_(h.accounts.claude.filter(r=>r.isDedicated&&r.platform==="claude-console"),r=>(i(),a("option",{key:r.id,value:`console:${r.id}`},c(r.name)+" ("+c(r.status==="active"?"正常":"异常")+") ",9,ft))),128))])):w("",!0)],8,pt),[[H,t.claudeAccountId]])]),e("div",null,[o[60]||(o[60]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),A(e("select",{"onUpdate:modelValue":o[20]||(o[20]=r=>t.geminiAccountId=r),class:"form-input w-full",disabled:t.permissions==="claude"},[o[59]||(o[59]=e("option",{value:""}," 使用共享账号池 ",-1)),(i(!0),a(T,null,_(h.accounts.gemini.filter(r=>r.isDedicated),r=>(i(),a("option",{key:r.id,value:r.id},c(r.name)+" ("+c(r.status==="active"?"正常":"异常")+") ",9,vt))),128))],8,bt),[[H,t.geminiAccountId]])])]),o[62]||(o[62]=e("p",{class:"text-xs text-gray-500 mt-2"}," 选择专属账号后,此API Key将只使用该账号,不选择则使用共享账号池 ",-1))]),e("div",null,[e("div",wt,[A(e("input",{id:"enableModelRestriction","onUpdate:modelValue":o[21]||(o[21]=r=>t.enableModelRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[se,t.enableModelRestriction]]),o[63]||(o[63]=e("label",{for:"enableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),t.enableModelRestriction?(i(),a("div",$t,[e("div",null,[o[66]||(o[66]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"限制的模型列表",-1)),e("div",At,[(i(!0),a(T,null,_(t.restrictedModels,(r,j)=>(i(),a("span",{key:j,class:"inline-flex items-center px-2 py-1 rounded-full text-xs bg-red-100 text-red-800"},[b(c(r)+" ",1),e("button",{type:"button",class:"ml-1 text-red-600 hover:text-red-800",onClick:le=>K(j)},o[64]||(o[64]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,Ct)]))),128)),t.restrictedModels.length===0?(i(),a("span",kt," 暂无限制的模型 ")):w("",!0)]),e("div",Kt,[A(e("input",{"onUpdate:modelValue":o[22]||(o[22]=r=>t.modelInput=r),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1 text-sm",onKeydown:ae(J($,["prevent"]),["enter"])},null,40,ht),[[U,t.modelInput]]),e("button",{type:"button",class:"px-3 py-1.5 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors text-sm",onClick:$},o[65]||(o[65]=[e("i",{class:"fas fa-plus"},null,-1)]))]),o[67]||(o[67]=e("p",{class:"text-xs text-gray-500 mt-1"}," 例如:claude-opus-4-20250514 ",-1))])])):w("",!0)]),e("div",null,[e("div",It,[A(e("input",{id:"enableClientRestriction","onUpdate:modelValue":o[23]||(o[23]=r=>t.enableClientRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[se,t.enableClientRestriction]]),o[68]||(o[68]=e("label",{for:"enableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),t.enableClientRestriction?(i(),a("div",Dt,[e("div",null,[o[69]||(o[69]=e("label",{class:"block text-xs font-medium text-gray-700 mb-2"},"允许的客户端",-1)),e("div",Lt,[(i(!0),a(T,null,_(D.value,r=>(i(),a("div",{key:r.id,class:"flex items-start"},[A(e("input",{id:`client_${r.id}`,"onUpdate:modelValue":o[24]||(o[24]=j=>t.allowedClients=j),type:"checkbox",value:r.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,Mt),[[se,t.allowedClients]]),e("label",{for:`client_${r.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",Rt,c(r.name),1),e("span",Tt,c(r.description),1)],8,St)]))),128))])])])):w("",!0)]),e("div",Pt,[e("button",{type:"button",class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-lg font-semibold hover:bg-gray-200 transition-colors text-sm",onClick:o[25]||(o[25]=r=>v.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:f.value,class:"btn btn-primary flex-1 py-2.5 px-4 font-semibold text-sm"},[f.value?(i(),a("div",Et)):(i(),a("i",Vt)),b(" "+c(f.value?"创建中...":"创建"),1)],8,_t)])],32)])])]))}},Ut=ne(jt,[["__scopeId","data-v-6f63995d"]]),qt={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Ot={class:"modal-content w-full max-w-4xl p-8 mx-auto max-h-[90vh] flex flex-col"},Ft={class:"flex items-center justify-between mb-6"},Wt=["value"],Nt={class:"space-y-4"},Yt={key:0},zt={class:"flex flex-wrap gap-2"},Bt=["onClick"],Ht={key:1},Gt={class:"flex flex-wrap gap-2"},Qt=["onClick"],Xt={class:"flex gap-2"},Jt=["onKeypress"],Zt={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},es={class:"space-y-2"},ts={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},ss={class:"space-y-3"},ls={class:"flex gap-2"},os={class:"flex gap-4"},ns={class:"flex items-center cursor-pointer"},is={class:"flex items-center cursor-pointer"},as={class:"flex items-center cursor-pointer"},rs={class:"grid grid-cols-1 gap-3"},ds=["disabled"],us={key:0,label:"Claude OAuth 账号"},cs=["value"],ms={key:1,label:"Claude Console 账号"},ps=["value"],xs=["disabled"],gs=["value"],ys={class:"flex items-center mb-3"},fs={key:0,class:"space-y-3"},bs={class:"flex flex-wrap gap-2 mb-3 min-h-[32px] p-2 bg-gray-50 rounded-lg border border-gray-200"},vs=["onClick"],ws={key:0,class:"text-gray-400 text-sm"},$s={class:"flex gap-2"},As=["onKeydown"],Cs={class:"flex items-center mb-3"},ks={key:0,class:"space-y-3"},Ks={class:"space-y-2"},hs=["id","value"],Is=["for"],Ds={class:"text-sm font-medium text-gray-700"},Ls={class:"text-xs text-gray-500 block"},Ms={class:"flex gap-3 pt-4"},Ss=["disabled"],Rs={key:0,class:"loading-spinner mr-2"},Ts={key:1,class:"fas fa-save mr-2"},Ps={__name:"EditApiKeyModal",props:{apiKey:{type:Object,required:!0},accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(h,{emit:L}){const g=h,V=L,M=xe(),f=Ae(),I=C(!1),P=C([]),k=C(""),O=C([]),D=Q(()=>O.value.filter(x=>!t.tags.includes(x))),t=me({name:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]}),y=()=>{t.modelInput&&!t.restrictedModels.includes(t.modelInput)&&(t.restrictedModels.push(t.modelInput),t.modelInput="")},E=x=>{t.restrictedModels.splice(x,1)},B=()=>{if(k.value&&k.value.trim()){const x=k.value.trim();t.tags.includes(x)||t.tags.push(x),k.value=""}},z=x=>{t.tags.includes(x)||t.tags.push(x)},$=x=>{t.tags.splice(x,1)},K=async()=>{I.value=!0;try{const x={tokenLimit:t.tokenLimit!==""&&t.tokenLimit!==null?parseInt(t.tokenLimit):0,rateLimitWindow:t.rateLimitWindow!==""&&t.rateLimitWindow!==null?parseInt(t.rateLimitWindow):0,rateLimitRequests:t.rateLimitRequests!==""&&t.rateLimitRequests!==null?parseInt(t.rateLimitRequests):0,concurrencyLimit:t.concurrencyLimit!==""&&t.concurrencyLimit!==null?parseInt(t.concurrencyLimit):0,dailyCostLimit:t.dailyCostLimit!==""&&t.dailyCostLimit!==null?parseFloat(t.dailyCostLimit):0,permissions:t.permissions,tags:t.tags};x.enableModelRestriction=t.enableModelRestriction,x.restrictedModels=t.restrictedModels,x.enableClientRestriction=t.enableClientRestriction,x.allowedClients=t.allowedClients,t.claudeAccountId?t.claudeAccountId.startsWith("console:")?(x.claudeConsoleAccountId=t.claudeAccountId.substring(8),x.claudeAccountId=null):(x.claudeAccountId=t.claudeAccountId,x.claudeConsoleAccountId=null):(x.claudeAccountId=null,x.claudeConsoleAccountId=null),x.geminiAccountId=t.geminiAccountId||null;const n=await q.put(`/admin/api-keys/${g.apiKey.id}`,x);n.success?(V("success"),V("close")):R(n.message||"更新失败","error")}catch{R("更新失败","error")}finally{I.value=!1}};return pe(async()=>{P.value=await M.loadSupportedClients(),O.value=await f.fetchTags(),t.name=g.apiKey.name,t.tokenLimit=g.apiKey.tokenLimit||"",t.rateLimitWindow=g.apiKey.rateLimitWindow||"",t.rateLimitRequests=g.apiKey.rateLimitRequests||"",t.concurrencyLimit=g.apiKey.concurrencyLimit||"",t.dailyCostLimit=g.apiKey.dailyCostLimit||"",t.permissions=g.apiKey.permissions||"all",g.apiKey.claudeAccountId?t.claudeAccountId=g.apiKey.claudeAccountId:g.apiKey.claudeConsoleAccountId?t.claudeAccountId=`console:${g.apiKey.claudeConsoleAccountId}`:t.claudeAccountId="",t.geminiAccountId=g.apiKey.geminiAccountId||"",t.restrictedModels=g.apiKey.restrictedModels||[],t.allowedClients=g.apiKey.allowedClients||[],t.tags=g.apiKey.tags||[],t.enableModelRestriction=g.apiKey.enableModelRestriction||!1,t.enableClientRestriction=g.apiKey.enableClientRestriction||!1}),(x,n)=>(i(),X(re,{to:"body"},[e("div",qt,[e("div",Ot,[e("div",Ft,[n[22]||(n[22]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-edit text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 编辑 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:n[0]||(n[0]=u=>x.$emit("close"))},n[21]||(n[21]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("form",{class:"space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:J(K,["prevent"])},[e("div",null,[n[23]||(n[23]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"名称",-1)),e("input",{value:t.name,type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed"},null,8,Wt),n[24]||(n[24]=e("p",{class:"text-xs text-gray-500 mt-2"}," 名称不可修改 ",-1))]),e("div",null,[n[32]||(n[32]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"标签",-1)),e("div",Nt,[t.tags.length>0?(i(),a("div",Yt,[n[26]||(n[26]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",zt,[(i(!0),a(T,null,_(t.tags,(u,N)=>(i(),a("span",{key:"selected-"+N,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[b(c(u)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:v=>$(N)},n[25]||(n[25]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,Bt)]))),128))])])):w("",!0),D.value.length>0?(i(),a("div",Ht,[n[28]||(n[28]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",Gt,[(i(!0),a(T,null,_(D.value,u=>(i(),a("button",{key:"available-"+u,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:N=>z(u)},[n[27]||(n[27]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),b(" "+c(u),1)],8,Qt))),128))])])):w("",!0),e("div",null,[n[30]||(n[30]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",Xt,[A(e("input",{"onUpdate:modelValue":n[1]||(n[1]=u=>k.value=u),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ae(J(B,["prevent"]),["enter"])},null,40,Jt),[[U,k.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:B},n[29]||(n[29]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),n[31]||(n[31]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",Zt,[n[40]||(n[40]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",es,[e("div",ts,[e("div",null,[n[33]||(n[33]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),A(e("input",{"onUpdate:modelValue":n[2]||(n[2]=u=>t.rateLimitWindow=u),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.rateLimitWindow]]),n[34]||(n[34]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[n[35]||(n[35]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),A(e("input",{"onUpdate:modelValue":n[3]||(n[3]=u=>t.rateLimitRequests=u),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.rateLimitRequests]]),n[36]||(n[36]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[n[37]||(n[37]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),A(e("input",{"onUpdate:modelValue":n[4]||(n[4]=u=>t.tokenLimit=u),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[U,t.tokenLimit]]),n[38]||(n[38]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),n[39]||(n[39]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),b(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),b(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),b(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[n[42]||(n[42]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"每日费用限制 (美元)",-1)),e("div",ss,[e("div",ls,[e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:n[5]||(n[5]=u=>t.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:n[6]||(n[6]=u=>t.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:n[7]||(n[7]=u=>t.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:n[8]||(n[8]=u=>t.dailyCostLimit="")}," 自定义 ")]),A(e("input",{"onUpdate:modelValue":n[9]||(n[9]=u=>t.dailyCostLimit=u),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[U,t.dailyCostLimit]]),n[41]||(n[41]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[n[43]||(n[43]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"并发限制",-1)),A(e("input",{"onUpdate:modelValue":n[10]||(n[10]=u=>t.concurrencyLimit=u),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[U,t.concurrencyLimit]]),n[44]||(n[44]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数 ",-1))]),e("div",null,[n[48]||(n[48]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"服务权限",-1)),e("div",os,[e("label",ns,[A(e("input",{"onUpdate:modelValue":n[11]||(n[11]=u=>t.permissions=u),type:"radio",value:"all",class:"mr-2"},null,512),[[te,t.permissions]]),n[45]||(n[45]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",is,[A(e("input",{"onUpdate:modelValue":n[12]||(n[12]=u=>t.permissions=u),type:"radio",value:"claude",class:"mr-2"},null,512),[[te,t.permissions]]),n[46]||(n[46]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",as,[A(e("input",{"onUpdate:modelValue":n[13]||(n[13]=u=>t.permissions=u),type:"radio",value:"gemini",class:"mr-2"},null,512),[[te,t.permissions]]),n[47]||(n[47]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),n[49]||(n[49]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[n[54]||(n[54]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"专属账号绑定",-1)),e("div",rs,[e("div",null,[n[51]||(n[51]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),A(e("select",{"onUpdate:modelValue":n[14]||(n[14]=u=>t.claudeAccountId=u),class:"form-input w-full",disabled:t.permissions==="gemini"},[n[50]||(n[50]=e("option",{value:""}," 使用共享账号池 ",-1)),h.accounts.claude.filter(u=>u.isDedicated&&u.platform==="claude-oauth").length>0?(i(),a("optgroup",us,[(i(!0),a(T,null,_(h.accounts.claude.filter(u=>u.isDedicated&&u.platform==="claude-oauth"),u=>(i(),a("option",{key:u.id,value:u.id},c(u.name)+" ("+c(u.status==="active"?"正常":"异常")+") ",9,cs))),128))])):w("",!0),h.accounts.claude.filter(u=>u.isDedicated&&u.platform==="claude-console").length>0?(i(),a("optgroup",ms,[(i(!0),a(T,null,_(h.accounts.claude.filter(u=>u.isDedicated&&u.platform==="claude-console"),u=>(i(),a("option",{key:u.id,value:`console:${u.id}`},c(u.name)+" ("+c(u.status==="active"?"正常":"异常")+") ",9,ps))),128))])):w("",!0)],8,ds),[[H,t.claudeAccountId]])]),e("div",null,[n[53]||(n[53]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),A(e("select",{"onUpdate:modelValue":n[15]||(n[15]=u=>t.geminiAccountId=u),class:"form-input w-full",disabled:t.permissions==="claude"},[n[52]||(n[52]=e("option",{value:""}," 使用共享账号池 ",-1)),(i(!0),a(T,null,_(h.accounts.gemini,u=>(i(),a("option",{key:u.id,value:u.id},c(u.name)+" ("+c(u.status==="active"?"正常":"异常")+") ",9,gs))),128))],8,xs),[[H,t.geminiAccountId]])])]),n[55]||(n[55]=e("p",{class:"text-xs text-gray-500 mt-2"}," 修改绑定账号将影响此API Key的请求路由 ",-1))]),e("div",null,[e("div",ys,[A(e("input",{id:"editEnableModelRestriction","onUpdate:modelValue":n[16]||(n[16]=u=>t.enableModelRestriction=u),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[se,t.enableModelRestriction]]),n[56]||(n[56]=e("label",{for:"editEnableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),t.enableModelRestriction?(i(),a("div",fs,[e("div",null,[n[59]||(n[59]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"限制的模型列表",-1)),e("div",bs,[(i(!0),a(T,null,_(t.restrictedModels,(u,N)=>(i(),a("span",{key:N,class:"inline-flex items-center px-3 py-1 rounded-full text-sm bg-red-100 text-red-800"},[b(c(u)+" ",1),e("button",{type:"button",class:"ml-2 text-red-600 hover:text-red-800",onClick:v=>E(N)},n[57]||(n[57]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,vs)]))),128)),t.restrictedModels.length===0?(i(),a("span",ws," 暂无限制的模型 ")):w("",!0)]),e("div",$s,[A(e("input",{"onUpdate:modelValue":n[17]||(n[17]=u=>t.modelInput=u),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1",onKeydown:ae(J(y,["prevent"]),["enter"])},null,40,As),[[U,t.modelInput]]),e("button",{type:"button",class:"px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors",onClick:y},n[58]||(n[58]=[e("i",{class:"fas fa-plus"},null,-1)]))]),n[60]||(n[60]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此API Key无法访问的模型,例如:claude-opus-4-20250514 ",-1))])])):w("",!0)]),e("div",null,[e("div",Cs,[A(e("input",{id:"editEnableClientRestriction","onUpdate:modelValue":n[18]||(n[18]=u=>t.enableClientRestriction=u),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[se,t.enableClientRestriction]]),n[61]||(n[61]=e("label",{for:"editEnableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),t.enableClientRestriction?(i(),a("div",ks,[e("div",null,[n[62]||(n[62]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"允许的客户端",-1)),n[63]||(n[63]=e("p",{class:"text-xs text-gray-500 mb-3"}," 勾选允许使用此API Key的客户端 ",-1)),e("div",Ks,[(i(!0),a(T,null,_(P.value,u=>(i(),a("div",{key:u.id,class:"flex items-start"},[A(e("input",{id:`edit_client_${u.id}`,"onUpdate:modelValue":n[19]||(n[19]=N=>t.allowedClients=N),type:"checkbox",value:u.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,hs),[[se,t.allowedClients]]),e("label",{for:`edit_client_${u.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",Ds,c(u.name),1),e("span",Ls,c(u.description),1)],8,Is)]))),128))])])])):w("",!0)]),e("div",Ms,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:n[20]||(n[20]=u=>x.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:I.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[I.value?(i(),a("div",Rs)):(i(),a("i",Ts)),b(" "+c(I.value?"保存中...":"保存修改"),1)],8,Ss)])],32)])])]))}},_s=ne(Ps,[["__scopeId","data-v-dd9249b5"]]),Es={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Vs={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},js={class:"flex items-center justify-between mb-6"},Us={class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},qs={class:"bg-blue-50 border border-blue-200 rounded-lg p-4"},Os={class:"flex items-start gap-3"},Fs={class:"text-sm text-gray-700"},Ws={class:"text-xs text-gray-600 mt-1"},Ns={key:0,class:"mt-3"},Ys=["min"],zs={key:1,class:"text-xs text-gray-500 mt-2"},Bs={class:"flex gap-3 pt-4"},Hs=["disabled"],Gs={key:0,class:"loading-spinner mr-2"},Qs={key:1,class:"fas fa-clock mr-2"},Xs={__name:"RenewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close","success"],setup(h,{emit:L}){const g=h,V=L;$e();const M=C(!1),f=me({renewDuration:"30d",customExpireDate:"",newExpiresAt:null}),I=Q(()=>{const t=new Date;return g.apiKey.expiresAt&&new Date(g.apiKey.expiresAt)>t?new Date(g.apiKey.expiresAt).toISOString().slice(0,16):(t.setMinutes(t.getMinutes()+1),t.toISOString().slice(0,16))}),P=t=>new Date(t).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),k=()=>{if(!f.renewDuration){f.newExpiresAt=null;return}if(f.renewDuration==="permanent"){f.newExpiresAt=null;return}if(f.renewDuration==="custom")return;const t=g.apiKey.expiresAt&&new Date(g.apiKey.expiresAt)>new Date?new Date(g.apiKey.expiresAt):new Date,E=f.renewDuration.match(/(\d+)([dhmy])/);if(E){const[,B,z]=E,$=parseInt(B);switch(z){case"d":t.setDate(t.getDate()+$);break;case"h":t.setHours(t.getHours()+$);break;case"m":t.setMonth(t.getMonth()+$);break;case"y":t.setFullYear(t.getFullYear()+$);break}f.newExpiresAt=t.toISOString()}},O=()=>{f.customExpireDate&&(f.newExpiresAt=new Date(f.customExpireDate).toISOString())},D=async()=>{M.value=!0;try{const t={expiresAt:f.renewDuration==="permanent"?null:f.newExpiresAt},y=await q.put(`/admin/api-keys/${g.apiKey.id}/renew`,t);y.success?(R("API Key 续期成功","success"),V("success"),V("close")):R(y.message||"续期失败","error")}catch{R("续期失败","error")}finally{M.value=!1}};return k(),(t,y)=>(i(),X(re,{to:"body"},[e("div",Es,[e("div",Vs,[e("div",js,[y[5]||(y[5]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-clock text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 续期 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:y[0]||(y[0]=E=>t.$emit("close"))},y[4]||(y[4]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("div",Us,[e("div",qs,[e("div",Os,[y[7]||(y[7]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[y[6]||(y[6]=e("h4",{class:"font-semibold text-gray-800 mb-1"}," API Key 信息 ",-1)),e("p",Fs,c(h.apiKey.name),1),e("p",Ws," 当前过期时间:"+c(h.apiKey.expiresAt?P(h.apiKey.expiresAt):"永不过期"),1)])])]),e("div",null,[y[9]||(y[9]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"续期时长",-1)),A(e("select",{"onUpdate:modelValue":y[1]||(y[1]=E=>f.renewDuration=E),class:"form-input w-full",onChange:k},y[8]||(y[8]=[e("option",{value:"7d"}," 延长 7 天 ",-1),e("option",{value:"30d"}," 延长 30 天 ",-1),e("option",{value:"90d"}," 延长 90 天 ",-1),e("option",{value:"180d"}," 延长 180 天 ",-1),e("option",{value:"365d"}," 延长 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1),e("option",{value:"permanent"}," 设为永不过期 ",-1)]),544),[[H,f.renewDuration]]),f.renewDuration==="custom"?(i(),a("div",Ns,[A(e("input",{"onUpdate:modelValue":y[2]||(y[2]=E=>f.customExpireDate=E),type:"datetime-local",class:"form-input w-full",min:I.value,onChange:O},null,40,Ys),[[U,f.customExpireDate]])])):w("",!0),f.newExpiresAt?(i(),a("p",zs," 新的过期时间:"+c(P(f.newExpiresAt)),1)):w("",!0)])]),e("div",Bs,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:y[3]||(y[3]=E=>t.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:M.value||!f.renewDuration,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:D},[M.value?(i(),a("div",Gs)):(i(),a("i",Qs)),b(" "+c(M.value?"续期中...":"确认续期"),1)],8,Hs)])])])]))}},Js=ne(Xs,[["__scopeId","data-v-0c3b1b3f"]]),Zs={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},el={class:"modal-content w-full max-w-lg p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},tl={class:"space-y-4 mb-6"},sl={class:"p-3 bg-gray-50 rounded-lg border"},ll={class:"text-gray-900 font-medium"},ol={key:0},nl={class:"p-3 bg-gray-50 rounded-lg border"},il={class:"text-gray-700"},al={class:"relative"},rl={class:"p-4 pr-14 bg-gray-900 rounded-lg border font-mono text-sm text-white break-all min-h-[60px] flex items-center"},dl={class:"absolute top-3 right-3"},ul=["title"],cl={__name:"NewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close"],setup(h,{emit:L}){const g=h,V=L,M=C(!1),f=()=>{M.value=!M.value},I=()=>{const D=g.apiKey.apiKey||g.apiKey.key||"";return D?M.value||D.length<=12?D:D.substring(0,8)+"●".repeat(Math.max(0,D.length-12))+D.substring(D.length-4):""},P=async()=>{const D=g.apiKey.apiKey||g.apiKey.key||"";if(!D){R("API Key 不存在","error");return}try{await navigator.clipboard.writeText(D),R("API Key 已复制到剪贴板","success")}catch(t){console.error("Failed to copy:",t);const y=document.createElement("textarea");y.value=D,document.body.appendChild(y),y.select();try{document.execCommand("copy"),R("API Key 已复制到剪贴板","success")}catch{R("复制失败,请手动复制","error")}finally{document.body.removeChild(y)}}},k=async()=>{window.showConfirm?await window.showConfirm("关闭提醒",`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。 - -确定要关闭吗?`,"确定关闭","取消")&&V("close"):confirm(`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。 - -确定要关闭吗?`)&&V("close")},O=async()=>{window.showConfirm?await window.showConfirm("确定要关闭吗?",`您还没有保存API Key,关闭后将无法再次查看。 - -建议您先复制API Key再关闭。`,"仍然关闭","返回复制")&&V("close"):confirm(`您还没有保存API Key,关闭后将无法再次查看。 - -确定要关闭吗?`)&&V("close")};return(D,t)=>(i(),X(re,{to:"body"},[e("div",Zs,[e("div",el,[e("div",{class:"flex items-center justify-between mb-6"},[t[1]||(t[1]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-12 h-12 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-check text-white text-lg"})]),e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900"}," API Key 创建成功 "),e("p",{class:"text-sm text-gray-600"}," 请妥善保存您的 API Key ")])],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",title:"直接关闭(不推荐)",onClick:O},t[0]||(t[0]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),t[7]||(t[7]=e("div",{class:"bg-amber-50 border-l-4 border-amber-400 p-4 mb-6"},[e("div",{class:"flex items-start"},[e("div",{class:"w-6 h-6 bg-amber-400 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5"},[e("i",{class:"fas fa-exclamation-triangle text-white text-sm"})]),e("div",{class:"ml-3"},[e("h5",{class:"font-semibold text-amber-900 mb-1"}," 重要提醒 "),e("p",{class:"text-sm text-amber-800"}," 这是您唯一能看到完整 API Key 的机会。关闭此窗口后,系统将不再显示完整的 API Key。请立即复制并妥善保存。 ")])])],-1)),e("div",tl,[e("div",null,[t[2]||(t[2]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"API Key 名称",-1)),e("div",sl,[e("span",ll,c(h.apiKey.name),1)])]),h.apiKey.description?(i(),a("div",ol,[t[3]||(t[3]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"备注",-1)),e("div",nl,[e("span",il,c(h.apiKey.description||"无描述"),1)])])):w("",!0),e("div",null,[t[4]||(t[4]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"API Key",-1)),e("div",al,[e("div",rl,c(I()),1),e("div",dl,[e("button",{type:"button",class:"btn-icon-sm hover:bg-gray-800 bg-gray-700",title:M.value?"隐藏API Key":"显示完整API Key",onClick:f},[e("i",{class:W(["fas",M.value?"fa-eye-slash":"fa-eye","text-gray-300"])},null,2)],8,ul)])]),t[5]||(t[5]=e("p",{class:"text-xs text-gray-500 mt-2"}," 点击眼睛图标切换显示模式,使用下方按钮复制完整 API Key ",-1))])]),e("div",{class:"flex gap-3"},[e("button",{class:"flex-1 btn btn-primary py-3 px-6 font-semibold flex items-center justify-center gap-2",onClick:P},t[6]||(t[6]=[e("i",{class:"fas fa-copy"},null,-1),b(" 复制 API Key ",-1)])),e("button",{class:"px-6 py-3 bg-gray-200 text-gray-800 rounded-xl font-semibold hover:bg-gray-300 transition-colors border border-gray-300",onClick:k}," 我已保存 ")])])])]))}},ml=ne(cl,[["__scopeId","data-v-2c02f1f7"]]),pl={class:"tab-content"},xl={class:"card p-6"},gl={class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},yl={class:"flex items-center gap-3"},fl=["value"],bl={key:0,class:"text-center py-12"},vl={key:1,class:"text-center py-12"},wl={key:2,class:"table-container"},$l={class:"min-w-full"},Al={class:"bg-gray-50/80 backdrop-blur-sm"},Cl={key:1,class:"fas fa-sort ml-1 text-gray-400"},kl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Kl={class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"},hl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Il={key:1,class:"fas fa-sort ml-1 text-gray-400"},Dl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Ll={class:"divide-y divide-gray-200/50"},Ml={class:"table-row"},Sl={class:"px-6 py-4 whitespace-nowrap"},Rl={class:"flex items-center"},Tl={class:"text-sm font-semibold text-gray-900"},Pl={class:"text-xs text-gray-500"},_l={class:"text-xs text-gray-500 mt-1"},El={key:0},Vl={key:1},jl={class:"px-6 py-4"},Ul={class:"flex flex-wrap gap-1"},ql={key:0,class:"text-xs text-gray-400"},Ol={class:"px-6 py-4 whitespace-nowrap"},Fl={class:"text-sm font-mono text-gray-600 bg-gray-50 px-3 py-1 rounded-lg"},Wl={class:"px-6 py-4 whitespace-nowrap"},Nl={class:"px-6 py-4"},Yl={class:"space-y-1"},zl={class:"flex justify-between text-sm"},Bl={class:"font-medium text-gray-900"},Hl={class:"flex justify-between text-sm"},Gl={class:"font-medium text-gray-900"},Ql={class:"flex justify-between text-sm"},Xl={class:"font-medium text-green-600"},Jl={key:0,class:"flex justify-between text-sm"},Zl={class:"flex justify-between text-sm"},eo={class:"font-medium text-purple-600"},to={class:"flex justify-between text-sm"},so={key:0,class:"text-xs text-gray-500"},lo={key:1,class:"flex justify-between text-sm"},oo={class:"font-medium text-indigo-600"},no={key:2,class:"flex justify-between text-sm"},io={class:"font-medium text-indigo-600"},ao={class:"flex justify-between text-xs text-gray-500"},ro={key:3,class:"flex justify-between text-xs text-orange-500"},uo={class:"flex justify-between text-xs text-blue-600"},co={class:"pt-1 border-t border-gray-100"},mo={class:"flex justify-between text-xs text-green-600"},po={class:"pt-2"},xo=["onClick"],go={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-500"},yo={class:"px-6 py-4 whitespace-nowrap text-sm"},fo={key:0},bo={key:0,class:"text-red-600"},vo={key:1,class:"text-orange-600"},wo={key:2,class:"text-gray-600"},$o={key:1,class:"text-gray-400"},Ao={class:"px-6 py-4 whitespace-nowrap text-sm"},Co={class:"flex gap-2"},ko=["onClick"],Ko=["onClick"],ho=["onClick"],Io=["onClick"],Do={key:0},Lo={colspan:"7",class:"px-6 py-4 bg-gray-50"},Mo={key:0,class:"text-center py-4"},So={class:"space-y-4"},Ro={class:"flex items-center justify-between mb-4"},To={class:"flex items-center gap-2"},Po={key:0,class:"text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded-full"},_o={class:"flex gap-1 items-center"},Eo={class:"flex gap-1 bg-gray-100 rounded p-1"},Vo=["onClick"],jo={key:0,class:"text-center py-8"},Uo={class:"flex items-center justify-center gap-2 mb-3"},qo=["onClick"],Oo={key:1,class:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"},Fo={class:"flex justify-between items-start mb-3"},Wo={class:"flex-1"},No={class:"text-sm font-semibold text-gray-800 block mb-1"},Yo={class:"text-xs text-gray-500 bg-blue-50 px-2 py-1 rounded-full"},zo={class:"space-y-2 mb-3"},Bo={class:"flex justify-between items-center text-sm"},Ho={class:"font-semibold text-gray-900"},Go={class:"flex justify-between items-center text-sm"},Qo={class:"font-semibold text-green-600"},Xo={class:"pt-2 mt-2 border-t border-gray-100"},Jo={class:"flex justify-between items-center text-xs text-gray-500"},Zo={class:"font-medium"},en={class:"flex justify-between items-center text-xs text-gray-500"},tn={class:"font-medium"},sn={key:0,class:"flex justify-between items-center text-xs text-purple-600"},ln={class:"font-medium"},on={key:1,class:"flex justify-between items-center text-xs text-purple-600"},nn={class:"font-medium"},an={class:"w-full bg-gray-200 rounded-full h-2 mt-3"},rn={class:"text-right mt-1"},dn={class:"text-xs font-medium text-indigo-600"},un={key:2,class:"mt-4 p-3 bg-gradient-to-r from-indigo-50 to-purple-50 rounded-lg border border-indigo-100"},cn={class:"flex items-center justify-between text-sm"},mn={class:"flex gap-4 text-xs"},pn={class:"text-gray-600"},xn={class:"font-semibold text-gray-800"},gn={class:"text-gray-600"},yn={class:"font-semibold text-gray-800"},fn={key:3,class:"mt-6 flex flex-col sm:flex-row justify-between items-center gap-4"},bn={class:"flex items-center gap-3"},vn={class:"text-sm text-gray-600"},wn={class:"flex items-center gap-2"},$n=["value"],An={class:"flex items-center gap-2"},Cn=["disabled"],kn={class:"flex items-center gap-1"},Kn={key:1,class:"px-2 text-gray-500"},hn=["onClick"],In={key:2,class:"px-2 text-gray-500"},Dn=["disabled"],Ln={__name:"ApiKeysView",setup(h){const L=xe(),g=C([]),V=C(!1),M=C("today"),f=C(""),I=C("asc"),P=C({}),k=C({}),O=C({}),D=C([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),t=C({claude:[],gemini:[]}),y=C(1),E=C(10),B=[5,10,20,50,100],z=C(""),$=C([]),K=C(!1),x=C(!1),n=C(!1),u=C(!1),N=C(null),v=C(null),o=C(null),r=Q(()=>{let d=g.value;return z.value&&(d=g.value.filter(p=>p.tags&&p.tags.includes(z.value))),f.value?[...d].sort((p,l)=>{let m=p[f.value],S=l[f.value];return f.value==="status"?(m=p.isActive?1:0,S=l.isActive?1:0):f.value==="cost"?(m=parseFloat(de(p.usage).replace("$","")),S=parseFloat(de(l.usage).replace("$",""))):(f.value==="createdAt"||f.value==="expiresAt")&&(m=m?new Date(m).getTime():0,S=S?new Date(S).getTime():0),mS?I.value==="asc"?1:-1:0}):d}),j=Q(()=>Math.ceil(r.value.length/E.value)),le=Q(()=>{const d=(y.value-1)*E.value,s=d+E.value;return r.value.slice(d,s)}),Z=Q(()=>{const d=[];let p=Math.max(1,y.value-Math.floor(2.5)),l=Math.min(j.value,p+5-1);l-p<4&&(p=Math.max(1,l-5+1));for(let m=p;m<=l;m++)d.push(m);return d}),Ce=async()=>{var d,s;try{const[p,l,m]=await Promise.all([q.get("/admin/claude-accounts"),q.get("/admin/claude-console-accounts"),q.get("/admin/gemini-accounts")]),S=[];p.success&&((d=p.data)==null||d.forEach(Y=>{S.push({...Y,platform:"claude-oauth",isDedicated:Y.accountType==="dedicated"})})),l.success&&((s=l.data)==null||s.forEach(Y=>{S.push({...Y,platform:"claude-console",isDedicated:Y.accountType==="dedicated"})})),t.value.claude=S,m.success&&(t.value.gemini=(m.data||[]).map(Y=>({...Y,isDedicated:Y.accountType==="dedicated"})))}catch(p){console.error("加载账户列表失败:",p)}},ee=async()=>{V.value=!0;try{const d=await q.get(`/admin/api-keys?timeRange=${M.value}`);if(d.success){g.value=d.data||[];const s=new Set;g.value.forEach(p=>{p.tags&&Array.isArray(p.tags)&&p.tags.forEach(l=>s.add(l))}),$.value=Array.from(s).sort(),y.value=1}}catch{R("加载 API Keys 失败","error")}finally{V.value=!1}},oe=d=>{f.value===d?I.value=I.value==="asc"?"desc":"asc":(f.value=d,I.value="asc"),y.value=1},F=d=>!d&&d!==0?"0":d.toLocaleString("zh-CN"),de=d=>!d||!d.total?"$0.0000":`$${(d.total.cost||0).toFixed(4)}`,ke=(d,s)=>{if(d){const p=t.value.claude.find(l=>l.id===d);return p?p.name:`账户-${d.substring(0,8)}`}if(s){const p=t.value.claude.find(l=>l.id===s);return p?`${p.name} (Console)`:`Console-${s.substring(0,8)}`}return"未知账户"},ue=d=>d?new Date(d)!d||ue(d)?!1:(new Date(d)-new Date)/(1e3*60*60*24)<=7,ye=d=>d?new Date(d).toLocaleDateString("zh-CN"):"",Ke=async d=>{P.value[d]?P.value[d]=!1:(P.value[d]=!0,O.value[d]||be(d),await ie(d,!0))},ie=async(d,s=!1)=>{if(!s&&k.value[d]&&k.value[d].length>0)return;const p=G(d);try{let l=`/admin/api-keys/${d}/model-stats`;const m=new URLSearchParams;if(p.customStart&&p.customEnd)m.append("startDate",p.customStart),m.append("endDate",p.customEnd),m.append("period","custom");else{const Y=p.preset==="today"?"daily":"monthly";m.append("period",Y)}l+="?"+m.toString();const S=await q.get(l);S.success&&(k.value[d]=S.data||[])}catch{R("加载模型统计失败","error"),k.value[d]=[]}},fe=(d,s)=>{const p=s.reduce((l,m)=>l+(m.allTokens||0),0);return p===0?0:Math.round(d/p*100)},he=d=>d.formatted&&d.formatted.total?d.formatted.total:d.cost!==void 0?`$${d.cost.toFixed(6)}`:"$0.000000",be=d=>{const s=new Date,p=new Date(s);p.setDate(s.getDate()-6),O.value[d]={type:"preset",preset:"7days",customStart:p.toISOString().split("T")[0],customEnd:s.toISOString().split("T")[0],customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}},G=d=>(O.value[d]||be(d),O.value[d]),ve=(d,s)=>{const p=G(s);p.type="preset",p.preset=d;const l=p.presetOptions.find(m=>m.value===d);if(l){const m=new Date,S=new Date(m);S.setDate(m.getDate()-(l.days-1)),p.customStart=S.toISOString().split("T")[0],p.customEnd=m.toISOString().split("T")[0];const Y=ce=>ce.getFullYear()+"-"+String(ce.getMonth()+1).padStart(2,"0")+"-"+String(ce.getDate()).padStart(2,"0")+" 00:00:00";p.customRange=[Y(S),Y(m)]}ie(s,!0)},Ie=(d,s)=>{const p=G(d);s&&s.length===2?(p.type="custom",p.preset="",p.customRange=s,p.customStart=s[0].split(" ")[0],p.customEnd=s[1].split(" ")[0],ie(d,!0)):s===null&&ve("7days",d)},De=d=>d>new Date,Le=d=>{const s=G(d);s.type="preset",s.preset="7days";const p=new Date,l=new Date(p);l.setDate(p.getDate()-6),s.customStart=l.toISOString().split("T")[0],s.customEnd=p.toISOString().split("T")[0],s.customRange=null,ie(d,!0),R("已重置筛选条件并刷新数据","info")},Me=()=>{K.value=!0},Se=d=>{N.value=d,x.value=!0},Re=d=>{v.value=d,n.value=!0},Te=d=>{K.value=!1,o.value=d,u.value=!0,ee()},Pe=()=>{x.value=!1,R("API Key 更新成功","success"),ee()},_e=()=>{n.value=!1,R("API Key 续期成功","success"),ee()},Ee=async d=>{let s=!1;if(window.showConfirm?s=await window.showConfirm("删除 API Key","确定要删除这个 API Key 吗?此操作不可恢复。","确定删除","取消"):s=confirm("确定要删除这个 API Key 吗?此操作不可恢复。"),!!s)try{const p=await q.delete(`/admin/api-keys/${d}`);p.success?(R("API Key 已删除","success"),ee()):R(p.message||"删除失败","error")}catch{R("删除失败","error")}},Ve=d=>{const p=`${window.location.origin}/admin-next/api-stats?apiId=${d.id}`,l=document.createElement("textarea");l.value=p,l.style.position="fixed",l.style.opacity="0",l.style.left="-9999px",document.body.appendChild(l),l.select(),l.setSelectionRange(0,99999);try{document.execCommand("copy")?R("已复制统计页面链接","success"):(R("复制失败,请手动复制","error"),console.log("统计页面链接:",p))}catch(m){R("复制失败,请手动复制","error"),console.error("复制错误:",m),console.log("统计页面链接:",p)}finally{document.body.removeChild(l)}};return pe(async()=>{await Promise.all([L.loadSupportedClients(),Ce(),ee()])}),(d,s)=>{const p=je;return i(),a("div",pl,[e("div",xl,[e("div",gl,[s[22]||(s[22]=e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900 mb-2"}," API Keys 管理 "),e("p",{class:"text-gray-600"}," 管理和监控您的 API 密钥 ")],-1)),e("div",yl,[A(e("select",{"onUpdate:modelValue":s[0]||(s[0]=l=>M.value=l),class:"px-2 py-1 text-sm text-gray-700 bg-white border border-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent hover:border-gray-300 transition-colors",onChange:s[1]||(s[1]=l=>ee())},s[19]||(s[19]=[e("option",{value:"today"}," 今日 ",-1),e("option",{value:"7days"}," 最近7天 ",-1),e("option",{value:"monthly"}," 本月 ",-1),e("option",{value:"all"}," 全部时间 ",-1)]),544),[[H,M.value]]),A(e("select",{"onUpdate:modelValue":s[2]||(s[2]=l=>z.value=l),class:"px-2 py-1 text-sm text-gray-700 bg-white border border-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent hover:border-gray-300 transition-colors",onChange:s[3]||(s[3]=l=>y.value=1)},[s[20]||(s[20]=e("option",{value:""}," 所有标签 ",-1)),(i(!0),a(T,null,_($.value,l=>(i(),a("option",{key:l,value:l},c(l),9,fl))),128))],544),[[H,z.value]]),e("button",{class:"btn btn-primary px-4 py-1.5 text-sm flex items-center gap-2",onClick:J(Me,["stop"])},s[21]||(s[21]=[e("i",{class:"fas fa-plus"},null,-1),b("创建新 Key ",-1)]))])]),V.value?(i(),a("div",bl,s[23]||(s[23]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载 API Keys... ",-1)]))):g.value.length===0?(i(),a("div",vl,s[24]||(s[24]=[e("div",{class:"w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center"},[e("i",{class:"fas fa-key text-gray-400 text-xl"})],-1),e("p",{class:"text-gray-500 text-lg"}," 暂无 API Keys ",-1),e("p",{class:"text-gray-400 text-sm mt-2"}," 点击上方按钮创建您的第一个 API Key ",-1)]))):(i(),a("div",wl,[e("table",$l,[e("thead",Al,[e("tr",null,[e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:s[4]||(s[4]=l=>oe("name"))},[s[25]||(s[25]=b(" 名称 ",-1)),f.value==="name"?(i(),a("i",{key:0,class:W(["fas",I.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),a("i",Cl))]),s[32]||(s[32]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 标签 ",-1)),s[33]||(s[33]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," API Key ",-1)),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:s[5]||(s[5]=l=>oe("status"))},[s[26]||(s[26]=b(" 状态 ",-1)),f.value==="status"?(i(),a("i",{key:0,class:W(["fas",I.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),a("i",kl))]),e("th",Kl,[s[29]||(s[29]=b(" 使用统计 ",-1)),e("span",{class:"cursor-pointer hover:bg-gray-100 px-2 py-1 rounded",onClick:s[6]||(s[6]=l=>oe("cost"))},[s[27]||(s[27]=b(" (费用 ",-1)),f.value==="cost"?(i(),a("i",{key:0,class:W(["fas",I.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),a("i",hl)),s[28]||(s[28]=b(") ",-1))])]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:s[7]||(s[7]=l=>oe("createdAt"))},[s[30]||(s[30]=b(" 创建时间 ",-1)),f.value==="createdAt"?(i(),a("i",{key:0,class:W(["fas",I.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),a("i",Il))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:s[8]||(s[8]=l=>oe("expiresAt"))},[s[31]||(s[31]=b(" 过期时间 ",-1)),f.value==="expiresAt"?(i(),a("i",{key:0,class:W(["fas",I.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),a("i",Dl))]),s[34]||(s[34]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 操作 ",-1))])]),e("tbody",Ll,[(i(!0),a(T,null,_(le.value,l=>(i(),a(T,{key:l.id},[e("tr",Ml,[e("td",Sl,[e("div",Rl,[s[37]||(s[37]=e("div",{class:"w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-key text-white text-xs"})],-1)),e("div",null,[e("div",Tl,c(l.name),1),e("div",Pl,c(l.id),1),e("div",_l,[l.claudeAccountId||l.claudeConsoleAccountId?(i(),a("span",El,[s[35]||(s[35]=e("i",{class:"fas fa-link mr-1"},null,-1)),b(" 绑定: "+c(ke(l.claudeAccountId,l.claudeConsoleAccountId)),1)])):(i(),a("span",Vl,s[36]||(s[36]=[e("i",{class:"fas fa-share-alt mr-1"},null,-1),b(" 使用共享池 ",-1)])))])])])]),e("td",jl,[e("div",Ul,[(i(!0),a(T,null,_(l.tags||[],m=>(i(),a("span",{key:m,class:"inline-flex items-center px-2 py-0.5 bg-blue-100 text-blue-800 text-xs rounded-full"},c(m),1))),128)),!l.tags||l.tags.length===0?(i(),a("span",ql,"无标签")):w("",!0)])]),e("td",Ol,[e("div",Fl,c((l.apiKey||"").substring(0,20))+"... ",1)]),e("td",Wl,[e("span",{class:W(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",l.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[e("div",{class:W(["w-2 h-2 rounded-full mr-2",l.isActive?"bg-green-500":"bg-red-500"])},null,2),b(" "+c(l.isActive?"活跃":"禁用"),1)],2)]),e("td",Nl,[e("div",Yl,[e("div",zl,[s[38]||(s[38]=e("span",{class:"text-gray-600"},"请求数:",-1)),e("span",Bl,c(F(l.usage&&l.usage.total&&l.usage.total.requests||0)),1)]),e("div",Hl,[s[39]||(s[39]=e("span",{class:"text-gray-600"},"Token:",-1)),e("span",Gl,c(F(l.usage&&l.usage.total&&l.usage.total.tokens||0)),1)]),e("div",Ql,[s[40]||(s[40]=e("span",{class:"text-gray-600"},"费用:",-1)),e("span",Xl,c(de(l.usage)),1)]),l.dailyCostLimit>0?(i(),a("div",Jl,[s[41]||(s[41]=e("span",{class:"text-gray-600"},"今日费用:",-1)),e("span",{class:W(["font-medium",(l.dailyCost||0)>=l.dailyCostLimit?"text-red-600":"text-blue-600"])}," $"+c((l.dailyCost||0).toFixed(2))+" / $"+c(l.dailyCostLimit.toFixed(2)),3)])):w("",!0),e("div",Zl,[s[42]||(s[42]=e("span",{class:"text-gray-600"},"并发限制:",-1)),e("span",eo,c(l.concurrencyLimit>0?l.concurrencyLimit:"无限制"),1)]),e("div",to,[s[43]||(s[43]=e("span",{class:"text-gray-600"},"当前并发:",-1)),e("span",{class:W(["font-medium",l.currentConcurrency>0?"text-orange-600":"text-gray-600"])},[b(c(l.currentConcurrency||0)+" ",1),l.concurrencyLimit>0?(i(),a("span",so,"/ "+c(l.concurrencyLimit),1)):w("",!0)],2)]),l.rateLimitWindow>0?(i(),a("div",lo,[s[44]||(s[44]=e("span",{class:"text-gray-600"},"时间窗口:",-1)),e("span",oo,c(l.rateLimitWindow)+" 分钟",1)])):w("",!0),l.rateLimitRequests>0?(i(),a("div",no,[s[45]||(s[45]=e("span",{class:"text-gray-600"},"请求限制:",-1)),e("span",io,c(l.rateLimitRequests)+" 次/窗口",1)])):w("",!0),e("div",ao,[e("span",null,"输入: "+c(F(l.usage&&l.usage.total&&l.usage.total.inputTokens||0)),1),e("span",null,"输出: "+c(F(l.usage&&l.usage.total&&l.usage.total.outputTokens||0)),1)]),(l.usage&&l.usage.total&&l.usage.total.cacheCreateTokens||0)>0||(l.usage&&l.usage.total&&l.usage.total.cacheReadTokens||0)>0?(i(),a("div",ro,[e("span",null,"缓存创建: "+c(F(l.usage&&l.usage.total&&l.usage.total.cacheCreateTokens||0)),1),e("span",null,"缓存读取: "+c(F(l.usage&&l.usage.total&&l.usage.total.cacheReadTokens||0)),1)])):w("",!0),e("div",uo,[e("span",null,"RPM: "+c(l.usage&&l.usage.averages&&l.usage.averages.rpm||0),1),e("span",null,"TPM: "+c(l.usage&&l.usage.averages&&l.usage.averages.tpm||0),1)]),e("div",co,[e("div",mo,[e("span",null,"今日: "+c(F(l.usage&&l.usage.daily&&l.usage.daily.requests||0))+"次",1),e("span",null,c(F(l.usage&&l.usage.daily&&l.usage.daily.tokens||0))+"T",1)])]),e("div",po,[l&&l.id?(i(),a("button",{key:0,class:"text-xs text-indigo-600 hover:text-indigo-800 font-medium",onClick:m=>Ke(l.id)},[e("i",{class:W(["fas",P.value[l.id]?"fa-chevron-up":"fa-chevron-down","mr-1"])},null,2),s[46]||(s[46]=b(" 模型使用分布 ",-1))],8,xo)):w("",!0)])])]),e("td",go,c(new Date(l.createdAt).toLocaleDateString()),1),e("td",yo,[l.expiresAt?(i(),a("div",fo,[ue(l.expiresAt)?(i(),a("div",bo,s[47]||(s[47]=[e("i",{class:"fas fa-exclamation-circle mr-1"},null,-1),b(" 已过期 ",-1)]))):ge(l.expiresAt)?(i(),a("div",vo,[s[48]||(s[48]=e("i",{class:"fas fa-clock mr-1"},null,-1)),b(" "+c(ye(l.expiresAt)),1)])):(i(),a("div",wo,c(ye(l.expiresAt)),1))])):(i(),a("div",$o,s[49]||(s[49]=[e("i",{class:"fas fa-infinity mr-1"},null,-1),b(" 永不过期 ",-1)])))]),e("td",Ao,[e("div",Co,[e("button",{class:"text-purple-600 hover:text-purple-900 font-medium hover:bg-purple-50 px-3 py-1 rounded-lg transition-colors",title:"复制统计页面链接",onClick:m=>Ve(l)},s[50]||(s[50]=[e("i",{class:"fas fa-chart-bar mr-1"},null,-1),b("统计 ",-1)]),8,ko),e("button",{class:"text-blue-600 hover:text-blue-900 font-medium hover:bg-blue-50 px-3 py-1 rounded-lg transition-colors",onClick:m=>Se(l)},s[51]||(s[51]=[e("i",{class:"fas fa-edit mr-1"},null,-1),b("编辑 ",-1)]),8,Ko),l.expiresAt&&(ue(l.expiresAt)||ge(l.expiresAt))?(i(),a("button",{key:0,class:"text-green-600 hover:text-green-900 font-medium hover:bg-green-50 px-3 py-1 rounded-lg transition-colors",onClick:m=>Re(l)},s[52]||(s[52]=[e("i",{class:"fas fa-clock mr-1"},null,-1),b("续期 ",-1)]),8,ho)):w("",!0),e("button",{class:"text-red-600 hover:text-red-900 font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors",onClick:m=>Ee(l.id)},s[53]||(s[53]=[e("i",{class:"fas fa-trash mr-1"},null,-1),b("删除 ",-1)]),8,Io)])])]),l&&l.id&&P.value[l.id]?(i(),a("tr",Do,[e("td",Lo,[k.value[l.id]?w("",!0):(i(),a("div",Mo,s[54]||(s[54]=[e("div",{class:"loading-spinner mx-auto"},null,-1),e("p",{class:"text-sm text-gray-500 mt-2"}," 加载模型统计... ",-1)]))),e("div",So,[e("div",Ro,[s[55]||(s[55]=e("h5",{class:"text-sm font-semibold text-gray-700 flex items-center"},[e("i",{class:"fas fa-chart-pie text-indigo-500 mr-2"}),b(" 模型使用分布 ")],-1)),e("div",To,[k.value[l.id]&&k.value[l.id].length>0?(i(),a("span",Po,c(k.value[l.id].length)+" 个模型 ",1)):w("",!0),e("div",_o,[e("div",Eo,[(i(!0),a(T,null,_(G(l.id).presetOptions,m=>(i(),a("button",{key:m.value,class:W(["px-2 py-1 rounded text-xs font-medium transition-colors",G(l.id).preset===m.value&&G(l.id).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:S=>ve(m.value,l.id)},c(m.label),11,Vo))),128))]),Ue(p,{"model-value":G(l.id).customRange,type:"datetimerange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期",format:"YYYY-MM-DD HH:mm:ss","value-format":"YYYY-MM-DD HH:mm:ss","disabled-date":De,"default-time":D.value,size:"small",style:{width:"280px"},class:"api-key-date-picker",clearable:!0,"unlink-panels":!1,"onUpdate:modelValue":m=>Ie(l.id,m)},null,8,["model-value","default-time","onUpdate:modelValue"])])])]),k.value[l.id]&&k.value[l.id].length===0?(i(),a("div",jo,[e("div",Uo,[s[57]||(s[57]=e("i",{class:"fas fa-chart-line text-gray-400 text-lg"},null,-1)),s[58]||(s[58]=e("p",{class:"text-sm text-gray-500"}," 暂无模型使用数据 ",-1)),e("button",{class:"text-blue-500 hover:text-blue-700 text-sm ml-2 flex items-center gap-1 transition-colors",title:"重置筛选条件并刷新",onClick:m=>Le(l.id)},s[56]||(s[56]=[e("i",{class:"fas fa-sync-alt text-xs"},null,-1),e("span",{class:"text-xs"},"刷新",-1)]),8,qo)]),s[59]||(s[59]=e("p",{class:"text-xs text-gray-400"}," 尝试调整时间范围或点击刷新重新加载数据 ",-1))])):k.value[l.id]&&k.value[l.id].length>0?(i(),a("div",Oo,[(i(!0),a(T,null,_(k.value[l.id],m=>(i(),a("div",{key:m.model,class:"bg-gradient-to-br from-white to-gray-50 rounded-xl p-4 border border-gray-200 hover:border-indigo-300 hover:shadow-lg transition-all duration-200"},[e("div",Fo,[e("div",Wo,[e("span",No,c(m.model),1),e("span",Yo,c(m.requests)+" 次请求",1)])]),e("div",zo,[e("div",Bo,[s[60]||(s[60]=e("span",{class:"text-gray-600 flex items-center"},[e("i",{class:"fas fa-coins text-yellow-500 mr-1 text-xs"}),b(" 总Token: ")],-1)),e("span",Ho,c(F(m.allTokens)),1)]),e("div",Go,[s[61]||(s[61]=e("span",{class:"text-gray-600 flex items-center"},[e("i",{class:"fas fa-dollar-sign text-green-500 mr-1 text-xs"}),b(" 费用: ")],-1)),e("span",Qo,c(he(m)),1)]),e("div",Xo,[e("div",Jo,[s[62]||(s[62]=e("span",{class:"flex items-center"},[e("i",{class:"fas fa-arrow-down text-green-500 mr-1"}),b(" 输入: ")],-1)),e("span",Zo,c(F(m.inputTokens)),1)]),e("div",en,[s[63]||(s[63]=e("span",{class:"flex items-center"},[e("i",{class:"fas fa-arrow-up text-blue-500 mr-1"}),b(" 输出: ")],-1)),e("span",tn,c(F(m.outputTokens)),1)]),m.cacheCreateTokens>0?(i(),a("div",sn,[s[64]||(s[64]=e("span",{class:"flex items-center"},[e("i",{class:"fas fa-save mr-1"}),b(" 缓存创建: ")],-1)),e("span",ln,c(F(m.cacheCreateTokens)),1)])):w("",!0),m.cacheReadTokens>0?(i(),a("div",on,[s[65]||(s[65]=e("span",{class:"flex items-center"},[e("i",{class:"fas fa-download mr-1"}),b(" 缓存读取: ")],-1)),e("span",nn,c(F(m.cacheReadTokens)),1)])):w("",!0)])]),e("div",an,[e("div",{class:"bg-gradient-to-r from-indigo-500 to-purple-600 h-2 rounded-full transition-all duration-500",style:qe({width:fe(m.allTokens,k.value[l.id])+"%"})},null,4)]),e("div",rn,[e("span",dn,c(fe(m.allTokens,k.value[l.id]))+"% ",1)])]))),128))])):w("",!0),k.value[l.id]&&k.value[l.id].length>0?(i(),a("div",un,[e("div",cn,[s[68]||(s[68]=e("span",{class:"font-semibold text-gray-700 flex items-center"},[e("i",{class:"fas fa-calculator text-indigo-500 mr-2"}),b(" 总计统计 ")],-1)),e("div",mn,[e("span",pn,[s[66]||(s[66]=b(" 总请求: ",-1)),e("span",xn,c(k.value[l.id].reduce((m,S)=>m+S.requests,0)),1)]),e("span",gn,[s[67]||(s[67]=b(" 总Token: ",-1)),e("span",yn,c(F(k.value[l.id].reduce((m,S)=>m+S.allTokens,0))),1)])])])])):w("",!0)])])])):w("",!0)],64))),128))])])])),r.value.length>0?(i(),a("div",fn,[e("div",bn,[e("span",vn," 共 "+c(r.value.length)+" 条记录 ",1),e("div",wn,[s[69]||(s[69]=e("span",{class:"text-sm text-gray-600"},"每页显示",-1)),A(e("select",{"onUpdate:modelValue":s[9]||(s[9]=l=>E.value=l),class:"px-2 py-1 text-sm text-gray-700 bg-white border border-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent hover:border-gray-300 transition-colors",onChange:s[10]||(s[10]=l=>y.value=1)},[(i(),a(T,null,_(B,l=>e("option",{key:l,value:l},c(l),9,$n)),64))],544),[[H,E.value]]),s[70]||(s[70]=e("span",{class:"text-sm text-gray-600"},"条",-1))])]),e("div",An,[e("button",{class:"px-3 py-1 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",disabled:y.value===1,onClick:s[11]||(s[11]=l=>y.value--)},s[71]||(s[71]=[e("i",{class:"fas fa-chevron-left"},null,-1)]),8,Cn),e("div",kn,[y.value>3?(i(),a("button",{key:0,class:"px-3 py-1 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50",onClick:s[12]||(s[12]=l=>y.value=1)}," 1 ")):w("",!0),y.value>4?(i(),a("span",Kn,"...")):w("",!0),(i(!0),a(T,null,_(Z.value,l=>(i(),a("button",{key:l,class:W(["px-3 py-1 text-sm font-medium rounded-md",l===y.value?"bg-blue-600 text-white":"text-gray-700 bg-white border border-gray-300 hover:bg-gray-50"]),onClick:m=>y.value=l},c(l),11,hn))),128)),y.value1&&y.valuey.value=j.value)},c(j.value),1)):w("",!0)]),e("button",{class:"px-3 py-1 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",disabled:y.value===j.value||j.value===0,onClick:s[14]||(s[14]=l=>y.value++)},s[72]||(s[72]=[e("i",{class:"fas fa-chevron-right"},null,-1)]),8,Dn)])])):w("",!0)]),K.value?(i(),X(Ut,{key:0,accounts:t.value,onClose:s[15]||(s[15]=l=>K.value=!1),onSuccess:Te},null,8,["accounts"])):w("",!0),x.value?(i(),X(_s,{key:1,"api-key":N.value,accounts:t.value,onClose:s[16]||(s[16]=l=>x.value=!1),onSuccess:Pe},null,8,["api-key","accounts"])):w("",!0),n.value?(i(),X(Js,{key:2,"api-key":v.value,onClose:s[17]||(s[17]=l=>n.value=!1),onSuccess:_e},null,8,["api-key"])):w("",!0),u.value?(i(),X(ml,{key:3,"api-key":o.value,onClose:s[18]||(s[18]=l=>u.value=!1)},null,8,["api-key"])):w("",!0)])}}},_n=ne(Ln,[["__scopeId","data-v-277a81a9"]]);export{_n as default}; diff --git a/web/admin-spa/dist/assets/ApiKeysView-Dw8A7_uy.css b/web/admin-spa/dist/assets/ApiKeysView-Dw8A7_uy.css deleted file mode 100644 index c1e0c6a8..00000000 --- a/web/admin-spa/dist/assets/ApiKeysView-Dw8A7_uy.css +++ /dev/null @@ -1 +0,0 @@ -pre[data-v-2c02f1f7]{white-space:pre-wrap;word-wrap:break-word}.tab-content[data-v-277a81a9]{min-height:calc(100vh - 300px)}.table-container[data-v-277a81a9]{overflow-x:auto;border-radius:12px;border:1px solid rgba(0,0,0,.05)}.table-row[data-v-277a81a9]{transition:all .2s ease}.table-row[data-v-277a81a9]:hover{background-color:#00000005}.loading-spinner[data-v-277a81a9]{width:24px;height:24px;border:2px solid #e5e7eb;border-top:2px solid #3b82f6;border-radius:50%;animation:spin-277a81a9 1s linear infinite}@keyframes spin-277a81a9{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.api-key-date-picker[data-v-277a81a9] .el-input__inner{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.api-key-date-picker[data-v-277a81a9] .el-input__inner:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.api-key-date-picker[data-v-277a81a9] .el-range-separator{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))} diff --git a/web/admin-spa/dist/assets/ApiStatsView-B5a23-WN.js b/web/admin-spa/dist/assets/ApiStatsView-B5a23-WN.js deleted file mode 100644 index 53fd2c24..00000000 --- a/web/admin-spa/dist/assets/ApiStatsView-B5a23-WN.js +++ /dev/null @@ -1 +0,0 @@ -import{aR as B,r as $,c as J,aW as A,x as f,y as m,z as t,O as y,K as H,aq as Q,u as s,aa as G,f as X,P as r,C as P,L as C,Q as O,ac as F,q as Z,aU as tt,V as st,o as et,R as S,J as at,av as it}from"./vue-vendor-CKToUHZx.js";import{L as ot}from"./LogoTitle-CXHYkSsD.js";import{_ as K}from"./index-9AMT1Op2.js";import{b as nt}from"./vendor-BDiMbLwQ.js";import lt from"./TutorialView-D-C0Do28.js";/* empty css */import"./element-plus-B8Fs_0jW.js";class rt{constructor(){this.baseURL=window.location.origin,this.isDev=!1}async request(n,a={}){try{this.isDev&&n.startsWith("/admin")&&(n="/webapi"+n);const l=await fetch(`${this.baseURL}${n}`,{headers:{"Content-Type":"application/json",...a.headers},...a}),c=await l.json();if(!l.ok)throw new Error(c.message||`请求失败: ${l.status}`);return c}catch(l){throw console.error("API Stats request error:",l),l}}async getKeyId(n){return this.request("/apiStats/api/get-key-id",{method:"POST",body:JSON.stringify({apiKey:n})})}async getUserStats(n){return this.request("/apiStats/api/user-stats",{method:"POST",body:JSON.stringify({apiId:n})})}async getUserModelStats(n,a="daily"){return this.request("/apiStats/api/user-model-stats",{method:"POST",body:JSON.stringify({apiId:n,period:a})})}async getOemSettings(){try{return await this.request("/admin/oem-settings")}catch(n){return console.error("Failed to load OEM settings:",n),{success:!0,data:{siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}}}}const D=new rt,M=B("apistats",()=>{const w=$(""),n=$(null),a=$(!1),l=$(!1),c=$(!0),e=$(""),i=$("daily"),d=$(null),v=$([]),_=$(null),h=$(null),x=$({siteName:"",siteIcon:"",siteIconData:""}),u=J(()=>{const o={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};return i.value==="daily"?_.value||o:h.value||o}),U=J(()=>{if(!d.value||!u.value)return{tokenUsage:0,costUsage:0,requestUsage:0};const o=u.value,g=d.value.limits;return{tokenUsage:g.tokenLimit>0?Math.min(o.allTokens/g.tokenLimit*100,100):0,costUsage:g.dailyCostLimit>0?Math.min(o.cost/g.dailyCostLimit*100,100):0,requestUsage:g.rateLimitRequests>0?Math.min(o.requests/g.rateLimitRequests*100,100):0}});async function T(){if(!w.value.trim()){e.value="请输入 API Key";return}a.value=!0,e.value="",d.value=null,v.value=[],n.value=null;try{const o=await D.getKeyId(w.value);if(o.success){n.value=o.data.id;const g=await D.getUserStats(n.value);if(g.success)d.value=g.data,await R(),e.value="",j();else throw new Error(g.message||"查询失败")}else throw new Error(o.message||"获取 API Key ID 失败")}catch(o){console.error("Query stats error:",o),e.value=o.message||"查询统计数据失败,请检查您的 API Key 是否正确",d.value=null,v.value=[],n.value=null}finally{a.value=!1}}async function R(){n.value&&(await Promise.all([L("daily"),L("monthly")]),await q(i.value))}async function L(o){try{const g=await D.getUserModelStats(n.value,o);if(g.success){const z=g.data||[],k={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};z.forEach(I=>{var W;k.requests+=I.requests||0,k.inputTokens+=I.inputTokens||0,k.outputTokens+=I.outputTokens||0,k.cacheCreateTokens+=I.cacheCreateTokens||0,k.cacheReadTokens+=I.cacheReadTokens||0,k.allTokens+=I.allTokens||0,k.cost+=((W=I.costs)==null?void 0:W.total)||0}),k.formattedCost=N(k.cost),o==="daily"?_.value=k:h.value=k}else console.warn(`Failed to load ${o} stats:`,g.message)}catch(g){console.error(`Load ${o} stats error:`,g)}}async function q(o="daily"){if(n.value){l.value=!0;try{const g=await D.getUserModelStats(n.value,o);if(g.success)v.value=g.data||[];else throw new Error(g.message||"加载模型统计失败")}catch(g){console.error("Load model stats error:",g),v.value=[]}finally{l.value=!1}}}async function E(o){i.value===o||l.value||(i.value=o,(o==="daily"&&!_.value||o==="monthly"&&!h.value)&&await L(o),await q(o))}async function b(){if(n.value){a.value=!0,e.value="",d.value=null,v.value=[];try{const o=await D.getUserStats(n.value);if(o.success)d.value=o.data,await R(),e.value="";else throw new Error(o.message||"查询失败")}catch(o){console.error("Load stats with apiId error:",o),e.value=o.message||"查询统计数据失败",d.value=null,v.value=[]}finally{a.value=!1}}}async function p(){c.value=!0;try{const o=await D.getOemSettings();o&&o.success&&o.data&&(x.value={...x.value,...o.data})}catch(o){console.error("Error loading OEM settings:",o),x.value={siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}finally{c.value=!1}}function N(o){return typeof o!="number"||o===0?"$0.000000":o>=1?"$"+o.toFixed(2):o>=.01?"$"+o.toFixed(4):"$"+o.toFixed(6)}function j(){if(n.value){const o=new URL(window.location);o.searchParams.set("apiId",n.value),window.history.pushState({},"",o)}}function V(){d.value=null,v.value=[],_.value=null,h.value=null,e.value="",i.value="daily",n.value=null}function Y(){w.value="",V()}return{apiKey:w,apiId:n,loading:a,modelStatsLoading:l,oemLoading:c,error:e,statsPeriod:i,statsData:d,modelStats:v,dailyStats:_,monthlyStats:h,oemSettings:x,currentPeriodData:u,usagePercentages:U,queryStats:T,loadAllPeriodStats:R,loadPeriodStats:L,loadModelStats:q,switchPeriod:E,loadStatsWithApiId:b,loadOemSettings:p,clearData:V,reset:Y}}),dt={class:"api-input-wide-card glass-strong rounded-3xl p-6 mb-8 shadow-xl"},ct={class:"max-w-4xl mx-auto"},ut={class:"api-input-grid grid grid-cols-1 lg:grid-cols-4"},ft={class:"lg:col-span-3"},mt=["disabled"],xt={class:"lg:col-span-1"},yt=["disabled"],pt={key:0,class:"fas fa-spinner loading-spinner"},gt={key:1,class:"fas fa-search"},vt={__name:"ApiKeyInput",setup(w){const n=M(),{apiKey:a,loading:l}=A(n),{queryStats:c}=n;return(e,i)=>(m(),f("div",dt,[i[6]||(i[6]=t("div",{class:"wide-card-title text-center mb-6"},[t("h2",{class:"text-2xl font-bold mb-2"},[t("i",{class:"fas fa-chart-line mr-3"}),y(" 使用统计查询 ")]),t("p",{class:"text-base text-gray-600"}," 查询您的 API Key 使用情况和统计数据 ")],-1)),t("div",ct,[t("div",ut,[t("div",ft,[i[3]||(i[3]=t("label",{class:"block text-sm font-medium mb-2 text-gray-700"},[t("i",{class:"fas fa-key mr-2"}),y(" 输入您的 API Key ")],-1)),H(t("input",{"onUpdate:modelValue":i[0]||(i[0]=d=>X(a)?a.value=d:null),type:"password",placeholder:"请输入您的 API Key (cr_...)",class:"wide-card-input w-full",disabled:s(l),onKeyup:i[1]||(i[1]=G((...d)=>s(c)&&s(c)(...d),["enter"]))},null,40,mt),[[Q,s(a)]])]),t("div",xt,[i[4]||(i[4]=t("label",{class:"hidden lg:block text-sm font-medium mb-2 text-gray-700"},"   ",-1)),t("button",{disabled:s(l)||!s(a).trim(),class:"btn btn-primary btn-query w-full h-full flex items-center justify-center gap-2",onClick:i[2]||(i[2]=(...d)=>s(c)&&s(c)(...d))},[s(l)?(m(),f("i",pt)):(m(),f("i",gt)),y(" "+r(s(l)?"查询中...":"查询统计"),1)],8,yt)])]),i[5]||(i[5]=t("div",{class:"security-notice mt-4"},[t("i",{class:"fas fa-shield-alt mr-2"}),y(" 您的 API Key 仅用于查询自己的统计数据,不会被存储或用于其他用途 ")],-1))])]))}},_t=K(vt,[["__scopeId","data-v-d80546e3"]]),bt={class:"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8"},ht={class:"card p-6"},$t={class:"space-y-3"},wt={class:"flex justify-between items-center"},kt={class:"font-medium text-gray-900"},St={class:"flex justify-between items-center"},Tt={class:"flex justify-between items-center"},It={class:"font-medium text-gray-900"},Ct={class:"flex justify-between items-center"},Lt={class:"font-medium text-gray-900"},Dt={class:"flex justify-between items-center"},Pt={key:0},At={key:0,class:"text-red-600 font-medium"},Kt={key:1,class:"text-orange-600 font-medium"},Mt={key:2,class:"text-gray-900 font-medium"},Rt={key:1,class:"text-gray-400 font-medium"},qt={class:"card p-6"},jt={class:"text-xl font-bold mb-4 flex items-center text-gray-900"},Ut={class:"text-sm font-normal text-gray-600 ml-2"},Et={class:"grid grid-cols-2 gap-4"},Nt={class:"stat-card text-center"},Ot={class:"text-3xl font-bold text-green-600"},Ft={class:"text-sm text-gray-600"},Vt={class:"stat-card text-center"},Wt={class:"text-3xl font-bold text-blue-600"},Jt={class:"text-sm text-gray-600"},Yt={class:"stat-card text-center"},zt={class:"text-3xl font-bold text-purple-600"},Bt={class:"text-sm text-gray-600"},Ht={class:"stat-card text-center"},Qt={class:"text-3xl font-bold text-yellow-600"},Gt={class:"text-sm text-gray-600"},Xt={__name:"StatsOverview",setup(w){const n=M(),{statsData:a,statsPeriod:l,currentPeriodData:c}=A(n),e=x=>{if(!x)return"无";try{return nt(x).format("YYYY年MM月DD日 HH:mm")}catch{return"格式错误"}},i=x=>x?new Date(x).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}):"",d=x=>x?new Date(x){if(!x)return!1;const T=(new Date(x)-new Date)/(1e3*60*60*24);return T>0&&T<=7},_=x=>(typeof x!="number"&&(x=parseInt(x)||0),x===0?"0":x>=1e6?(x/1e6).toFixed(1)+"M":x>=1e3?(x/1e3).toFixed(1)+"K":x.toLocaleString()),h=x=>({claude:"Claude",gemini:"Gemini",all:"全部模型"})[x]||x||"未知";return(x,u)=>(m(),f("div",bt,[t("div",ht,[u[8]||(u[8]=t("h3",{class:"text-xl font-bold mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-info-circle mr-3 text-blue-500"}),y(" API Key 信息 ")],-1)),t("div",$t,[t("div",wt,[u[0]||(u[0]=t("span",{class:"text-gray-600"},"名称",-1)),t("span",kt,r(s(a).name),1)]),t("div",St,[u[1]||(u[1]=t("span",{class:"text-gray-600"},"状态",-1)),t("span",{class:P([s(a).isActive?"text-green-600":"text-red-600","font-medium"])},[t("i",{class:P([s(a).isActive?"fas fa-check-circle":"fas fa-times-circle","mr-1"])},null,2),y(" "+r(s(a).isActive?"活跃":"已停用"),1)],2)]),t("div",Tt,[u[2]||(u[2]=t("span",{class:"text-gray-600"},"权限",-1)),t("span",It,r(h(s(a).permissions)),1)]),t("div",Ct,[u[3]||(u[3]=t("span",{class:"text-gray-600"},"创建时间",-1)),t("span",Lt,r(e(s(a).createdAt)),1)]),t("div",Dt,[u[7]||(u[7]=t("span",{class:"text-gray-600"},"过期时间",-1)),s(a).expiresAt?(m(),f("div",Pt,[d(s(a).expiresAt)?(m(),f("div",At,u[4]||(u[4]=[t("i",{class:"fas fa-exclamation-circle mr-1"},null,-1),y(" 已过期 ",-1)]))):v(s(a).expiresAt)?(m(),f("div",Kt,[u[5]||(u[5]=t("i",{class:"fas fa-clock mr-1"},null,-1)),y(" "+r(i(s(a).expiresAt)),1)])):(m(),f("div",Mt,r(i(s(a).expiresAt)),1))])):(m(),f("div",Rt,u[6]||(u[6]=[t("i",{class:"fas fa-infinity mr-1"},null,-1),y(" 永不过期 ",-1)])))])])]),t("div",qt,[t("h3",jt,[u[9]||(u[9]=t("i",{class:"fas fa-chart-bar mr-3 text-green-500"},null,-1)),u[10]||(u[10]=y(" 使用统计概览 ",-1)),t("span",Ut,"("+r(s(l)==="daily"?"今日":"本月")+")",1)]),t("div",Et,[t("div",Nt,[t("div",Ot,r(_(s(c).requests)),1),t("div",Ft,r(s(l)==="daily"?"今日":"本月")+"请求数 ",1)]),t("div",Vt,[t("div",Wt,r(_(s(c).allTokens)),1),t("div",Jt,r(s(l)==="daily"?"今日":"本月")+"Token数 ",1)]),t("div",Yt,[t("div",zt,r(s(c).formattedCost||"$0.000000"),1),t("div",Bt,r(s(l)==="daily"?"今日":"本月")+"费用 ",1)]),t("div",Ht,[t("div",Qt,r(_(s(c).inputTokens)),1),t("div",Gt,r(s(l)==="daily"?"今日":"本月")+"输入Token ",1)])])])]))}},Zt=K(Xt,[["__scopeId","data-v-e7abc110"]]),ts={class:"card p-6"},ss={class:"text-xl font-bold mb-4 flex items-center text-gray-900"},es={class:"text-sm font-normal text-gray-600 ml-2"},as={class:"space-y-3"},is={class:"flex justify-between items-center"},os={class:"font-medium text-gray-900"},ns={class:"flex justify-between items-center"},ls={class:"font-medium text-gray-900"},rs={class:"flex justify-between items-center"},ds={class:"font-medium text-gray-900"},cs={class:"flex justify-between items-center"},us={class:"font-medium text-gray-900"},fs={class:"mt-4 pt-4 border-t border-gray-200"},ms={class:"flex justify-between items-center font-bold text-gray-900"},xs={class:"text-xl"},ys={__name:"TokenDistribution",setup(w){const n=M(),{statsPeriod:a,currentPeriodData:l}=A(n),c=e=>(typeof e!="number"&&(e=parseInt(e)||0),e===0?"0":e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":e.toLocaleString());return(e,i)=>(m(),f("div",ts,[t("h3",ss,[i[0]||(i[0]=t("i",{class:"fas fa-coins mr-3 text-yellow-500"},null,-1)),i[1]||(i[1]=y(" Token 使用分布 ",-1)),t("span",es,"("+r(s(a)==="daily"?"今日":"本月")+")",1)]),t("div",as,[t("div",is,[i[2]||(i[2]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-arrow-right mr-2 text-green-500"}),y(" 输入 Token ")],-1)),t("span",os,r(c(s(l).inputTokens)),1)]),t("div",ns,[i[3]||(i[3]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-arrow-left mr-2 text-blue-500"}),y(" 输出 Token ")],-1)),t("span",ls,r(c(s(l).outputTokens)),1)]),t("div",rs,[i[4]||(i[4]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-save mr-2 text-purple-500"}),y(" 缓存创建 Token ")],-1)),t("span",ds,r(c(s(l).cacheCreateTokens)),1)]),t("div",cs,[i[5]||(i[5]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-download mr-2 text-orange-500"}),y(" 缓存读取 Token ")],-1)),t("span",us,r(c(s(l).cacheReadTokens)),1)])]),t("div",fs,[t("div",ms,[t("span",null,r(s(a)==="daily"?"今日":"本月")+"总计",1),t("span",xs,r(c(s(l).allTokens)),1)])])]))}},ps=K(ys,[["__scopeId","data-v-ff744b2f"]]),gs={class:"card p-6"},vs={class:"space-y-3"},_s={class:"flex justify-between items-center"},bs={class:"font-medium text-gray-900"},hs={class:"flex justify-between items-center"},$s={class:"font-medium text-gray-900"},ws={class:"flex justify-between items-center"},ks={class:"font-medium text-gray-900"},Ss={class:"flex justify-between items-center"},Ts={class:"font-medium text-gray-900"},Is={class:"flex justify-between items-center"},Cs={class:"font-medium text-gray-900"},Ls={key:0,class:"text-orange-600"},Ds={key:1,class:"text-green-600"},Ps={class:"flex justify-between items-center"},As={class:"font-medium text-gray-900"},Ks={key:0,class:"text-orange-600"},Ms={key:1,class:"text-green-600"},Rs={key:0,class:"card p-6 mt-6"},qs={class:"grid grid-cols-1 lg:grid-cols-2 gap-6"},js={key:0,class:"bg-amber-50 border border-amber-200 rounded-lg p-4"},Us={class:"space-y-2"},Es={class:"text-gray-800"},Ns={key:1,class:"bg-blue-50 border border-blue-200 rounded-lg p-4"},Os={class:"space-y-2"},Fs={class:"text-gray-800"},Vs={__name:"LimitConfig",setup(w){const n=M(),{statsData:a}=A(n),l=c=>(typeof c!="number"&&(c=parseInt(c)||0),c===0?"0":c>=1e6?(c/1e6).toFixed(1)+"M":c>=1e3?(c/1e3).toFixed(1)+"K":c.toLocaleString());return(c,e)=>(m(),f("div",null,[t("div",gs,[e[10]||(e[10]=t("h3",{class:"text-xl font-bold mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-shield-alt mr-3 text-red-500"}),y(" 限制配置 ")],-1)),t("div",vs,[t("div",_s,[e[0]||(e[0]=t("span",{class:"text-gray-600"},"Token 限制",-1)),t("span",bs,r(s(a).limits.tokenLimit>0?l(s(a).limits.tokenLimit):"无限制"),1)]),t("div",hs,[e[1]||(e[1]=t("span",{class:"text-gray-600"},"并发限制",-1)),t("span",$s,r(s(a).limits.concurrencyLimit>0?s(a).limits.concurrencyLimit:"无限制"),1)]),t("div",ws,[e[2]||(e[2]=t("span",{class:"text-gray-600"},"速率限制",-1)),t("span",ks,r(s(a).limits.rateLimitRequests>0&&s(a).limits.rateLimitWindow>0?`${s(a).limits.rateLimitRequests}次/${s(a).limits.rateLimitWindow}分钟`:"无限制"),1)]),t("div",Ss,[e[3]||(e[3]=t("span",{class:"text-gray-600"},"每日费用限制",-1)),t("span",Ts,r(s(a).limits.dailyCostLimit>0?"$"+s(a).limits.dailyCostLimit:"无限制"),1)]),t("div",Is,[e[6]||(e[6]=t("span",{class:"text-gray-600"},"模型限制",-1)),t("span",Cs,[s(a).restrictions.enableModelRestriction&&s(a).restrictions.restrictedModels.length>0?(m(),f("span",Ls,[e[4]||(e[4]=t("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),y(" 限制 "+r(s(a).restrictions.restrictedModels.length)+" 个模型 ",1)])):(m(),f("span",Ds,e[5]||(e[5]=[t("i",{class:"fas fa-check-circle mr-1"},null,-1),y(" 允许所有模型 ",-1)])))])]),t("div",Ps,[e[9]||(e[9]=t("span",{class:"text-gray-600"},"客户端限制",-1)),t("span",As,[s(a).restrictions.enableClientRestriction&&s(a).restrictions.allowedClients.length>0?(m(),f("span",Ks,[e[7]||(e[7]=t("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),y(" 限制 "+r(s(a).restrictions.allowedClients.length)+" 个客户端 ",1)])):(m(),f("span",Ms,e[8]||(e[8]=[t("i",{class:"fas fa-check-circle mr-1"},null,-1),y(" 允许所有客户端 ",-1)])))])])])]),s(a).restrictions.enableModelRestriction&&s(a).restrictions.restrictedModels.length>0||s(a).restrictions.enableClientRestriction&&s(a).restrictions.allowedClients.length>0?(m(),f("div",Rs,[e[17]||(e[17]=t("h3",{class:"text-xl font-bold mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-list-alt mr-3 text-amber-500"}),y(" 详细限制信息 ")],-1)),t("div",qs,[s(a).restrictions.enableModelRestriction&&s(a).restrictions.restrictedModels.length>0?(m(),f("div",js,[e[12]||(e[12]=t("h4",{class:"font-bold text-amber-800 mb-3 flex items-center"},[t("i",{class:"fas fa-robot mr-2"}),y(" 受限模型列表 ")],-1)),t("div",Us,[(m(!0),f(O,null,F(s(a).restrictions.restrictedModels,i=>(m(),f("div",{key:i,class:"bg-white rounded px-3 py-2 text-sm border border-amber-200"},[e[11]||(e[11]=t("i",{class:"fas fa-ban mr-2 text-red-500"},null,-1)),t("span",Es,r(i),1)]))),128))]),e[13]||(e[13]=t("p",{class:"text-xs text-amber-700 mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),y(" 此 API Key 不能访问以上列出的模型 ")],-1))])):C("",!0),s(a).restrictions.enableClientRestriction&&s(a).restrictions.allowedClients.length>0?(m(),f("div",Ns,[e[15]||(e[15]=t("h4",{class:"font-bold text-blue-800 mb-3 flex items-center"},[t("i",{class:"fas fa-desktop mr-2"}),y(" 允许的客户端 ")],-1)),t("div",Os,[(m(!0),f(O,null,F(s(a).restrictions.allowedClients,i=>(m(),f("div",{key:i,class:"bg-white rounded px-3 py-2 text-sm border border-blue-200"},[e[14]||(e[14]=t("i",{class:"fas fa-check mr-2 text-green-500"},null,-1)),t("span",Fs,r(i),1)]))),128))]),e[16]||(e[16]=t("p",{class:"text-xs text-blue-700 mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),y(" 此 API Key 只能被以上列出的客户端使用 ")],-1))])):C("",!0)])])):C("",!0)]))}},Ws=K(Vs,[["__scopeId","data-v-f97c29cf"]]),Js={class:"card p-6"},Ys={class:"mb-6"},zs={class:"text-xl font-bold flex items-center text-gray-900"},Bs={class:"text-sm font-normal text-gray-600 ml-2"},Hs={key:0,class:"text-center py-8"},Qs={key:1,class:"space-y-4"},Gs={class:"flex justify-between items-start mb-3"},Xs={class:"font-bold text-lg text-gray-900"},Zs={class:"text-gray-600 text-sm"},te={class:"text-right"},se={class:"text-lg font-bold text-green-600"},ee={class:"grid grid-cols-2 md:grid-cols-4 gap-3 text-sm"},ae={class:"bg-gray-50 rounded p-2"},ie={class:"font-medium text-gray-900"},oe={class:"bg-gray-50 rounded p-2"},ne={class:"font-medium text-gray-900"},le={class:"bg-gray-50 rounded p-2"},re={class:"font-medium text-gray-900"},de={class:"bg-gray-50 rounded p-2"},ce={class:"font-medium text-gray-900"},ue={key:2,class:"text-center py-8 text-gray-500"},fe={__name:"ModelUsageStats",setup(w){const n=M(),{statsPeriod:a,modelStats:l,modelStatsLoading:c}=A(n),e=i=>(typeof i!="number"&&(i=parseInt(i)||0),i===0?"0":i>=1e6?(i/1e6).toFixed(1)+"M":i>=1e3?(i/1e3).toFixed(1)+"K":i.toLocaleString());return(i,d)=>(m(),f("div",Js,[t("div",Ys,[t("h3",zs,[d[0]||(d[0]=t("i",{class:"fas fa-robot mr-3 text-indigo-500"},null,-1)),d[1]||(d[1]=y(" 模型使用统计 ",-1)),t("span",Bs,"("+r(s(a)==="daily"?"今日":"本月")+")",1)])]),s(c)?(m(),f("div",Hs,d[2]||(d[2]=[t("i",{class:"fas fa-spinner loading-spinner text-2xl mb-2 text-gray-600"},null,-1),t("p",{class:"text-gray-600"}," 加载模型统计数据中... ",-1)]))):s(l).length>0?(m(),f("div",Qs,[(m(!0),f(O,null,F(s(l),(v,_)=>{var h;return m(),f("div",{key:_,class:"model-usage-item"},[t("div",Gs,[t("div",null,[t("h4",Xs,r(v.model),1),t("p",Zs,r(v.requests)+" 次请求 ",1)]),t("div",te,[t("div",se,r(((h=v.formatted)==null?void 0:h.total)||"$0.000000"),1),d[3]||(d[3]=t("div",{class:"text-sm text-gray-600"}," 总费用 ",-1))])]),t("div",ee,[t("div",ae,[d[4]||(d[4]=t("div",{class:"text-gray-600"}," 输入 Token ",-1)),t("div",ie,r(e(v.inputTokens)),1)]),t("div",oe,[d[5]||(d[5]=t("div",{class:"text-gray-600"}," 输出 Token ",-1)),t("div",ne,r(e(v.outputTokens)),1)]),t("div",le,[d[6]||(d[6]=t("div",{class:"text-gray-600"}," 缓存创建 ",-1)),t("div",re,r(e(v.cacheCreateTokens)),1)]),t("div",de,[d[7]||(d[7]=t("div",{class:"text-gray-600"}," 缓存读取 ",-1)),t("div",ce,r(e(v.cacheReadTokens)),1)])])])}),128))])):(m(),f("div",ue,[d[8]||(d[8]=t("i",{class:"fas fa-chart-pie text-3xl mb-3"},null,-1)),t("p",null,"暂无"+r(s(a)==="daily"?"今日":"本月")+"模型使用数据",1)]))]))}},me=K(fe,[["__scopeId","data-v-ccf97793"]]),xe={class:"min-h-screen gradient-bg p-6"},ye={class:"glass-strong rounded-3xl p-6 mb-8 shadow-xl"},pe={class:"flex flex-col md:flex-row justify-between items-center gap-4"},ge={class:"flex items-center gap-3"},ve={class:"mb-8"},_e={class:"flex justify-center"},be={class:"inline-flex bg-white/10 backdrop-blur-xl rounded-full p-1 shadow-lg border border-white/20"},he={key:0,class:"tab-content"},$e={key:0,class:"mb-8"},we={class:"bg-red-500/20 border border-red-500/30 rounded-xl p-4 text-red-800 backdrop-blur-sm"},ke={key:1,class:"fade-in"},Se={class:"glass-strong rounded-3xl p-6 shadow-xl"},Te={class:"mb-6 pb-6 border-b border-gray-200"},Ie={class:"flex flex-col md:flex-row items-start md:items-center justify-between gap-4"},Ce={class:"flex gap-2"},Le=["disabled"],De=["disabled"],Pe={class:"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8"},Ae={key:1,class:"tab-content"},Ke={class:"glass-strong rounded-3xl shadow-xl"},Me={__name:"ApiStatsView",setup(w){const n=tt(),a=M(),l=$("stats"),{apiKey:c,apiId:e,loading:i,modelStatsLoading:d,oemLoading:v,error:_,statsPeriod:h,statsData:x,oemSettings:u}=A(a),{queryStats:U,switchPeriod:T,loadStatsWithApiId:R,loadOemSettings:L,reset:q}=a,E=b=>{(b.ctrlKey||b.metaKey)&&b.key==="Enter"&&(!i.value&&c.value.trim()&&U(),b.preventDefault()),b.key==="Escape"&&q()};return Z(()=>{console.log("API Stats Page loaded"),L();const b=n.query.apiId,p=n.query.apiKey;b&&b.match(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i)?(e.value=b,R()):p&&p.length>10&&(c.value=p),document.addEventListener("keydown",E)}),st(()=>{document.removeEventListener("keydown",E)}),et(c,b=>{b||a.clearData()}),(b,p)=>{const N=it("router-link");return m(),f("div",xe,[t("div",ye,[t("div",pe,[S(ot,{loading:s(v),title:s(u).siteName,subtitle:l.value==="stats"?"API Key 使用统计":"使用教程","logo-src":s(u).siteIconData||s(u).siteIcon},null,8,["loading","title","subtitle","logo-src"]),t("div",ge,[S(N,{to:"/dashboard",class:"admin-button rounded-xl px-4 py-2 text-white transition-all duration-300 flex items-center gap-2"},{default:at(()=>p[4]||(p[4]=[t("i",{class:"fas fa-cog text-sm"},null,-1),t("span",{class:"text-sm font-medium"},"管理后台",-1)])),_:1,__:[4]})])])]),t("div",ve,[t("div",_e,[t("div",be,[t("button",{class:P(["tab-pill-button",l.value==="stats"?"active":""]),onClick:p[0]||(p[0]=j=>l.value="stats")},p[5]||(p[5]=[t("i",{class:"fas fa-chart-line mr-2"},null,-1),t("span",null,"统计查询",-1)]),2),t("button",{class:P(["tab-pill-button",l.value==="tutorial"?"active":""]),onClick:p[1]||(p[1]=j=>l.value="tutorial")},p[6]||(p[6]=[t("i",{class:"fas fa-graduation-cap mr-2"},null,-1),t("span",null,"使用教程",-1)]),2)])])]),l.value==="stats"?(m(),f("div",he,[S(_t),s(_)?(m(),f("div",$e,[t("div",we,[p[7]||(p[7]=t("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),y(" "+r(s(_)),1)])])):C("",!0),s(x)?(m(),f("div",ke,[t("div",Se,[t("div",Te,[t("div",Ie,[p[10]||(p[10]=t("div",{class:"flex items-center gap-3"},[t("i",{class:"fas fa-clock text-blue-500 text-lg"}),t("span",{class:"text-lg font-medium text-gray-700"},"统计时间范围")],-1)),t("div",Ce,[t("button",{class:P([["period-btn",{active:s(h)==="daily"}],"px-6 py-2 text-sm font-medium flex items-center gap-2"]),disabled:s(i)||s(d),onClick:p[2]||(p[2]=j=>s(T)("daily"))},p[8]||(p[8]=[t("i",{class:"fas fa-calendar-day"},null,-1),y(" 今日 ",-1)]),10,Le),t("button",{class:P([["period-btn",{active:s(h)==="monthly"}],"px-6 py-2 text-sm font-medium flex items-center gap-2"]),disabled:s(i)||s(d),onClick:p[3]||(p[3]=j=>s(T)("monthly"))},p[9]||(p[9]=[t("i",{class:"fas fa-calendar-alt"},null,-1),y(" 本月 ",-1)]),10,De)])])]),S(Zt),t("div",Pe,[S(ps),S(Ws)]),S(me)])])):C("",!0)])):C("",!0),l.value==="tutorial"?(m(),f("div",Ae,[t("div",Ke,[S(lt)])])):C("",!0)])}}},Fe=K(Me,[["__scopeId","data-v-38cbdfe3"]]);export{Fe as default}; diff --git a/web/admin-spa/dist/assets/ApiStatsView-C5BOZdu2.css b/web/admin-spa/dist/assets/ApiStatsView-C5BOZdu2.css deleted file mode 100644 index 2f1904f7..00000000 --- a/web/admin-spa/dist/assets/ApiStatsView-C5BOZdu2.css +++ /dev/null @@ -1 +0,0 @@ -.api-input-wide-card[data-v-d80546e3]{background:#fffffff2;-webkit-backdrop-filter:blur(25px);backdrop-filter:blur(25px);border:1px solid rgba(255,255,255,.3);box-shadow:0 25px 50px -12px #00000040,0 0 0 1px #ffffff0d,inset 0 1px #ffffff1a;transition:all .3s cubic-bezier(.4,0,.2,1)}.api-input-wide-card[data-v-d80546e3]:hover{box-shadow:0 32px 64px -12px #00000059,0 0 0 1px #ffffff14,inset 0 1px #ffffff26;transform:translateY(-1px)}.wide-card-title h2[data-v-d80546e3]{color:#1f2937;text-shadow:0 1px 2px rgba(0,0,0,.1);font-weight:700}.wide-card-title p[data-v-d80546e3]{color:#4b5563;text-shadow:0 1px 1px rgba(0,0,0,.05)}.wide-card-title .fas.fa-chart-line[data-v-d80546e3]{color:#3b82f6;text-shadow:0 1px 2px rgba(59,130,246,.2)}.api-input-grid[data-v-d80546e3]{align-items:end;gap:1rem}.wide-card-input[data-v-d80546e3]{background:#fffffff2;border:2px solid rgba(255,255,255,.4);border-radius:12px;padding:14px 16px;font-size:16px;transition:all .3s ease;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);color:#1f2937;box-shadow:0 4px 6px -1px #0000001a}.wide-card-input[data-v-d80546e3]::-moz-placeholder{color:#9ca3af}.wide-card-input[data-v-d80546e3]::placeholder{color:#9ca3af}.wide-card-input[data-v-d80546e3]:focus{outline:none;border-color:#60a5fa;box-shadow:0 0 0 3px #60a5fa33,0 10px 15px -3px #0000001a;background:#fff}.btn[data-v-d80546e3]{font-weight:500;border-radius:12px;border:none;cursor:pointer;transition:all .3s ease;position:relative;overflow:hidden;letter-spacing:.025em}.btn-query[data-v-d80546e3]{padding:14px 24px;font-size:16px}.btn-primary[data-v-d80546e3]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;box-shadow:0 10px 15px -3px #667eea4d,0 4px 6px -2px #667eea0d}.btn-primary[data-v-d80546e3]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 20px 25px -5px #667eea4d,0 10px 10px -5px #667eea1a}.btn-primary[data-v-d80546e3]:disabled{opacity:.6;cursor:not-allowed;transform:none}.security-notice[data-v-d80546e3]{background:#ffffff26;border:1px solid rgba(255,255,255,.25);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:8px;padding:12px 16px;color:#374151;font-size:.875rem;transition:all .3s ease}.security-notice[data-v-d80546e3]:hover{background:#fff3;border-color:#ffffff59}.security-notice .fas.fa-shield-alt[data-v-d80546e3]{color:#10b981;text-shadow:0 1px 2px rgba(16,185,129,.2)}.loading-spinner[data-v-d80546e3]{animation:spin-d80546e3 1s linear infinite;filter:drop-shadow(0 0 4px rgba(255,255,255,.5))}@keyframes spin-d80546e3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 768px){.api-input-wide-card[data-v-d80546e3]{padding:1.25rem}.wide-card-title[data-v-d80546e3]{margin-bottom:1.25rem}.wide-card-title h2[data-v-d80546e3]{font-size:1.5rem}.wide-card-title p[data-v-d80546e3]{font-size:.875rem}.api-input-grid[data-v-d80546e3]{gap:1rem}.wide-card-input[data-v-d80546e3]{padding:12px 14px;font-size:15px}.btn-query[data-v-d80546e3]{padding:12px 20px;font-size:15px}.security-notice[data-v-d80546e3]{padding:10px 14px;font-size:.8rem}}@media (max-width: 480px){.api-input-wide-card[data-v-d80546e3]{padding:1rem}.wide-card-title h2[data-v-d80546e3]{font-size:1.25rem}.wide-card-title p[data-v-d80546e3]{font-size:.8rem}.wide-card-input[data-v-d80546e3]{padding:10px 12px;font-size:14px}.btn-query[data-v-d80546e3]{padding:10px 16px;font-size:14px}}.card[data-v-e7abc110]{background:#fffffff2;border-radius:16px;border:1px solid rgba(255,255,255,.2);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;overflow:hidden;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1)}.card[data-v-e7abc110]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.card[data-v-e7abc110]:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #00000026,0 10px 10px -5px #00000014}.stat-card[data-v-e7abc110]{background:linear-gradient(135deg,#fffffff2,#fffc);border-radius:20px;border:1px solid rgba(255,255,255,.3);padding:24px;position:relative;overflow:hidden;transition:all .3s ease}.stat-card[data-v-e7abc110]:before{content:"";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:radial-gradient(circle,rgba(255,255,255,.1) 0%,transparent 70%);opacity:0;transition:opacity .3s ease}.stat-card[data-v-e7abc110]:hover{transform:translateY(-4px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.stat-card[data-v-e7abc110]:hover:before{opacity:1}@media (max-width: 768px){.card[data-v-e7abc110]{margin-bottom:1rem}.stat-card[data-v-e7abc110]{padding:.75rem}.stat-card .text-3xl[data-v-e7abc110]{font-size:1.5rem}}@media (max-width: 480px){.card[data-v-e7abc110]{padding:1rem}.stat-card[data-v-e7abc110]{padding:.5rem}.stat-card .text-3xl[data-v-e7abc110]{font-size:1.25rem}.stat-card .text-sm[data-v-e7abc110]{font-size:.75rem}}.card[data-v-ff744b2f]{background:#fffffff2;border-radius:16px;border:1px solid rgba(255,255,255,.2);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;overflow:hidden;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1)}.card[data-v-ff744b2f]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.card[data-v-ff744b2f]:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #00000026,0 10px 10px -5px #00000014}.card[data-v-f97c29cf]{background:#fffffff2;border-radius:16px;border:1px solid rgba(255,255,255,.2);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;overflow:hidden;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1)}.card[data-v-f97c29cf]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.card[data-v-f97c29cf]:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #00000026,0 10px 10px -5px #00000014}.card[data-v-ccf97793]{background:#fffffff2;border-radius:16px;border:1px solid rgba(255,255,255,.2);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;overflow:hidden;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1)}.card[data-v-ccf97793]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.card[data-v-ccf97793]:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #00000026,0 10px 10px -5px #00000014}.model-usage-item[data-v-ccf97793]{background:#fffffff2;border:1px solid rgba(255,255,255,.2);border-radius:12px;padding:16px;transition:all .3s ease;position:relative;overflow:hidden}.model-usage-item[data-v-ccf97793]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.model-usage-item[data-v-ccf97793]:hover{transform:translateY(-2px);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;border-color:#ffffff4d}.loading-spinner[data-v-ccf97793]{animation:spin-ccf97793 1s linear infinite;filter:drop-shadow(0 0 4px rgba(255,255,255,.5))}@keyframes spin-ccf97793{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 768px){.model-usage-item .grid[data-v-ccf97793]{grid-template-columns:1fr 1fr;gap:.5rem}}@media (max-width: 480px){.model-usage-item .grid[data-v-ccf97793]{grid-template-columns:1fr}}.gradient-bg[data-v-38cbdfe3]{background:linear-gradient(135deg,#667eea,#764ba2,#f093fb);background-attachment:fixed;min-height:100vh;position:relative}.gradient-bg[data-v-38cbdfe3]:before{content:"";position:fixed;top:0;left:0;right:0;bottom:0;background:radial-gradient(circle at 20% 80%,rgba(240,147,251,.2) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(102,126,234,.2) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(118,75,162,.1) 0%,transparent 50%);pointer-events:none;z-index:0}.glass-strong[data-v-38cbdfe3]{background:#fffffff2;-webkit-backdrop-filter:blur(25px);backdrop-filter:blur(25px);border:1px solid rgba(255,255,255,.3);box-shadow:0 25px 50px -12px #00000040,0 0 0 1px #ffffff0d,inset 0 1px #ffffff1a;position:relative;z-index:1}.header-title[data-v-38cbdfe3]{background:linear-gradient(135deg,#667eea,#764ba2);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:700;letter-spacing:-.025em}.admin-button[data-v-38cbdfe3]{background:linear-gradient(135deg,#667eea,#764ba2);border:1px solid rgba(255,255,255,.2);text-decoration:none;box-shadow:0 4px 6px -1px #667eea4d,0 2px 4px -1px #667eea1a;position:relative;overflow:hidden}.admin-button[data-v-38cbdfe3]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent);transition:left .5s}.admin-button[data-v-38cbdfe3]:hover{transform:translateY(-2px);box-shadow:0 10px 15px -3px #667eea66,0 4px 6px -2px #667eea26}.admin-button[data-v-38cbdfe3]:hover:before{left:100%}.period-btn[data-v-38cbdfe3]{position:relative;overflow:hidden;border-radius:12px;font-weight:500;letter-spacing:.025em;transition:all .3s ease;border:none;cursor:pointer}.period-btn.active[data-v-38cbdfe3]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;box-shadow:0 10px 15px -3px #667eea4d,0 4px 6px -2px #667eea0d;transform:translateY(-1px)}.period-btn[data-v-38cbdfe3]:not(.active){color:#374151;background:transparent}.period-btn[data-v-38cbdfe3]:not(.active):hover{background:#ffffff1a;color:#1f2937}.tab-pill-button[data-v-38cbdfe3]{padding:.625rem 1.25rem;border-radius:9999px;font-weight:500;font-size:.875rem;color:#fffc;background:transparent;border:none;cursor:pointer;transition:all .2s ease;position:relative;display:inline-flex;align-items:center;white-space:nowrap}.tab-pill-button[data-v-38cbdfe3]:hover{color:#fff;background:#ffffff1a}.tab-pill-button.active[data-v-38cbdfe3]{background:#fff;color:#764ba2;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.tab-pill-button i[data-v-38cbdfe3]{font-size:.875rem}.tab-content[data-v-38cbdfe3]{animation:tabFadeIn-38cbdfe3 .4s ease-out}@keyframes tabFadeIn-38cbdfe3{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.fade-in[data-v-38cbdfe3]{animation:fadeIn-38cbdfe3 .6s ease-out}@keyframes fadeIn-38cbdfe3{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}} diff --git a/web/admin-spa/dist/assets/DashboardView-B39lq_zZ.css b/web/admin-spa/dist/assets/DashboardView-B39lq_zZ.css deleted file mode 100644 index cd677052..00000000 --- a/web/admin-spa/dist/assets/DashboardView-B39lq_zZ.css +++ /dev/null @@ -1 +0,0 @@ -.custom-date-picker[data-v-e2cbd0e3] .el-input__inner{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.custom-date-picker[data-v-e2cbd0e3] .el-input__inner:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.custom-date-picker[data-v-e2cbd0e3] .el-input__inner{font-size:13px;padding:0 10px}.custom-date-picker[data-v-e2cbd0e3] .el-range-separator{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1));padding:0 2px}.custom-date-picker[data-v-e2cbd0e3] .el-range-input{font-size:13px}@keyframes spin-e2cbd0e3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-spin[data-v-e2cbd0e3]{animation:spin-e2cbd0e3 1s linear infinite} diff --git a/web/admin-spa/dist/assets/DashboardView-BM1-V-So.js b/web/admin-spa/dist/assets/DashboardView-BM1-V-So.js deleted file mode 100644 index 129181fb..00000000 --- a/web/admin-spa/dist/assets/DashboardView-BM1-V-So.js +++ /dev/null @@ -1 +0,0 @@ -import{E as Dt}from"./element-plus-B8Fs_0jW.js";import{aR as wt,r as T,c as Tt,aW as _t,o as mt,q as St,D as ot,V as Rt,x as w,z as t,P as p,u as a,O as k,L as z,Q as bt,ac as kt,C as G,R as $t,K as At,al as Mt,y as _}from"./vue-vendor-CKToUHZx.js";import{a as J,_ as Ut}from"./index-9AMT1Op2.js";import{s as xt}from"./toast-BvwA7Mwb.js";import{C as vt}from"./chart-Cor9iTVD.js";import"./vendor-BDiMbLwQ.js";const Kt=wt("dashboard",()=>{const nt=T(!1),N=T({totalApiKeys:0,activeApiKeys:0,totalAccounts:0,activeAccounts:0,rateLimitedAccounts:0,todayRequests:0,totalRequests:0,todayTokens:0,todayInputTokens:0,todayOutputTokens:0,totalTokens:0,totalInputTokens:0,totalOutputTokens:0,totalCacheCreateTokens:0,totalCacheReadTokens:0,todayCacheCreateTokens:0,todayCacheReadTokens:0,systemRPM:0,systemTPM:0,realtimeRPM:0,realtimeTPM:0,metricsWindow:5,isHistoricalMetrics:!1,systemStatus:"正常",uptime:0,systemTimezone:8}),c=T({todayCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}}}),lt=T([]),H=T([]),X=T([]),M=T({data:[],topApiKeys:[],totalApiKeys:0}),n=T({type:"preset",preset:"7days",customStart:"",customEnd:"",customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}),S=T("day"),q=T("requests"),I=T([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),pt=Tt(()=>{const s=N.value.uptime,r=Math.floor(s/86400),l=Math.floor(s%86400/3600),i=Math.floor(s%3600/60);return r>0?`${r}天 ${l}小时`:l>0?`${l}小时 ${i}分钟`:`${i}分钟`});function A(s,r=!0){const l=s.getFullYear(),i=s.getMonth(),o=s.getDate();return r?new Date(Date.UTC(l,i,o-1,16,0,0,0)):new Date(Date.UTC(l,i,o,15,59,59,999))}async function yt(){nt.value=!0;try{const[s,r,l]=await Promise.all([J.get("/admin/dashboard"),J.get("/admin/usage-costs?period=today"),J.get("/admin/usage-costs?period=all")]);if(s.success){const i=s.data.overview||{},o=s.data.recentActivity||{},d=s.data.systemAverages||{},u=s.data.realtimeMetrics||{},f=s.data.systemHealth||{};N.value={totalApiKeys:i.totalApiKeys||0,activeApiKeys:i.activeApiKeys||0,totalAccounts:i.totalClaudeAccounts||0,activeAccounts:i.activeClaudeAccounts||0,rateLimitedAccounts:i.rateLimitedClaudeAccounts||0,todayRequests:o.requestsToday||0,totalRequests:i.totalRequestsUsed||0,todayTokens:o.tokensToday||0,todayInputTokens:o.inputTokensToday||0,todayOutputTokens:o.outputTokensToday||0,totalTokens:i.totalTokensUsed||0,totalInputTokens:i.totalInputTokensUsed||0,totalOutputTokens:i.totalOutputTokensUsed||0,totalCacheCreateTokens:i.totalCacheCreateTokensUsed||0,totalCacheReadTokens:i.totalCacheReadTokensUsed||0,todayCacheCreateTokens:o.cacheCreateTokensToday||0,todayCacheReadTokens:o.cacheReadTokensToday||0,systemRPM:d.rpm||0,systemTPM:d.tpm||0,realtimeRPM:u.rpm||0,realtimeTPM:u.tpm||0,metricsWindow:u.windowMinutes||5,isHistoricalMetrics:u.isHistorical||!1,systemStatus:f.redisConnected?"正常":"异常",uptime:f.uptime||0,systemTimezone:s.data.systemTimezone||8}}r.success&&l.success&&(c.value={todayCosts:r.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:l.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}}})}catch(s){console.error("加载仪表板数据失败:",s)}finally{nt.value=!1}}async function rt(s=7,r="day"){try{let l="/admin/usage-trend?";if(r==="hour")if(l+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const o=d=>{const[f,m]=d.split(" "),[$,P,F]=f.split("-").map(Number),[K,L,B]=m.split(":").map(Number);return new Date(Date.UTC($,P-1,F,K-8,L,B)).toISOString()};l+=`&startDate=${encodeURIComponent(o(n.value.customRange[0]))}`,l+=`&endDate=${encodeURIComponent(o(n.value.customRange[1]))}`}else{const o=new Date;let d,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(o),d=new Date(o.getTime()-24*60*60*1e3);break;case"yesterday":const f=new Date;f.setDate(f.getDate()-1),d=A(f,!0),u=A(f,!1);break;case"dayBefore":const m=new Date;m.setDate(m.getDate()-2),d=A(m,!0),u=A(m,!1);break;default:d=new Date(o.getTime()-24*60*60*1e3),u=o}else d=new Date(o.getTime()-s*24*60*60*1e3),u=o;l+=`&startDate=${encodeURIComponent(d.toISOString())}`,l+=`&endDate=${encodeURIComponent(u.toISOString())}`}else l+=`granularity=day&days=${s}`;const i=await J.get(l);i.success&&(H.value=i.data)}catch(l){console.error("加载使用趋势失败:",l)}}async function it(s="daily"){try{const r=await J.get(`/admin/model-stats?period=${s}`);r.success&&(X.value=r.data)}catch(r){console.error("加载模型统计失败:",r)}}async function tt(s="requests"){try{let r="/admin/api-keys-usage-trend?",l=7;if(S.value==="hour")if(r+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const o=d=>{const[f,m]=d.split(" "),[$,P,F]=f.split("-").map(Number),[K,L,B]=m.split(":").map(Number);return new Date(Date.UTC($,P-1,F,K-8,L,B)).toISOString()};r+=`&startDate=${encodeURIComponent(o(n.value.customRange[0]))}`,r+=`&endDate=${encodeURIComponent(o(n.value.customRange[1]))}`}else{const o=new Date;let d,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(o),d=new Date(o.getTime()-24*60*60*1e3);break;case"yesterday":const f=new Date;f.setDate(f.getDate()-1),d=A(f,!0),u=A(f,!1);break;case"dayBefore":const m=new Date;m.setDate(m.getDate()-2),d=A(m,!0),u=A(m,!1);break;default:d=new Date(o.getTime()-24*60*60*1e3),u=o}else d=new Date(o.getTime()-24*60*60*1e3),u=o;r+=`&startDate=${encodeURIComponent(d.toISOString())}`,r+=`&endDate=${encodeURIComponent(u.toISOString())}`}else l=n.value.type==="preset"?n.value.preset==="today"?1:n.value.preset==="7days"?7:30:Q(n.value.customStart,n.value.customEnd),r+=`granularity=day&days=${l}`;r+=`&metric=${s}`;const i=await J.get(r);i.success&&(M.value={data:i.data||[],topApiKeys:i.topApiKeys||[],totalApiKeys:i.totalApiKeys||0})}catch(r){console.error("加载API Keys趋势失败:",r)}}function j(s){n.value.type="preset",n.value.preset=s;const r=n.value.presetOptions.find(l=>l.value===s);if(r){const l=new Date;let i,o;if(S.value==="hour")switch(s){case"last24h":o=new Date(l),i=new Date(l.getTime()-24*60*60*1e3);break;case"yesterday":const d=new Date;d.setDate(d.getDate()-1),i=A(d,!0),o=A(d,!1);break;case"dayBefore":const u=new Date;u.setDate(u.getDate()-2),i=A(u,!0),o=A(u,!1);break}else i=new Date(l),o=new Date(l),s==="today"?(i.setHours(0,0,0,0),o.setHours(23,59,59,999)):(i.setDate(l.getDate()-(r.days-1)),i.setHours(0,0,0,0),o.setHours(23,59,59,999));if(n.value.customStart=i.toISOString().split("T")[0],n.value.customEnd=o.toISOString().split("T")[0],S.value==="hour"&&(s==="yesterday"||s==="dayBefore")){const d=new Date;s==="yesterday"?d.setDate(d.getDate()-1):d.setDate(d.getDate()-2);const u=d.getFullYear(),f=String(d.getMonth()+1).padStart(2,"0"),m=String(d.getDate()).padStart(2,"0");n.value.customRange=[`${u}-${f}-${m} 00:00:00`,`${u}-${f}-${m} 23:59:59`]}else{const d=u=>{const $=new Date(u.getTime()+288e5),P=$.getUTCFullYear(),F=String($.getUTCMonth()+1).padStart(2,"0"),K=String($.getUTCDate()).padStart(2,"0"),L=String($.getUTCHours()).padStart(2,"0"),B=String($.getUTCMinutes()).padStart(2,"0"),Z=String($.getUTCSeconds()).padStart(2,"0");return`${P}-${F}-${K} ${L}:${B}:${Z}`};n.value.customRange=[d(i),d(o)]}}E()}function ft(s){if(s&&s.length===2){n.value.type="custom",n.value.preset="",n.value.customRange=s,n.value.customStart=s[0].split(" ")[0],n.value.customEnd=s[1].split(" ")[0],N.value.systemTimezone;const r=o=>{const[d,u]=o.split(" "),[f,m,$]=d.split("-").map(Number),[P,F,K]=u.split(":").map(Number);return new Date(f,m-1,$,P,F,K)},l=r(s[0]),i=r(s[1]);if(S.value==="hour"){if((i-l)/36e5>24){xt("小时粒度下日期范围不能超过24小时","warning");return}}else if(Math.ceil((i-l)/864e5)+1>31){xt("日期范围不能超过 31 天","warning");return}E()}else s===null&&j(S.value==="hour"?"last24h":"7days")}function et(s){if(S.value=s,s==="hour"){if(n.value.presetOptions=[{value:"last24h",label:"近24小时",hours:24},{value:"yesterday",label:"昨天",hours:24},{value:"dayBefore",label:"前天",hours:24}],n.value.type==="custom"&&n.value.customRange&&n.value.customRange.length===2){const r=new Date(n.value.customRange[0]);if((new Date(n.value.customRange[1])-r)/(1e3*60*60)>24){xt("小时粒度下日期范围不能超过24小时,已切换到近24小时","warning"),j("last24h");return}}if(["today","7days","30days"].includes(n.value.preset)){j("last24h");return}}else if(n.value.presetOptions=[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}],["last24h","yesterday","dayBefore"].includes(n.value.preset)){j("7days");return}E()}async function E(){let s,r="monthly";if(n.value.type==="preset"){const l=n.value.presetOptions.find(i=>i.value===n.value.preset);S.value==="hour"?(s=1,r="daily"):(s=l?l.days:7,n.value.preset==="today"?r="daily":r="monthly")}else{if(S.value==="hour"){const l=new Date(n.value.customRange[0]),i=new Date(n.value.customRange[1]),o=Math.ceil((i-l)/(1e3*60*60));s=Math.ceil(o/24)||1}else s=Q(n.value.customStart,n.value.customEnd);r="daily"}await Promise.all([rt(s,S.value),it(r),tt(q.value)])}function Q(s,r){if(!s||!r)return 7;const l=new Date(s),i=new Date(r),o=Math.abs(i-l);return Math.ceil(o/(1e3*60*60*24))||7}function Y(s){return s>new Date}return{loading:nt,dashboardData:N,costsData:c,modelStats:lt,trendData:H,dashboardModelStats:X,apiKeysTrendData:M,dateFilter:n,trendGranularity:S,apiKeysTrendMetric:q,defaultTime:I,formattedUptime:pt,loadDashboardData:yt,loadUsageTrend:rt,loadModelStats:it,loadApiKeysTrend:tt,setDateFilterPreset:j,onCustomDateRangeChange:ft,setTrendGranularity:et,refreshChartsData:E,disabledDate:Y}}),It={class:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6 mb-8"},Pt={class:"stat-card"},Ft={class:"flex items-center justify-between"},Ot={class:"text-3xl font-bold text-gray-900"},Bt={class:"text-xs text-gray-500 mt-1"},zt={class:"stat-card"},Ht={class:"flex items-center justify-between"},qt={class:"text-3xl font-bold text-gray-900"},Et={class:"text-xs text-gray-500 mt-1"},Lt={key:0,class:"text-yellow-600"},Vt={class:"stat-card"},Nt={class:"flex items-center justify-between"},jt={class:"text-3xl font-bold text-gray-900"},Yt={class:"text-xs text-gray-500 mt-1"},Wt={class:"stat-card"},Gt={class:"flex items-center justify-between"},Qt={class:"text-3xl font-bold text-green-600"},Zt={class:"text-xs text-gray-500 mt-1"},Jt={class:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6 mb-8"},Xt={class:"stat-card"},te={class:"flex items-center justify-between"},ee={class:"flex-1 mr-8"},se={class:"flex items-baseline gap-2 mb-2 flex-wrap"},ae={class:"text-3xl font-bold text-blue-600"},oe={class:"text-sm text-green-600 font-medium"},ne={class:"text-xs text-gray-500"},le={class:"flex justify-between items-center flex-wrap gap-x-4"},re={class:"font-medium"},ie={class:"font-medium"},de={key:0,class:"text-purple-600"},ue={class:"font-medium"},ce={key:1,class:"text-purple-600"},me={class:"font-medium"},pe={class:"stat-card"},ye={class:"flex items-center justify-between"},fe={class:"flex-1 mr-8"},ge={class:"flex items-baseline gap-2 mb-2 flex-wrap"},xe={class:"text-3xl font-bold text-emerald-600"},ve={class:"text-sm text-green-600 font-medium"},he={class:"text-xs text-gray-500"},be={class:"flex justify-between items-center flex-wrap gap-x-4"},ke={class:"font-medium"},Te={class:"font-medium"},Ce={key:0,class:"text-purple-600"},De={class:"font-medium"},we={key:1,class:"text-purple-600"},_e={class:"font-medium"},Se={class:"stat-card"},Re={class:"flex items-center justify-between"},$e={class:"text-sm font-semibold text-gray-600 mb-1"},Ae={class:"text-xs text-gray-400"},Me={class:"text-3xl font-bold text-orange-600"},Ue={class:"text-xs text-gray-500 mt-1"},Ke={key:0,class:"text-yellow-600"},Ie={class:"stat-card"},Pe={class:"flex items-center justify-between"},Fe={class:"text-sm font-semibold text-gray-600 mb-1"},Oe={class:"text-xs text-gray-400"},Be={class:"text-3xl font-bold text-rose-600"},ze={class:"text-xs text-gray-500 mt-1"},He={key:0,class:"text-yellow-600"},qe={class:"mb-8"},Ee={class:"flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-6"},Le={class:"flex flex-wrap gap-2 items-center"},Ve={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ne=["onClick"],je={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ye={class:"flex items-center gap-2"},We={key:0,class:"text-xs text-orange-600"},Ge={class:"flex items-center gap-2"},Qe={class:"flex items-center bg-gray-100 rounded-lg px-3 py-1"},Ze={class:"relative inline-flex items-center cursor-pointer"},Je={class:"ml-2.5 text-sm font-medium text-gray-600 select-none flex items-center gap-1"},Xe=["disabled"],ts={class:"grid grid-cols-1 lg:grid-cols-2 gap-6"},es={class:"card p-6"},ss={class:"relative",style:{height:"300px"}},as={class:"card p-6"},os={key:0,class:"text-center py-8"},ns={key:1,class:"overflow-auto max-h-[300px]"},ls={class:"min-w-full"},rs={class:"divide-y divide-gray-200"},is={class:"px-4 py-2 text-sm text-gray-900"},ds={class:"px-4 py-2 text-sm text-gray-600 text-right"},us={class:"px-4 py-2 text-sm text-gray-600 text-right"},cs={class:"px-4 py-2 text-sm text-green-600 text-right font-medium"},ms={class:"px-4 py-2 text-sm font-medium text-right"},ps={class:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},ys={class:"mb-8"},fs={class:"card p-6"},gs={style:{height:"300px"}},xs={class:"mb-8"},vs={class:"card p-6"},hs={class:"flex items-center justify-between mb-4"},bs={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},ks={class:"mb-4 text-sm text-gray-600"},Ts={key:0},Cs={key:1},Ds={style:{height:"350px"}},ws={__name:"DashboardView",setup(nt){const N=Kt(),{dashboardData:c,costsData:lt,dashboardModelStats:H,trendData:X,apiKeysTrendData:M,formattedUptime:n,dateFilter:S,trendGranularity:q,apiKeysTrendMetric:I,defaultTime:pt}=_t(N),{loadDashboardData:A,loadApiKeysTrend:yt,setDateFilterPreset:rt,onCustomDateRangeChange:it,setTrendGranularity:tt,refreshChartsData:j,disabledDate:ft}=N,et=T(null),E=T(null),Q=T(null);let Y=null,s=null,r=null;const l=T(!1),i=T(30),o=T(null),d=T(0),u=T(null),f=T(!1);Tt(()=>!l.value||d.value<=0?"":`${d.value}秒后刷新`);function m(v){return v>=1e6?(v/1e6).toFixed(2)+"M":v>=1e3?(v/1e3).toFixed(2)+"K":v.toString()}function $(v,e){if(!e||e.length===0)return 0;const C=e.reduce((g,V)=>g+V.allTokens,0);return C===0?0:(v/C*100).toFixed(1)}function P(){if(!et.value)return;Y&&Y.destroy();const v=H.value||[],e={labels:v.map(C=>C.model),datasets:[{data:v.map(C=>C.allTokens),backgroundColor:["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],borderWidth:0}]};Y=new vt(et.value,{type:"doughnut",data:e,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:15,usePointStyle:!0,font:{size:12}}},tooltip:{callbacks:{label:function(C){const g=C.label||"",V=m(C.parsed),st=$(C.parsed,v);return`${g}: ${V} (${st}%)`}}}}}})}function F(){var D;if(!E.value)return;s&&s.destroy();const v=X.value||[],e=v.map(y=>y.inputTokens||0),C=v.map(y=>y.outputTokens||0),g=v.map(y=>y.cacheCreateTokens||0),V=v.map(y=>y.cacheReadTokens||0),st=v.map(y=>y.requests||0),dt=v.map(y=>y.cost||0),ut=(D=v[0])!=null&&D.date?"date":"hour",U={labels:v.map(y=>{if(y.label)return y.label;if(ut==="hour"){const x=new Date(y.hour),R=String(x.getMonth()+1).padStart(2,"0"),W=String(x.getDate()).padStart(2,"0"),ct=String(x.getHours()).padStart(2,"0");return`${R}/${W} ${ct}:00`}const b=y.date;if(b&&b.includes("-")){const x=b.split("-");if(x.length>=3)return`${x[1]}/${x[2]}`}return y.date}),datasets:[{label:"输入Token",data:e,borderColor:"rgb(102, 126, 234)",backgroundColor:"rgba(102, 126, 234, 0.1)",tension:.3},{label:"输出Token",data:C,borderColor:"rgb(240, 147, 251)",backgroundColor:"rgba(240, 147, 251, 0.1)",tension:.3},{label:"缓存创建Token",data:g,borderColor:"rgb(59, 130, 246)",backgroundColor:"rgba(59, 130, 246, 0.1)",tension:.3},{label:"缓存读取Token",data:V,borderColor:"rgb(147, 51, 234)",backgroundColor:"rgba(147, 51, 234, 0.1)",tension:.3},{label:"费用 (USD)",data:dt,borderColor:"rgb(34, 197, 94)",backgroundColor:"rgba(34, 197, 94, 0.1)",tension:.3,yAxisID:"y2"},{label:"请求数",data:st,borderColor:"rgb(16, 185, 129)",backgroundColor:"rgba(16, 185, 129, 0.1)",tension:.3,yAxisID:"y1"}]};s=new vt(E.value,{type:"line",data:U,options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},plugins:{title:{display:!0,text:"Token使用趋势",font:{size:16,weight:"bold"}},legend:{position:"top"},tooltip:{mode:"index",intersect:!1,itemSort:function(y,b){const x=y.dataset.label||"",R=b.dataset.label||"";return x==="费用 (USD)"||R==="费用 (USD)"?x==="费用 (USD)"?-1:1:x==="请求数"||R==="请求数"?x==="请求数"?1:-1:b.parsed.y-y.parsed.y},callbacks:{label:function(y){const b=y.dataset.label||"";let x=y.parsed.y;return b==="费用 (USD)"?x<.01?b+": $"+x.toFixed(6):b+": $"+x.toFixed(4):b==="请求数"?b+": "+x.toLocaleString()+" 次":x>=1e6?b+": "+(x/1e6).toFixed(2)+"M tokens":x>=1e3?b+": "+(x/1e3).toFixed(2)+"K tokens":b+": "+x.toLocaleString()+" tokens"}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:q.value==="hour"?"时间":"日期"}},y:{type:"linear",display:!0,position:"left",title:{display:!0,text:"Token数量"},ticks:{callback:function(y){return m(y)}}},y1:{type:"linear",display:!0,position:"right",title:{display:!0,text:"请求数"},grid:{drawOnChartArea:!1},ticks:{callback:function(y){return y.toLocaleString()}}},y2:{type:"linear",display:!1,position:"right"}}}})}function K(){var dt,ut;if(!Q.value)return;r&&r.destroy();const v=M.value.data||[],e=I.value,C=["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],g=((dt=M.value.topApiKeys)==null?void 0:dt.map((h,U)=>{var b,x;const D=M.value.data.map(R=>!R.apiKeys||!R.apiKeys[h]?0:e==="tokens"?R.apiKeys[h].tokens:R.apiKeys[h].requests||0);return{label:((x=(b=M.value.data.find(R=>R.apiKeys&&R.apiKeys[h]))==null?void 0:b.apiKeys[h])==null?void 0:x.name)||`API Key ${h}`,data:D,borderColor:C[U%C.length],backgroundColor:C[U%C.length]+"20",tension:.4,fill:!1}}))||[],V=(ut=v[0])!=null&&ut.date?"date":"hour",st={labels:v.map(h=>{if(h.label)return h.label;if(V==="hour"){const D=new Date(h.hour),y=String(D.getMonth()+1).padStart(2,"0"),b=String(D.getDate()).padStart(2,"0"),x=String(D.getHours()).padStart(2,"0");return`${y}/${b} ${x}:00`}const U=h.date;if(U&&U.includes("-")){const D=U.split("-");if(D.length>=3)return`${D[1]}/${D[2]}`}return h.date}),datasets:g};r=new vt(Q.value,{type:"line",data:st,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:20,usePointStyle:!0,font:{size:12}}},tooltip:{mode:"index",intersect:!1,itemSort:function(h,U){return U.parsed.y-h.parsed.y},callbacks:{label:function(h){var ct;const U=h.dataset.label||"",D=h.parsed.y,y=h.dataIndex,b=M.value.data[y],R=h.chart.data.datasets.map((O,at)=>({value:O.data[y]||0,index:at})).sort((O,at)=>at.value-O.value).findIndex(O=>O.index===h.datasetIndex)+1;let W="";if(R===1?W="🥇 ":R===2?W="🥈 ":R===3&&(W="🥉 "),I.value==="tokens"){let O="";D>=1e6?O=(D/1e6).toFixed(2)+"M":D>=1e3?O=(D/1e3).toFixed(2)+"K":O=D.toLocaleString();const at=M.value.topApiKeys[h.datasetIndex],gt=(ct=b==null?void 0:b.apiKeys)==null?void 0:ct[at],Ct=(gt==null?void 0:gt.formattedCost)||"$0.00";return`${W}${U}: ${O} tokens (${Ct})`}else return`${W}${U}: ${D.toLocaleString()} 次`}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:q.value==="hour"?"时间":"日期"}},y:{beginAtZero:!0,title:{display:!0,text:I.value==="tokens"?"Token 数量":"请求次数"},ticks:{callback:function(h){return m(h)}}}}}})}async function L(){await yt(I.value),await ot(),K()}mt(H,()=>{ot(()=>P())}),mt(X,()=>{ot(()=>F())}),mt(M,()=>{ot(()=>K())});async function B(){if(!f.value){f.value=!0;try{await Promise.all([A(),j()])}finally{f.value=!1}}}function Z(){l.value&&(d.value=i.value,u.value&&clearInterval(u.value),o.value&&clearTimeout(o.value),u.value=setInterval(()=>{d.value--,d.value<=0&&clearInterval(u.value)},1e3),o.value=setTimeout(async()=>{await B(),l.value&&Z()},i.value*1e3))}function ht(){u.value&&(clearInterval(u.value),u.value=null),o.value&&(clearTimeout(o.value),o.value=null),d.value=0}return mt(l,v=>{v?Z():ht()}),St(async()=>{await B(),await ot(),P(),F(),K()}),Rt(()=>{ht(),Y&&Y.destroy(),s&&s.destroy(),r&&r.destroy()}),(v,e)=>{const C=Dt;return _(),w("div",null,[t("div",It,[t("div",Pt,[t("div",Ft,[t("div",null,[e[7]||(e[7]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 总API Keys ",-1)),t("p",Ot,p(a(c).totalApiKeys),1),t("p",Bt," 活跃: "+p(a(c).activeApiKeys||0),1)]),e[8]||(e[8]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-blue-500 to-blue-600"},[t("i",{class:"fas fa-key"})],-1))])]),t("div",zt,[t("div",Ht,[t("div",null,[e[9]||(e[9]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 服务账户 ",-1)),t("p",qt,p(a(c).totalAccounts),1),t("p",Et,[k(" 活跃: "+p(a(c).activeAccounts||0)+" ",1),a(c).rateLimitedAccounts>0?(_(),w("span",Lt," | 限流: "+p(a(c).rateLimitedAccounts),1)):z("",!0)])]),e[10]||(e[10]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-green-500 to-green-600"},[t("i",{class:"fas fa-user-circle"})],-1))])]),t("div",Vt,[t("div",Nt,[t("div",null,[e[11]||(e[11]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 今日请求 ",-1)),t("p",jt,p(a(c).todayRequests),1),t("p",Yt," 总请求: "+p(m(a(c).totalRequests||0)),1)]),e[12]||(e[12]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-purple-500 to-purple-600"},[t("i",{class:"fas fa-chart-line"})],-1))])]),t("div",Wt,[t("div",Gt,[t("div",null,[e[13]||(e[13]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 系统状态 ",-1)),t("p",Qt,p(a(c).systemStatus),1),t("p",Zt," 运行时间: "+p(a(n)),1)]),e[14]||(e[14]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-yellow-500 to-orange-500"},[t("i",{class:"fas fa-heartbeat"})],-1))])])]),t("div",Jt,[t("div",Xt,[t("div",te,[t("div",ee,[e[19]||(e[19]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 今日Token ",-1)),t("div",se,[t("p",ae,p(m((a(c).todayInputTokens||0)+(a(c).todayOutputTokens||0)+(a(c).todayCacheCreateTokens||0)+(a(c).todayCacheReadTokens||0))),1),t("span",oe,"/ "+p(a(lt).todayCosts.formatted.totalCost),1)]),t("div",ne,[t("div",le,[t("span",null,[e[15]||(e[15]=k("输入: ",-1)),t("span",re,p(m(a(c).todayInputTokens||0)),1)]),t("span",null,[e[16]||(e[16]=k("输出: ",-1)),t("span",ie,p(m(a(c).todayOutputTokens||0)),1)]),(a(c).todayCacheCreateTokens||0)>0?(_(),w("span",de,[e[17]||(e[17]=k("缓存创建: ",-1)),t("span",ue,p(m(a(c).todayCacheCreateTokens||0)),1)])):z("",!0),(a(c).todayCacheReadTokens||0)>0?(_(),w("span",ce,[e[18]||(e[18]=k("缓存读取: ",-1)),t("span",me,p(m(a(c).todayCacheReadTokens||0)),1)])):z("",!0)])])]),e[20]||(e[20]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-indigo-500 to-indigo-600"},[t("i",{class:"fas fa-coins"})],-1))])]),t("div",pe,[t("div",ye,[t("div",fe,[e[25]||(e[25]=t("p",{class:"text-sm font-semibold text-gray-600 mb-1"}," 总Token消耗 ",-1)),t("div",ge,[t("p",xe,p(m((a(c).totalInputTokens||0)+(a(c).totalOutputTokens||0)+(a(c).totalCacheCreateTokens||0)+(a(c).totalCacheReadTokens||0))),1),t("span",ve,"/ "+p(a(lt).totalCosts.formatted.totalCost),1)]),t("div",he,[t("div",be,[t("span",null,[e[21]||(e[21]=k("输入: ",-1)),t("span",ke,p(m(a(c).totalInputTokens||0)),1)]),t("span",null,[e[22]||(e[22]=k("输出: ",-1)),t("span",Te,p(m(a(c).totalOutputTokens||0)),1)]),(a(c).totalCacheCreateTokens||0)>0?(_(),w("span",Ce,[e[23]||(e[23]=k("缓存创建: ",-1)),t("span",De,p(m(a(c).totalCacheCreateTokens||0)),1)])):z("",!0),(a(c).totalCacheReadTokens||0)>0?(_(),w("span",we,[e[24]||(e[24]=k("缓存读取: ",-1)),t("span",_e,p(m(a(c).totalCacheReadTokens||0)),1)])):z("",!0)])])]),e[26]||(e[26]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-emerald-500 to-emerald-600"},[t("i",{class:"fas fa-database"})],-1))])]),t("div",Se,[t("div",Re,[t("div",null,[t("p",$e,[e[27]||(e[27]=k(" 实时RPM ",-1)),t("span",Ae,"("+p(a(c).metricsWindow)+"分钟)",1)]),t("p",Me,p(a(c).realtimeRPM||0),1),t("p",Ue,[e[29]||(e[29]=k(" 每分钟请求数 ",-1)),a(c).isHistoricalMetrics?(_(),w("span",Ke,e[28]||(e[28]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),k(" 历史数据 ",-1)]))):z("",!0)])]),e[30]||(e[30]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-orange-500 to-orange-600"},[t("i",{class:"fas fa-tachometer-alt"})],-1))])]),t("div",Ie,[t("div",Pe,[t("div",null,[t("p",Fe,[e[31]||(e[31]=k(" 实时TPM ",-1)),t("span",Oe,"("+p(a(c).metricsWindow)+"分钟)",1)]),t("p",Be,p(m(a(c).realtimeTPM||0)),1),t("p",ze,[e[33]||(e[33]=k(" 每分钟Token数 ",-1)),a(c).isHistoricalMetrics?(_(),w("span",He,e[32]||(e[32]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),k(" 历史数据 ",-1)]))):z("",!0)])]),e[34]||(e[34]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-rose-500 to-rose-600"},[t("i",{class:"fas fa-rocket"})],-1))])])]),t("div",qe,[t("div",Ee,[e[41]||(e[41]=t("h3",{class:"text-xl font-bold text-gray-900"}," 模型使用分布与Token使用趋势 ",-1)),t("div",Le,[t("div",Ve,[(_(!0),w(bt,null,kt(a(S).presetOptions,g=>(_(),w("button",{key:g.value,class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",a(S).preset===g.value&&a(S).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:V=>a(rt)(g.value)},p(g.label),11,Ne))),128))]),t("div",je,[t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",a(q)==="day"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[0]||(e[0]=g=>a(tt)("day"))},e[35]||(e[35]=[t("i",{class:"fas fa-calendar-day mr-1"},null,-1),k("按天 ",-1)]),2),t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",a(q)==="hour"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[1]||(e[1]=g=>a(tt)("hour"))},e[36]||(e[36]=[t("i",{class:"fas fa-clock mr-1"},null,-1),k("按小时 ",-1)]),2)]),t("div",Ye,[$t(C,{modelValue:a(S).customRange,"onUpdate:modelValue":e[2]||(e[2]=g=>a(S).customRange=g),"default-time":a(pt),type:"datetimerange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期",format:"YYYY-MM-DD HH:mm:ss","value-format":"YYYY-MM-DD HH:mm:ss","disabled-date":a(ft),size:"default",style:{width:"400px"},class:"custom-date-picker",onChange:a(it)},null,8,["modelValue","default-time","disabled-date","onChange"]),a(q)==="hour"?(_(),w("span",We,e[37]||(e[37]=[t("i",{class:"fas fa-info-circle"},null,-1),k(" 最多24小时 ",-1)]))):z("",!0)]),t("div",Ge,[t("div",Qe,[t("label",Ze,[At(t("input",{"onUpdate:modelValue":e[3]||(e[3]=g=>l.value=g),type:"checkbox",class:"sr-only peer"},null,512),[[Mt,l.value]]),e[40]||(e[40]=t("div",{class:"relative w-9 h-5 bg-gray-300 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-500 transition-all duration-200 after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:w-4 after:h-4 after:rounded-full after:shadow-sm after:transition-transform after:duration-200 peer-checked:after:translate-x-4"},null,-1)),t("span",Je,[e[38]||(e[38]=t("i",{class:"fas fa-redo-alt text-xs text-gray-500"},null,-1)),e[39]||(e[39]=t("span",null,"自动刷新",-1)),l.value?(_(),w("span",{key:0,class:G(["ml-1 text-xs text-blue-600 font-mono transition-opacity",d.value>0?"opacity-100":"opacity-0"])},p(d.value)+"s ",3)):z("",!0)])])]),t("button",{disabled:f.value,class:"px-3 py-1 rounded-md text-sm font-medium transition-colors bg-white text-blue-600 shadow-sm hover:bg-gray-50 border border-gray-300 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",title:"立即刷新数据",onClick:e[4]||(e[4]=g=>B())},[t("i",{class:G(["fas fa-sync-alt text-xs",{"animate-spin":f.value}])},null,2),t("span",null,p(f.value?"刷新中":"刷新"),1)],8,Xe)])])]),t("div",ts,[t("div",es,[e[42]||(e[42]=t("h4",{class:"text-lg font-semibold text-gray-800 mb-4"}," Token使用分布 ",-1)),t("div",ss,[t("canvas",{ref_key:"modelUsageChart",ref:et},null,512)])]),t("div",as,[e[45]||(e[45]=t("h4",{class:"text-lg font-semibold text-gray-800 mb-4"}," 详细统计数据 ",-1)),a(H).length===0?(_(),w("div",os,e[43]||(e[43]=[t("p",{class:"text-gray-500"}," 暂无模型使用数据 ",-1)]))):(_(),w("div",ns,[t("table",ls,[e[44]||(e[44]=t("thead",{class:"bg-gray-50 sticky top-0"},[t("tr",null,[t("th",{class:"px-4 py-2 text-left text-xs font-medium text-gray-700"}," 模型 "),t("th",{class:"px-4 py-2 text-right text-xs font-medium text-gray-700"}," 请求数 "),t("th",{class:"px-4 py-2 text-right text-xs font-medium text-gray-700"}," 总Token "),t("th",{class:"px-4 py-2 text-right text-xs font-medium text-gray-700"}," 费用 "),t("th",{class:"px-4 py-2 text-right text-xs font-medium text-gray-700"}," 占比 ")])],-1)),t("tbody",rs,[(_(!0),w(bt,null,kt(a(H),g=>(_(),w("tr",{key:g.model,class:"hover:bg-gray-50"},[t("td",is,p(g.model),1),t("td",ds,p(m(g.requests)),1),t("td",us,p(m(g.allTokens)),1),t("td",cs,p(g.formatted?g.formatted.total:"$0.000000"),1),t("td",ms,[t("span",ps,p($(g.allTokens,a(H)))+"% ",1)])]))),128))])])]))])])]),t("div",ys,[t("div",fs,[t("div",gs,[t("canvas",{ref_key:"usageTrendChart",ref:E},null,512)])])]),t("div",xs,[t("div",vs,[t("div",hs,[e[48]||(e[48]=t("h3",{class:"text-lg font-semibold text-gray-900"}," API Keys 使用趋势 ",-1)),t("div",bs,[t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",a(I)==="requests"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[5]||(e[5]=g=>{I.value="requests",L()})},e[46]||(e[46]=[t("i",{class:"fas fa-exchange-alt mr-1"},null,-1),k("请求次数 ",-1)]),2),t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",a(I)==="tokens"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[6]||(e[6]=g=>{I.value="tokens",L()})},e[47]||(e[47]=[t("i",{class:"fas fa-coins mr-1"},null,-1),k("Token 数量 ",-1)]),2)])]),t("div",ks,[a(M).totalApiKeys>10?(_(),w("span",Ts," 共 "+p(a(M).totalApiKeys)+" 个 API Key,显示使用量前 10 个 ",1)):(_(),w("span",Cs," 共 "+p(a(M).totalApiKeys)+" 个 API Key ",1))]),t("div",Ds,[t("canvas",{ref_key:"apiKeysUsageTrendChart",ref:Q},null,512)])])])])}}},Us=Ut(ws,[["__scopeId","data-v-e2cbd0e3"]]);export{Us as default}; diff --git a/web/admin-spa/dist/assets/LoginView-DaxEvag8.js b/web/admin-spa/dist/assets/LoginView-DaxEvag8.js deleted file mode 100644 index a07f70f4..00000000 --- a/web/admin-spa/dist/assets/LoginView-DaxEvag8.js +++ /dev/null @@ -1 +0,0 @@ -import{c as b,r as x,q as f,x as a,z as s,L as i,Q as y,u as o,P as m,Y as _,K as u,aq as c,O as g,y as n}from"./vue-vendor-CKToUHZx.js";import{_ as v,u as w}from"./index-9AMT1Op2.js";/* empty css */import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const h={class:"flex items-center justify-center min-h-screen p-6"},k={class:"glass-strong rounded-3xl p-10 w-full max-w-md shadow-2xl"},L={class:"text-center mb-8"},S={class:"w-20 h-20 mx-auto mb-6 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-2xl flex items-center justify-center backdrop-blur-sm overflow-hidden"},V=["src"],I={key:1,class:"fas fa-cloud text-3xl text-gray-700"},N={key:1,class:"w-12 h-12 bg-gray-300/50 rounded animate-pulse"},q={key:0,class:"text-3xl font-bold text-white mb-2 header-title"},D={key:1,class:"h-9 w-64 bg-gray-300/50 rounded animate-pulse mx-auto mb-2"},E=["disabled"],j={key:0,class:"fas fa-sign-in-alt mr-2"},B={key:1,class:"loading-spinner mr-2"},M={key:0,class:"mt-6 p-4 bg-red-500/20 border border-red-500/30 rounded-xl text-red-800 text-sm text-center backdrop-blur-sm"},F={__name:"LoginView",setup(O){const e=w(),d=b(()=>e.oemLoading),l=x({username:"",password:""});f(()=>{e.loadOemSettings()});const p=async()=>{await e.login(l.value)};return(T,t)=>(n(),a("div",h,[s("div",k,[s("div",L,[s("div",S,[d.value?(n(),a("div",N)):(n(),a(y,{key:0},[o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon?(n(),a("img",{key:0,src:o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon,alt:"Logo",class:"w-12 h-12 object-contain",onError:t[0]||(t[0]=r=>r.target.style.display="none")},null,40,V)):(n(),a("i",I))],64))]),!d.value&&o(e).oemSettings.siteName?(n(),a("h1",q,m(o(e).oemSettings.siteName),1)):d.value?(n(),a("div",D)):i("",!0),t[3]||(t[3]=s("p",{class:"text-gray-600 text-lg"}," 管理后台 ",-1))]),s("form",{class:"space-y-6",onSubmit:_(p,["prevent"])},[s("div",null,[t[4]||(t[4]=s("label",{class:"block text-sm font-semibold text-gray-900 mb-3"},"用户名",-1)),u(s("input",{"onUpdate:modelValue":t[1]||(t[1]=r=>l.value.username=r),type:"text",required:"",class:"form-input w-full",placeholder:"请输入用户名"},null,512),[[c,l.value.username]])]),s("div",null,[t[5]||(t[5]=s("label",{class:"block text-sm font-semibold text-gray-900 mb-3"},"密码",-1)),u(s("input",{"onUpdate:modelValue":t[2]||(t[2]=r=>l.value.password=r),type:"password",required:"",class:"form-input w-full",placeholder:"请输入密码"},null,512),[[c,l.value.password]])]),s("button",{type:"submit",disabled:o(e).loginLoading,class:"btn btn-primary w-full py-4 px-6 text-lg font-semibold"},[o(e).loginLoading?i("",!0):(n(),a("i",j)),o(e).loginLoading?(n(),a("div",B)):i("",!0),g(" "+m(o(e).loginLoading?"登录中...":"登录"),1)],8,E)],32),o(e).loginError?(n(),a("div",M,[t[6]||(t[6]=s("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),g(m(o(e).loginError),1)])):i("",!0)])]))}},P=v(F,[["__scopeId","data-v-82195a01"]]);export{P as default}; diff --git a/web/admin-spa/dist/assets/LogoTitle-CXHYkSsD.js b/web/admin-spa/dist/assets/LogoTitle-CXHYkSsD.js deleted file mode 100644 index 01172cc1..00000000 --- a/web/admin-spa/dist/assets/LogoTitle-CXHYkSsD.js +++ /dev/null @@ -1 +0,0 @@ -/* empty css */import{_ as r}from"./index-9AMT1Op2.js";import{x as t,y as s,z as o,Q as d,L as a,A as c,C as g,P as i}from"./vue-vendor-CKToUHZx.js";const u={class:"flex items-center gap-4"},f={class:"w-12 h-12 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl flex items-center justify-center backdrop-blur-sm flex-shrink-0 overflow-hidden"},y=["src"],m={key:1,class:"fas fa-cloud text-xl text-gray-700"},h={key:1,class:"w-8 h-8 bg-gray-300/50 rounded animate-pulse"},x={class:"flex flex-col justify-center min-h-[48px]"},b={class:"flex items-center gap-3"},k={key:1,class:"h-8 w-64 bg-gray-300/50 rounded animate-pulse"},_={key:0,class:"text-gray-600 text-sm leading-tight mt-0.5"},S={__name:"LogoTitle",props:{loading:{type:Boolean,default:!1},title:{type:String,default:""},subtitle:{type:String,default:""},logoSrc:{type:String,default:""},titleClass:{type:String,default:"text-gray-900"}},setup(e){const n=l=>{l.target.style.display="none"};return(l,p)=>(s(),t("div",u,[o("div",f,[e.loading?(s(),t("div",h)):(s(),t(d,{key:0},[e.logoSrc?(s(),t("img",{key:0,src:e.logoSrc,alt:"Logo",class:"w-8 h-8 object-contain",onError:n},null,40,y)):(s(),t("i",m))],64))]),o("div",x,[o("div",b,[!e.loading&&e.title?(s(),t("h1",{key:0,class:g(["text-2xl font-bold header-title leading-tight",e.titleClass])},i(e.title),3)):e.loading?(s(),t("div",k)):a("",!0),c(l.$slots,"after-title",{},void 0,!0)]),e.subtitle?(s(),t("p",_,i(e.subtitle),1)):a("",!0)])]))}},C=r(S,[["__scopeId","data-v-718feedc"]]);export{C as L}; diff --git a/web/admin-spa/dist/assets/MainLayout-BE6L3XCu.js b/web/admin-spa/dist/assets/MainLayout-BE6L3XCu.js deleted file mode 100644 index c82072f1..00000000 --- a/web/admin-spa/dist/assets/MainLayout-BE6L3XCu.js +++ /dev/null @@ -1 +0,0 @@ -import{c as M,r as w,_ as O,q as E,V as R,x as o,y as n,z as t,L as T,R as y,J as U,P as b,C as V,Y as $,O as v,T as D,K as k,aq as _,Q as N,aT as q,ac as F,o as J,av as H,aU as Q,I as A,aV as Y,M as G}from"./vue-vendor-CKToUHZx.js";import{_ as L,u as W,a as j}from"./index-9AMT1Op2.js";import{s as g}from"./toast-BvwA7Mwb.js";import{L as X}from"./LogoTitle-CXHYkSsD.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";/* empty css */const Z={class:"glass-strong rounded-3xl p-6 mb-8 shadow-xl",style:{"z-index":"10",position:"relative"}},ee={class:"flex flex-col md:flex-row justify-between items-center gap-4"},te={class:"flex items-center gap-4"},se={class:"flex items-center gap-2"},ae={class:"text-sm text-gray-400 font-mono"},ne=["href"],oe={class:"relative user-menu-container"},le={class:"px-4 py-3 border-b border-gray-100"},re={class:"flex items-center justify-between text-sm"},ie={class:"font-mono text-gray-700"},ue={key:0,class:"mt-2"},de={class:"flex items-center justify-between text-sm mb-2"},ce={class:"font-mono text-green-600"},me=["href"],fe={key:1,class:"mt-2 text-center text-xs text-gray-500"},pe={key:2,class:"mt-2 text-center"},ve={key:"message",class:"px-3 py-1.5 bg-green-100 border border-green-200 rounded-lg inline-block"},xe={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},ge={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},be=["value"],ye={class:"flex gap-3 pt-4"},we=["disabled"],he={key:0,class:"loading-spinner mr-2"},ke={key:1,class:"fas fa-save mr-2"},_e={__name:"AppHeader",setup(C){const x=q(),d=W(),m=M(()=>d.user||{username:"Admin"}),l=M(()=>d.oemSettings||{}),h=M(()=>d.oemLoading),s=w({current:"...",latest:"",hasUpdate:!1,checkingUpdate:!1,lastChecked:null,releaseInfo:null,noUpdateMessage:!1}),r=w(!1),f=w(!1),p=w(!1),a=O({currentPassword:"",newPassword:"",confirmPassword:"",newUsername:""}),P=async()=>{if(!s.value.checkingUpdate){s.value.checkingUpdate=!0;try{const u=await j.get("/admin/check-updates");if(u.success){const e=u.data;s.value.current=e.current,s.value.latest=e.latest,s.value.hasUpdate=e.hasUpdate,s.value.releaseInfo=e.releaseInfo,s.value.lastChecked=new Date,localStorage.setItem("versionInfo",JSON.stringify({current:e.current,latest:e.latest,lastChecked:s.value.lastChecked,hasUpdate:e.hasUpdate,releaseInfo:e.releaseInfo})),e.hasUpdate||(s.value.noUpdateMessage=!0,setTimeout(()=>{s.value.noUpdateMessage=!1},3e3))}}catch(u){console.error("Error checking for updates:",u);const e=localStorage.getItem("versionInfo");if(e){const c=JSON.parse(e);s.value.current=c.current||s.value.current,s.value.latest=c.latest,s.value.hasUpdate=c.hasUpdate,s.value.releaseInfo=c.releaseInfo,s.value.lastChecked=new Date(c.lastChecked)}}finally{s.value.checkingUpdate=!1}}},z=()=>{a.currentPassword="",a.newPassword="",a.confirmPassword="",a.newUsername="",f.value=!0,r.value=!1},I=()=>{f.value=!1},B=async()=>{if(a.newPassword!==a.confirmPassword){g("两次输入的密码不一致","error");return}if(a.newPassword.length<8){g("新密码长度至少8位","error");return}p.value=!0;try{const u=await j.post("/admin/change-password",{currentPassword:a.currentPassword,newPassword:a.newPassword,newUsername:a.newUsername||void 0});if(u.success){const e=a.newUsername?"账户信息修改成功,请重新登录":"密码修改成功,请重新登录";g(e,"success"),I(),setTimeout(()=>{d.logout(),x.push("/login")},1500)}else g(u.message||"修改失败","error")}catch{g("修改密码失败","error")}finally{p.value=!1}},K=()=>{confirm("确定要退出登录吗?")&&(d.logout(),x.push("/login"),g("已安全退出","success")),r.value=!1},S=u=>{!u.target.closest(".user-menu-container")&&r.value&&(r.value=!1)};return E(()=>{P(),setInterval(()=>{P()},36e5),document.addEventListener("click",S)}),R(()=>{document.removeEventListener("click",S)}),(u,e)=>{var c;return n(),o(N,null,[t("div",Z,[t("div",ee,[t("div",te,[y(X,{loading:h.value,title:l.value.siteName,subtitle:"管理后台","logo-src":l.value.siteIconData||l.value.siteIcon,"title-class":"text-white"},{"after-title":U(()=>{var i;return[t("div",se,[t("span",ae,"v"+b(s.value.current||"..."),1),s.value.hasUpdate?(n(),o("a",{key:0,href:((i=s.value.releaseInfo)==null?void 0:i.htmlUrl)||"#",target:"_blank",class:"inline-flex items-center gap-1 px-2 py-0.5 bg-green-500 border border-green-600 rounded-full text-xs text-white hover:bg-green-600 transition-colors animate-pulse",title:"有新版本可用"},e[7]||(e[7]=[t("i",{class:"fas fa-arrow-up text-[10px]"},null,-1),t("span",null,"新版本",-1)]),8,ne)):T("",!0)])]}),_:1},8,["loading","title","logo-src"])]),t("div",oe,[t("button",{class:"btn btn-primary px-4 py-3 flex items-center gap-2 relative",onClick:e[0]||(e[0]=i=>r.value=!r.value)},[e[8]||(e[8]=t("i",{class:"fas fa-user-circle"},null,-1)),t("span",null,b(m.value.username||"Admin"),1),t("i",{class:V(["fas fa-chevron-down text-xs transition-transform duration-200",{"rotate-180":r.value}])},null,2)]),r.value?(n(),o("div",{key:0,class:"absolute right-0 top-full mt-2 w-56 bg-white rounded-xl shadow-xl border border-gray-200 py-2 user-menu-dropdown",style:{"z-index":"999999"},onClick:e[2]||(e[2]=$(()=>{},["stop"]))},[t("div",le,[t("div",re,[e[9]||(e[9]=t("span",{class:"text-gray-500"},"当前版本",-1)),t("span",ie,"v"+b(s.value.current||"..."),1)]),s.value.hasUpdate?(n(),o("div",ue,[t("div",de,[e[10]||(e[10]=t("span",{class:"text-green-600 font-medium"},[t("i",{class:"fas fa-arrow-up mr-1"}),v("有新版本 ")],-1)),t("span",ce,"v"+b(s.value.latest),1)]),t("a",{href:((c=s.value.releaseInfo)==null?void 0:c.htmlUrl)||"#",target:"_blank",class:"block w-full text-center px-3 py-1.5 bg-green-500 text-white text-sm rounded-lg hover:bg-green-600 transition-colors"},e[11]||(e[11]=[t("i",{class:"fas fa-external-link-alt mr-1"},null,-1),v("查看更新 ",-1)]),8,me)])):s.value.checkingUpdate?(n(),o("div",fe,e[12]||(e[12]=[t("i",{class:"fas fa-spinner fa-spin mr-1"},null,-1),v("检查更新中... ",-1)]))):(n(),o("div",pe,[y(D,{name:"fade",mode:"out-in"},{default:U(()=>[s.value.noUpdateMessage?(n(),o("div",ve,e[13]||(e[13]=[t("p",{class:"text-xs text-green-700 font-medium"},[t("i",{class:"fas fa-check-circle mr-1"}),v("当前已是最新版本 ")],-1)]))):(n(),o("button",{key:"button",class:"text-xs text-blue-500 hover:text-blue-700 transition-colors",onClick:e[1]||(e[1]=i=>P())},e[14]||(e[14]=[t("i",{class:"fas fa-sync-alt mr-1"},null,-1),v("检查更新 ",-1)])))]),_:1})]))]),t("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:z},e[15]||(e[15]=[t("i",{class:"fas fa-key text-blue-500"},null,-1),t("span",null,"修改账户信息",-1)])),e[17]||(e[17]=t("hr",{class:"my-2 border-gray-200"},null,-1)),t("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:K},e[16]||(e[16]=[t("i",{class:"fas fa-sign-out-alt text-red-500"},null,-1),t("span",null,"退出登录",-1)]))])):T("",!0)])])]),f.value?(n(),o("div",xe,[t("div",ge,[t("div",{class:"flex items-center justify-between mb-6"},[e[19]||(e[19]=t("div",{class:"flex items-center gap-3"},[t("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[t("i",{class:"fas fa-key text-white"})]),t("h3",{class:"text-xl font-bold text-gray-900"}," 修改账户信息 ")],-1)),t("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:I},e[18]||(e[18]=[t("i",{class:"fas fa-times text-xl"},null,-1)]))]),t("form",{class:"space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:$(B,["prevent"])},[t("div",null,[e[20]||(e[20]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前用户名",-1)),t("input",{value:m.value.username||"Admin",type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed"},null,8,be),e[21]||(e[21]=t("p",{class:"text-xs text-gray-500 mt-2"}," 当前用户名,输入新用户名以修改 ",-1))]),t("div",null,[e[22]||(e[22]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新用户名",-1)),k(t("input",{"onUpdate:modelValue":e[3]||(e[3]=i=>a.newUsername=i),type:"text",class:"form-input w-full",placeholder:"输入新用户名(留空保持不变)"},null,512),[[_,a.newUsername]]),e[23]||(e[23]=t("p",{class:"text-xs text-gray-500 mt-2"}," 留空表示不修改用户名 ",-1))]),t("div",null,[e[24]||(e[24]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前密码",-1)),k(t("input",{"onUpdate:modelValue":e[4]||(e[4]=i=>a.currentPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入当前密码"},null,512),[[_,a.currentPassword]])]),t("div",null,[e[25]||(e[25]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新密码",-1)),k(t("input",{"onUpdate:modelValue":e[5]||(e[5]=i=>a.newPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入新密码"},null,512),[[_,a.newPassword]]),e[26]||(e[26]=t("p",{class:"text-xs text-gray-500 mt-2"}," 密码长度至少8位 ",-1))]),t("div",null,[e[27]||(e[27]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"确认新密码",-1)),k(t("input",{"onUpdate:modelValue":e[6]||(e[6]=i=>a.confirmPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请再次输入新密码"},null,512),[[_,a.confirmPassword]])]),t("div",ye,[t("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:I}," 取消 "),t("button",{type:"submit",disabled:p.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[p.value?(n(),o("div",he)):(n(),o("i",ke)),v(" "+b(p.value?"保存中...":"保存修改"),1)],8,we)])],32)])])):T("",!0)],64)}}},Ue=L(_e,[["__scopeId","data-v-590374fc"]]),Ce={class:"flex flex-wrap gap-2 mb-6 bg-white/10 rounded-2xl p-2 backdrop-blur-sm"},Pe=["onClick"],Ie={__name:"TabBar",props:{activeTab:{type:String,required:!0}},emits:["tab-change"],setup(C){const x=[{key:"dashboard",name:"仪表板",icon:"fas fa-tachometer-alt"},{key:"apiKeys",name:"API Keys",icon:"fas fa-key"},{key:"accounts",name:"账户管理",icon:"fas fa-user-circle"},{key:"tutorial",name:"使用教程",icon:"fas fa-graduation-cap"},{key:"settings",name:"其他设置",icon:"fas fa-cogs"}];return(d,m)=>(n(),o("div",Ce,[(n(),o(N,null,F(x,l=>t("button",{key:l.key,class:V(["tab-btn flex-1 py-3 px-6 text-sm font-semibold transition-all duration-300",C.activeTab===l.key?"active":"text-gray-700 hover:bg-white/10 hover:text-gray-900"]),onClick:h=>d.$emit("tab-change",l.key)},[t("i",{class:V(l.icon+" mr-2")},null,2),v(b(l.name),1)],10,Pe)),64))]))}},Me=L(Ie,[["__scopeId","data-v-aabb6896"]]),Te={class:"min-h-screen p-6"},Ve={class:"glass-strong rounded-3xl p-6 shadow-xl",style:{"z-index":"1","min-height":"calc(100vh - 240px)"}},Le={class:"tab-content"},Se={__name:"MainLayout",setup(C){const x=Q(),d=q(),m=w("dashboard"),l={dashboard:"/dashboard",apiKeys:"/api-keys",accounts:"/accounts",tutorial:"/tutorial",settings:"/settings"};J(()=>x.path,s=>{const r=Object.keys(l).find(f=>l[f]===s);r&&(m.value=r)},{immediate:!0});const h=s=>{m.value=s,d.push(l[s])};return(s,r)=>{const f=H("router-view");return n(),o("div",Te,[y(Ue),t("div",Ve,[y(Me,{"active-tab":m.value,onTabChange:h},null,8,["active-tab"]),t("div",Le,[y(f,null,{default:U(({Component:p})=>[y(D,{name:"slide-up",mode:"out-in"},{default:U(()=>[(n(),A(Y,{include:["DashboardView","ApiKeysView"]},[(n(),A(G(p)))],1024))]),_:2},1024)]),_:1})])])])}}},Be=L(Se,[["__scopeId","data-v-59f33a38"]]);export{Be as default}; diff --git a/web/admin-spa/dist/assets/MainLayout-tWrOHYRR.css b/web/admin-spa/dist/assets/MainLayout-tWrOHYRR.css deleted file mode 100644 index 6683a655..00000000 --- a/web/admin-spa/dist/assets/MainLayout-tWrOHYRR.css +++ /dev/null @@ -1 +0,0 @@ -.user-menu-dropdown[data-v-590374fc]{margin-top:8px}.fade-enter-active[data-v-590374fc],.fade-leave-active[data-v-590374fc]{transition:opacity .3s}.fade-enter-from[data-v-590374fc],.fade-leave-to[data-v-590374fc]{opacity:0} diff --git a/web/admin-spa/dist/assets/SettingsView-D9bl7XvV.css b/web/admin-spa/dist/assets/SettingsView-D9bl7XvV.css deleted file mode 100644 index 5ca392ff..00000000 --- a/web/admin-spa/dist/assets/SettingsView-D9bl7XvV.css +++ /dev/null @@ -1 +0,0 @@ -.settings-container[data-v-d29d5f49]{min-height:calc(100vh - 300px)}.card[data-v-d29d5f49]{background:#fff;border-radius:12px;box-shadow:0 2px 12px #0000001a;border:1px solid #e5e7eb}.table-container[data-v-d29d5f49]{overflow:hidden;border-radius:8px;border:1px solid #f3f4f6}.table-row[data-v-d29d5f49]{transition:background-color .2s ease}.table-row[data-v-d29d5f49]:hover{background-color:#f9fafb}.form-input[data-v-d29d5f49]{width:100%;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.5rem 1rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-input[data-v-d29d5f49]:focus{border-color:transparent;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.btn[data-v-d29d5f49]{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn[data-v-d29d5f49]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-primary[data-v-d29d5f49]{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary[data-v-d29d5f49]:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.btn-primary[data-v-d29d5f49]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.btn-success[data-v-d29d5f49]{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-success[data-v-d29d5f49]:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.btn-success[data-v-d29d5f49]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity, 1))}.loading-spinner[data-v-d29d5f49]{height:1.25rem;width:1.25rem}@keyframes spin-d29d5f49{to{transform:rotate(360deg)}}.loading-spinner[data-v-d29d5f49]{animation:spin-d29d5f49 1s linear infinite;border-radius:9999px;border-width:2px;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-border-opacity: 1;border-top-color:rgb(37 99 235 / var(--tw-border-opacity, 1))} diff --git a/web/admin-spa/dist/assets/SettingsView-DhzunnrL.js b/web/admin-spa/dist/assets/SettingsView-DhzunnrL.js deleted file mode 100644 index 20c89c2a..00000000 --- a/web/admin-spa/dist/assets/SettingsView-DhzunnrL.js +++ /dev/null @@ -1,3 +0,0 @@ -import{aR as k,r as x,aW as C,q as O,x as m,z as e,u as i,K as T,aq as N,L as _,O as v,C as j,P as S,y as g}from"./vue-vendor-CKToUHZx.js";import{s as c}from"./toast-BvwA7Mwb.js";import{a as D,_ as F}from"./index-9AMT1Op2.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const E=k("settings",()=>{const l=x({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null}),r=x(!1),p=x(!1),d=async()=>{r.value=!0;try{const s=await D.get("/admin/oem-settings");return s&&s.success&&(l.value={...l.value,...s.data},f()),s}catch(s){throw console.error("Failed to load OEM settings:",s),s}finally{r.value=!1}},a=async s=>{p.value=!0;try{const o=await D.put("/admin/oem-settings",s);return o&&o.success&&(l.value={...l.value,...o.data},f()),o}catch(o){throw console.error("Failed to save OEM settings:",o),o}finally{p.value=!1}},w=async()=>{const s={siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null};return l.value={...s},await a(s)},f=()=>{if(l.value.siteName&&(document.title=`${l.value.siteName} - 管理后台`),l.value.siteIconData||l.value.siteIcon){const s=document.querySelector('link[rel="icon"]')||document.createElement("link");s.rel="icon",s.href=l.value.siteIconData||l.value.siteIcon,document.querySelector('link[rel="icon"]')||document.head.appendChild(s)}};return{oemSettings:l,loading:r,saving:p,loadOemSettings:d,saveOemSettings:a,resetOemSettings:w,applyOemSettings:f,formatDateTime:s=>s?new Date(s).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}):"",validateIconFile:s=>{const o=[];return s.size>350*1024&&o.push("图标文件大小不能超过 350KB"),["image/x-icon","image/png","image/jpeg","image/jpg","image/svg+xml"].includes(s.type)||o.push("不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件"),{isValid:o.length===0,errors:o}},fileToBase64:s=>new Promise((o,n)=>{const t=new FileReader;t.onload=u=>o(u.target.result),t.onerror=n,t.readAsDataURL(s)})}}),B={class:"settings-container"},V={class:"card p-6"},R={key:0,class:"text-center py-12"},M={key:1,class:"table-container"},A={class:"min-w-full"},q={class:"divide-y divide-gray-200/50"},z={class:"table-row"},K={class:"px-6 py-4"},L={class:"table-row"},U={class:"px-6 py-4"},$={class:"space-y-3"},P={key:0,class:"inline-flex items-center gap-3 p-3 bg-gray-50 rounded-lg"},W=["src"],G={class:"px-6 py-6",colspan:"2"},H={class:"flex items-center justify-between"},J={class:"flex gap-3"},Q=["disabled"],X={key:0,class:"loading-spinner mr-2"},Y={key:1,class:"fas fa-save mr-2"},Z=["disabled"],ee={key:0,class:"text-sm text-gray-500"},te={__name:"SettingsView",setup(l){const r=E(),{loading:p,saving:d,oemSettings:a}=C(r),w=x();O(async()=>{try{await r.loadOemSettings()}catch{c("加载设置失败","error")}});const f=async()=>{try{const n={siteName:a.value.siteName,siteIcon:a.value.siteIcon,siteIconData:a.value.siteIconData},t=await r.saveOemSettings(n);t&&t.success?c("OEM设置保存成功","success"):c((t==null?void 0:t.message)||"保存失败","error")}catch{c("保存OEM设置失败","error")}},b=async()=>{if(confirm(`确定要重置为默认设置吗? - -这将清除所有自定义的网站名称和图标设置。`))try{const n=await r.resetOemSettings();n&&n.success?c("已重置为默认设置","success"):c("重置失败","error")}catch{c("重置失败","error")}},h=async n=>{const t=n.target.files[0];if(!t)return;const u=r.validateIconFile(t);if(!u.isValid){u.errors.forEach(y=>c(y,"error"));return}try{const y=await r.fileToBase64(t);a.value.siteIconData=y}catch{c("文件读取失败","error")}n.target.value=""},I=()=>{a.value.siteIcon="",a.value.siteIconData=""},s=()=>{console.warn("Icon failed to load")},o=r.formatDateTime;return(n,t)=>(g(),m("div",B,[e("div",V,[t[12]||(t[12]=e("div",{class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},[e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900 mb-2"}," 其他设置 "),e("p",{class:"text-gray-600"}," 自定义网站名称和图标 ")])],-1)),i(p)?(g(),m("div",R,t[2]||(t[2]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载设置... ",-1)]))):(g(),m("div",M,[e("table",A,[e("tbody",q,[e("tr",z,[t[4]||(t[4]=e("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[e("div",{class:"flex items-center"},[e("div",{class:"w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-font text-white text-xs"})]),e("div",null,[e("div",{class:"text-sm font-semibold text-gray-900"}," 网站名称 "),e("div",{class:"text-xs text-gray-500"}," 品牌标识 ")])])],-1)),e("td",K,[T(e("input",{"onUpdate:modelValue":t[0]||(t[0]=u=>i(a).siteName=u),type:"text",class:"form-input w-full max-w-md",placeholder:"Claude Relay Service",maxlength:"100"},null,512),[[N,i(a).siteName]]),t[3]||(t[3]=e("p",{class:"text-xs text-gray-500 mt-1"}," 将显示在浏览器标题和页面头部 ",-1))])]),e("tr",L,[t[9]||(t[9]=e("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[e("div",{class:"flex items-center"},[e("div",{class:"w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-image text-white text-xs"})]),e("div",null,[e("div",{class:"text-sm font-semibold text-gray-900"}," 网站图标 "),e("div",{class:"text-xs text-gray-500"}," Favicon ")])])],-1)),e("td",U,[e("div",$,[i(a).siteIconData||i(a).siteIcon?(g(),m("div",P,[e("img",{src:i(a).siteIconData||i(a).siteIcon,alt:"图标预览",class:"w-8 h-8",onError:s},null,40,W),t[6]||(t[6]=e("span",{class:"text-sm text-gray-600"},"当前图标",-1)),e("button",{class:"text-red-600 hover:text-red-900 font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors",onClick:I},t[5]||(t[5]=[e("i",{class:"fas fa-trash mr-1"},null,-1),v("删除 ",-1)]))])):_("",!0),e("div",null,[e("input",{ref_key:"iconFileInput",ref:w,type:"file",accept:".ico,.png,.jpg,.jpeg,.svg",class:"hidden",onChange:h},null,544),e("button",{class:"btn btn-success px-4 py-2",onClick:t[1]||(t[1]=u=>n.$refs.iconFileInput.click())},t[7]||(t[7]=[e("i",{class:"fas fa-upload mr-2"},null,-1),v(" 上传图标 ",-1)])),t[8]||(t[8]=e("span",{class:"text-xs text-gray-500 ml-3"},"支持 .ico, .png, .jpg, .svg 格式,最大 350KB",-1))])])])]),e("tr",null,[e("td",G,[e("div",H,[e("div",J,[e("button",{disabled:i(d),class:j(["btn btn-primary px-6 py-3",{"opacity-50 cursor-not-allowed":i(d)}]),onClick:f},[i(d)?(g(),m("div",X)):(g(),m("i",Y)),v(" "+S(i(d)?"保存中...":"保存设置"),1)],10,Q),e("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:i(d),onClick:b},t[10]||(t[10]=[e("i",{class:"fas fa-undo mr-2"},null,-1),v(" 重置为默认 ",-1)]),8,Z)]),i(a).updatedAt?(g(),m("div",ee,[t[11]||(t[11]=e("i",{class:"fas fa-clock mr-1"},null,-1)),v(" 最后更新:"+S(i(o)(i(a).updatedAt)),1)])):_("",!0)])])])])])]))])]))}},le=F(te,[["__scopeId","data-v-d29d5f49"]]);export{le as default}; diff --git a/web/admin-spa/dist/assets/TutorialView-BM6fz9TT.css b/web/admin-spa/dist/assets/TutorialView-BM6fz9TT.css deleted file mode 100644 index 11927c64..00000000 --- a/web/admin-spa/dist/assets/TutorialView-BM6fz9TT.css +++ /dev/null @@ -1 +0,0 @@ -.tutorial-container[data-v-508c8654]{min-height:calc(100vh - 300px)}.tutorial-content[data-v-508c8654]{animation:fadeIn-508c8654 .3s ease-in-out}@keyframes fadeIn-508c8654{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}code[data-v-508c8654]{font-family:Fira Code,Monaco,Menlo,Ubuntu Mono,monospace}.tutorial-content h4[data-v-508c8654]{scroll-margin-top:100px}.tutorial-content .bg-gradient-to-r[data-v-508c8654]{transition:all .2s ease}.tutorial-content .bg-gradient-to-r[data-v-508c8654]:hover{transform:translateY(-1px);box-shadow:0 4px 12px #0000001a} diff --git a/web/admin-spa/dist/assets/TutorialView-D-C0Do28.js b/web/admin-spa/dist/assets/TutorialView-D-C0Do28.js deleted file mode 100644 index 8c274fc1..00000000 --- a/web/admin-spa/dist/assets/TutorialView-D-C0Do28.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as m}from"./index-9AMT1Op2.js";import{r as g,c as x,x as i,z as a,L as b,O as e,Q as u,ac as p,aY as l,P as d,y as c,C as v}from"./vue-vendor-CKToUHZx.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const y={class:"card p-6"},f={class:"mb-8"},h={class:"flex flex-wrap gap-2 p-2 bg-gray-100 rounded-xl"},C=["onClick"],w={key:0,class:"tutorial-content"},A={class:"mb-10"},T={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-6 border border-orange-100 mb-6"},P={class:"space-y-4"},N={class:"bg-white rounded-lg p-4 border border-orange-200"},S={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm"},H={class:"text-gray-300"},O={class:"bg-white rounded-lg p-4 border border-orange-200"},I={class:"mt-3 space-y-2"},R={class:"bg-gray-100 p-2 rounded text-sm"},B={class:"font-mono"},U={class:"bg-blue-50 border border-blue-200 rounded-lg p-4 mt-6"},j={class:"mt-3 space-y-2"},E={class:"bg-gray-100 p-2 rounded text-sm font-mono"},L={key:1,class:"tutorial-content"},_={class:"mb-10"},q={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-6 border border-orange-100 mb-6"},k={class:"space-y-4"},G={class:"bg-white rounded-lg p-4 border border-orange-200"},K={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm"},z={class:"text-gray-300"},D={class:"bg-white rounded-lg p-4 border border-orange-200"},W={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm mb-3"},$={class:"text-gray-300"},M={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm"},V={class:"text-gray-300"},F={key:2,class:"tutorial-content"},Q={class:"mb-10"},Y={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-6 border border-orange-100 mb-6"},J={class:"space-y-4"},X={class:"bg-white rounded-lg p-4 border border-orange-200"},Z={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm"},tt={class:"text-gray-300"},at={class:"bg-white rounded-lg p-4 border border-orange-200"},et={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm mb-3"},dt={class:"text-gray-300"},st={class:"bg-gray-900 text-green-400 p-3 rounded font-mono text-sm"},lt={class:"text-gray-300"},rt={__name:"TutorialView",setup(ot){const r=g("windows"),n=[{key:"windows",name:"Windows",icon:"fab fa-windows"},{key:"macos",name:"macOS",icon:"fab fa-apple"},{key:"linux",name:"Linux / WSL2",icon:"fab fa-linux"}];return x(()=>window.location.origin),(s,t)=>(c(),i("div",y,[t[55]||(t[55]=a("div",{class:"mb-8"},[a("h3",{class:"text-2xl font-bold text-gray-900 mb-4 flex items-center"},[a("i",{class:"fas fa-graduation-cap text-blue-600 mr-3"}),e(" Claude Code 使用教程 ")]),a("p",{class:"text-gray-600 text-lg"}," 跟着这个教程,你可以轻松在自己的电脑上安装并使用 Claude Code。 ")],-1)),a("div",f,[a("div",h,[(c(),i(u,null,p(n,o=>a("button",{key:o.key,class:v(["flex-1 py-3 px-6 text-sm font-semibold rounded-lg transition-all duration-300 flex items-center justify-center gap-2",r.value===o.key?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:bg-white/50 hover:text-gray-900"]),onClick:it=>r.value=o.key},[a("i",{class:v(o.icon)},null,2),e(" "+d(o.name),1)],10,C)),64))])]),r.value==="windows"?(c(),i("div",w,[t[19]||(t[19]=l('

1 安装 Node.js 环境

Claude Code 需要 Node.js 环境才能运行。

Windows 安装方法

方法一:官网下载(推荐)

  1. 打开浏览器访问 https://nodejs.org/
  2. 点击 "LTS" 版本进行下载(推荐长期支持版本)
  3. 下载完成后双击 .msi 文件
  4. 按照安装向导完成安装,保持默认设置即可

方法二:使用包管理器

如果你安装了 Chocolatey 或 Scoop,可以使用命令行安装:

# 使用 Chocolatey
choco install nodejs
# 或使用 Scoop
scoop install nodejs
Windows 注意事项
  • • 建议使用 PowerShell 而不是 CMD
  • • 如果遇到权限问题,尝试以管理员身份运行
  • • 某些杀毒软件可能会误报,需要添加白名单
验证安装是否成功

安装完成后,打开 PowerShell 或 CMD,输入以下命令:

node --version
npm --version

如果显示版本号,说明安装成功了!

2 安装 Git Bash

Windows 环境下需要使用 Git Bash 安装Claude code。安装完成后,环境变量设置和使用 Claude Code 仍然在普通的 PowerShell 或 CMD 中进行。

下载并安装 Git for Windows
  1. 访问 https://git-scm.com/downloads/win
  2. 点击 "Download for Windows" 下载安装包
  3. 运行下载的 .exe 安装文件
  4. 在安装过程中保持默认设置,直接点击 "Next" 完成安装
安装完成后
  • • 在任意文件夹右键可以看到 "Git Bash Here" 选项
  • • 也可以从开始菜单启动 "Git Bash"
  • • 只需要在 Git Bash 中运行 npm install 命令
  • • 后续的环境变量设置和使用都在 PowerShell/CMD 中
验证 Git Bash 安装

打开 Git Bash,输入以下命令验证:

git --version

如果显示 Git 版本号,说明安装成功!

3 安装 Claude Code

安装 Claude Code

打开 Git Bash(重要:不要使用 PowerShell),运行以下命令:

# 在 Git Bash 中全局安装 Claude Code
npm install -g @anthropic-ai/claude-code

这个命令会从 npm 官方仓库下载并安装最新版本的 Claude Code。

重要提醒
  • • 必须在 Git Bash 中运行,不要在 PowerShell 中运行
  • • 如果遇到权限问题,可以尝试在 Git Bash 中使用 sudo 命令
验证 Claude Code 安装

安装完成后,输入以下命令检查是否安装成功:

claude --version

如果显示版本号,恭喜你!Claude Code 已经成功安装了。

',3)),a("div",A,[t[18]||(t[18]=a("h4",{class:"text-xl font-semibold text-gray-800 mb-4 flex items-center"},[a("span",{class:"w-8 h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-sm font-bold mr-3"},"4"),e(" 设置环境变量 ")],-1)),a("div",T,[t[12]||(t[12]=a("h5",{class:"text-lg font-semibold text-gray-800 mb-3 flex items-center"},[a("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[13]||(t[13]=a("p",{class:"text-gray-700 mb-4"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),a("div",P,[a("div",N,[t[1]||(t[1]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法一:PowerShell 临时设置(推荐) ",-1)),t[2]||(t[2]=a("p",{class:"text-gray-600 text-sm mb-3"}," 在 PowerShell 中运行以下命令: ",-1)),a("div",S,[a("div",H,' $env:ANTHROPIC_BASE_URL = "'+d(s.currentBaseUrl)+'" ',1),t[0]||(t[0]=a("div",{class:"text-gray-300"},' $env:ANTHROPIC_AUTH_TOKEN = "你的API密钥" ',-1))]),t[3]||(t[3]=a("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),a("div",O,[t[10]||(t[10]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法二:系统环境变量(永久设置) ",-1)),t[11]||(t[11]=a("ol",{class:"text-gray-600 text-sm space-y-1 list-decimal list-inside"},[a("li",null,'右键"此电脑" → "属性" → "高级系统设置"'),a("li",null,'点击"环境变量"按钮'),a("li",null,'在"用户变量"或"系统变量"中点击"新建"'),a("li",null,"添加以下两个变量:")],-1)),a("div",I,[a("div",R,[t[4]||(t[4]=a("strong",null,"变量名:",-1)),t[5]||(t[5]=e(" ANTHROPIC_BASE_URL",-1)),t[6]||(t[6]=a("br",null,null,-1)),t[7]||(t[7]=a("strong",null,"变量值:",-1)),t[8]||(t[8]=e()),a("span",B,d(s.currentBaseUrl),1)]),t[9]||(t[9]=a("div",{class:"bg-gray-100 p-2 rounded text-sm"},[a("strong",null,"变量名:"),e(" ANTHROPIC_AUTH_TOKEN"),a("br"),a("strong",null,"变量值:"),e(),a("span",{class:"font-mono"},"你的API密钥")],-1))])])])]),a("div",U,[t[17]||(t[17]=l('
验证环境变量设置

设置完环境变量后,可以通过以下命令验证是否设置成功:

在 PowerShell 中验证:
echo $env:ANTHROPIC_BASE_URL
echo $env:ANTHROPIC_AUTH_TOKEN
在 CMD 中验证:
echo %ANTHROPIC_BASE_URL%
echo %ANTHROPIC_AUTH_TOKEN%
',3)),a("div",j,[t[15]||(t[15]=a("p",{class:"text-blue-700 text-sm"},[a("strong",null,"预期输出示例:")],-1)),a("div",E,[a("div",null,d(s.currentBaseUrl),1),t[14]||(t[14]=a("div",null,"cr_xxxxxxxxxxxxxxxxxx",-1))]),t[16]||(t[16]=a("p",{class:"text-blue-700 text-xs"}," 💡 如果输出为空或显示变量名本身,说明环境变量设置失败,请重新设置。 ",-1))])])]),t[20]||(t[20]=l('

5 开始使用 Claude Code

现在你可以开始使用 Claude Code 了!

启动 Claude Code
claude
在特定项目中使用
# 进入你的项目目录
cd C:\\path\\to\\your\\project
# 启动 Claude Code
claude

Windows 常见问题解决

安装时提示 "permission denied" 错误

这通常是权限问题,尝试以下解决方法:

  • 以管理员身份运行 PowerShell
  • 或者配置 npm 使用用户目录:npm config set prefix %APPDATA%\\npm
PowerShell 执行策略错误

如果遇到执行策略限制,运行:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
环境变量设置后不生效

设置永久环境变量后需要:

  • 重新启动 PowerShell 或 CMD
  • 或者注销并重新登录 Windows
  • 验证设置:echo $env:ANTHROPIC_BASE_URL
',2))])):r.value==="macos"?(c(),i("div",L,[t[36]||(t[36]=l('

1 安装 Node.js 环境

Claude Code 需要 Node.js 环境才能运行。

macOS 安装方法

方法一:使用 Homebrew(推荐)

如果你已经安装了 Homebrew,使用它安装 Node.js 会更方便:

# 更新 Homebrew
brew update
# 安装 Node.js
brew install node

方法二:官网下载

  1. 访问 https://nodejs.org/
  2. 下载适合 macOS 的 LTS 版本
  3. 打开下载的 .pkg 文件
  4. 按照安装程序指引完成安装
macOS 注意事项
  • • 如果遇到权限问题,可能需要使用 sudo
  • • 首次运行可能需要在系统偏好设置中允许
  • • 建议使用 Terminal 或 iTerm2
验证安装是否成功

安装完成后,打开 Terminal,输入以下命令:

node --version
npm --version

如果显示版本号,说明安装成功了!

2 安装 Claude Code

安装 Claude Code

打开 Terminal,运行以下命令:

# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code

如果遇到权限问题,可以使用 sudo:

sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装

安装完成后,输入以下命令检查是否安装成功:

claude --version

如果显示版本号,恭喜你!Claude Code 已经成功安装了。

',2)),a("div",_,[t[35]||(t[35]=a("h4",{class:"text-xl font-semibold text-gray-800 mb-4 flex items-center"},[a("span",{class:"w-8 h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-sm font-bold mr-3"},"3"),e(" 设置环境变量 ")],-1)),a("div",q,[t[33]||(t[33]=a("h5",{class:"text-lg font-semibold text-gray-800 mb-3 flex items-center"},[a("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[34]||(t[34]=a("p",{class:"text-gray-700 mb-4"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),a("div",k,[a("div",G,[t[22]||(t[22]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[23]||(t[23]=a("p",{class:"text-gray-600 text-sm mb-3"}," 在 Terminal 中运行以下命令: ",-1)),a("div",K,[a("div",z,' export ANTHROPIC_BASE_URL="'+d(s.currentBaseUrl)+'" ',1),t[21]||(t[21]=a("div",{class:"text-gray-300"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[24]||(t[24]=a("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),a("div",D,[t[31]||(t[31]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[32]||(t[32]=a("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件(根据你使用的 shell): ",-1)),a("div",W,[t[25]||(t[25]=a("div",{class:"mb-2"}," # 对于 zsh (默认) ",-1)),a("div",$,` echo 'export ANTHROPIC_BASE_URL="`+d(s.currentBaseUrl)+`"' >> ~/.zshrc `,1),t[26]||(t[26]=a("div",{class:"text-gray-300"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[27]||(t[27]=a("div",{class:"text-gray-300"}," source ~/.zshrc ",-1))]),a("div",M,[t[28]||(t[28]=a("div",{class:"mb-2"}," # 对于 bash ",-1)),a("div",V,` echo 'export ANTHROPIC_BASE_URL="`+d(s.currentBaseUrl)+`"' >> ~/.bash_profile `,1),t[29]||(t[29]=a("div",{class:"text-gray-300"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bash_profile `,-1)),t[30]||(t[30]=a("div",{class:"text-gray-300"}," source ~/.bash_profile ",-1))])])])])]),t[37]||(t[37]=l('

4 开始使用 Claude Code

现在你可以开始使用 Claude Code 了!

启动 Claude Code
claude
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude

macOS 常见问题解决

安装时提示权限错误

尝试以下解决方法:

  • 使用 sudo 安装:sudo npm install -g @anthropic-ai/claude-code
  • 或者配置 npm 使用用户目录:npm config set prefix ~/.npm-global
macOS 安全设置阻止运行

如果系统阻止运行 Claude Code:

  • 打开"系统偏好设置" → "安全性与隐私"
  • 点击"仍要打开"或"允许"
  • 或者在 Terminal 中运行:sudo spctl --master-disable
环境变量不生效

检查以下几点:

  • 确认修改了正确的配置文件(.zshrc 或 .bash_profile)
  • 重新启动 Terminal
  • 验证设置:echo $ANTHROPIC_BASE_URL
',2))])):r.value==="linux"?(c(),i("div",F,[t[53]||(t[53]=l('

1 安装 Node.js 环境

Claude Code 需要 Node.js 环境才能运行。

Linux 安装方法

方法一:使用官方仓库(推荐)

# 添加 NodeSource 仓库
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
# 安装 Node.js
sudo apt-get install -y nodejs

方法二:使用系统包管理器

虽然版本可能不是最新的,但对于基本使用已经足够:

# Ubuntu/Debian
sudo apt update
sudo apt install nodejs npm
# CentOS/RHEL/Fedora
sudo dnf install nodejs npm
Linux 注意事项
  • • 某些发行版可能需要安装额外的依赖
  • • 如果遇到权限问题,使用 sudo
  • • 确保你的用户在 npm 的全局目录有写权限
验证安装是否成功

安装完成后,打开终端,输入以下命令:

node --version
npm --version

如果显示版本号,说明安装成功了!

2 安装 Claude Code

安装 Claude Code

打开终端,运行以下命令:

# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code

如果遇到权限问题,可以使用 sudo:

sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装

安装完成后,输入以下命令检查是否安装成功:

claude --version

如果显示版本号,恭喜你!Claude Code 已经成功安装了。

',2)),a("div",Q,[t[52]||(t[52]=a("h4",{class:"text-xl font-semibold text-gray-800 mb-4 flex items-center"},[a("span",{class:"w-8 h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-sm font-bold mr-3"},"3"),e(" 设置环境变量 ")],-1)),a("div",Y,[t[50]||(t[50]=a("h5",{class:"text-lg font-semibold text-gray-800 mb-3 flex items-center"},[a("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[51]||(t[51]=a("p",{class:"text-gray-700 mb-4"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),a("div",J,[a("div",X,[t[39]||(t[39]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[40]||(t[40]=a("p",{class:"text-gray-600 text-sm mb-3"}," 在终端中运行以下命令: ",-1)),a("div",Z,[a("div",tt,' export ANTHROPIC_BASE_URL="'+d(s.currentBaseUrl)+'" ',1),t[38]||(t[38]=a("div",{class:"text-gray-300"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[41]||(t[41]=a("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),a("div",at,[t[48]||(t[48]=a("h6",{class:"font-medium text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[49]||(t[49]=a("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件: ",-1)),a("div",et,[t[42]||(t[42]=a("div",{class:"mb-2"}," # 对于 bash (默认) ",-1)),a("div",dt,` echo 'export ANTHROPIC_BASE_URL="`+d(s.currentBaseUrl)+`"' >> ~/.bashrc `,1),t[43]||(t[43]=a("div",{class:"text-gray-300"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bashrc `,-1)),t[44]||(t[44]=a("div",{class:"text-gray-300"}," source ~/.bashrc ",-1))]),a("div",st,[t[45]||(t[45]=a("div",{class:"mb-2"}," # 对于 zsh ",-1)),a("div",lt,` echo 'export ANTHROPIC_BASE_URL="`+d(s.currentBaseUrl)+`"' >> ~/.zshrc `,1),t[46]||(t[46]=a("div",{class:"text-gray-300"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[47]||(t[47]=a("div",{class:"text-gray-300"}," source ~/.zshrc ",-1))])])])])]),t[54]||(t[54]=l('

4 开始使用 Claude Code

现在你可以开始使用 Claude Code 了!

启动 Claude Code
claude
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude

Linux 常见问题解决

安装时提示权限错误

尝试以下解决方法:

  • 使用 sudo 安装:sudo npm install -g @anthropic-ai/claude-code
  • 或者配置 npm 使用用户目录:npm config set prefix ~/.npm-global
  • 然后添加到 PATH:export PATH=~/.npm-global/bin:$PATH
缺少依赖库

某些 Linux 发行版需要安装额外依赖:

# Ubuntu/Debian
sudo apt install build-essential
# CentOS/RHEL
sudo dnf groupinstall "Development Tools"
环境变量不生效

检查以下几点:

  • 确认修改了正确的配置文件(.bashrc 或 .zshrc)
  • 重新启动终端或运行 source ~/.bashrc
  • 验证设置:echo $ANTHROPIC_BASE_URL
',2))])):b("",!0),t[56]||(t[56]=a("div",{class:"bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-xl p-6 text-center"},[a("h5",{class:"text-xl font-semibold mb-2"}," 🎉 恭喜你! "),a("p",{class:"text-blue-100 mb-4"}," 你已经成功安装并配置了 Claude Code,现在可以开始享受 AI 编程助手带来的便利了。 "),a("p",{class:"text-sm text-blue-200"}," 如果在使用过程中遇到任何问题,可以查看官方文档或社区讨论获取帮助。 ")],-1))]))}},gt=m(rt,[["__scopeId","data-v-508c8654"]]);export{gt as default}; diff --git a/web/admin-spa/dist/assets/index-9AMT1Op2.js b/web/admin-spa/dist/assets/index-9AMT1Op2.js deleted file mode 100644 index 26a6bb0c..00000000 --- a/web/admin-spa/dist/assets/index-9AMT1Op2.js +++ /dev/null @@ -1,2 +0,0 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/LoginView-DaxEvag8.js","assets/vue-vendor-CKToUHZx.js","assets/element-plus-B8Fs_0jW.js","assets/vendor-BDiMbLwQ.js","assets/element-plus-CPnoEkWW.css","assets/LoginView-tn0RQdqM.css","assets/LogoTitle-BiOf3Vkp.css","assets/MainLayout-BE6L3XCu.js","assets/toast-BvwA7Mwb.js","assets/LogoTitle-CXHYkSsD.js","assets/MainLayout-tWrOHYRR.css","assets/DashboardView-BM1-V-So.js","assets/chart-Cor9iTVD.js","assets/DashboardView-B39lq_zZ.css","assets/ApiKeysView-DUk0IljI.js","assets/ApiKeysView-Dw8A7_uy.css","assets/AccountsView-dkIreWzq.js","assets/AccountsView-QM0EhO-E.css","assets/TutorialView-D-C0Do28.js","assets/TutorialView-BM6fz9TT.css","assets/SettingsView-DhzunnrL.js","assets/SettingsView-D9bl7XvV.css","assets/ApiStatsView-B5a23-WN.js","assets/ApiStatsView-C5BOZdu2.css"])))=>i.map(i=>d[i]); -import{aP as K,aQ as W,aR as F,r as _,c as L,q as R,V as D,I as q,z as h,x as b,ac as M,Q as G,a5 as N,y,C as S,L as x,P as T,Y as U,B as H,R as P,J,T as Q,O as X,av as Y,aM as Z,aS as ee}from"./vue-vendor-CKToUHZx.js";import{i as te,z as oe}from"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))o(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const n of a.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&o(n)}).observe(document,{childList:!0,subtree:!0});function e(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerPolicy&&(a.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?a.credentials="include":s.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(s){if(s.ep)return;s.ep=!0;const a=e(s);fetch(s.href,a)}})();const se="modulepreload",ne=function(r){return"/admin-next/"+r},$={},w=function(t,e,o){let s=Promise.resolve();if(e&&e.length>0){document.getElementsByTagName("link");const n=document.querySelector("meta[property=csp-nonce]"),p=(n==null?void 0:n.nonce)||(n==null?void 0:n.getAttribute("nonce"));s=Promise.allSettled(e.map(c=>{if(c=ne(c),c in $)return;$[c]=!0;const l=c.endsWith(".css"),d=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${d}`))return;const i=document.createElement("link");if(i.rel=l?"stylesheet":se,l||(i.as="script"),i.crossOrigin="",i.href=c,p&&i.setAttribute("nonce",p),document.head.appendChild(i),l)return new Promise((m,f)=>{i.addEventListener("load",m),i.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${c}`)))})}))}function a(n){const p=new Event("vite:preloadError",{cancelable:!0});if(p.payload=n,window.dispatchEvent(p),!p.defaultPrevented)throw n}return s.then(n=>{for(const p of n||[])p.status==="rejected"&&a(p.reason);return t().catch(a)})},V={basePath:"/admin-next/",apiPrefix:""};function ae(r=""){return r&&!r.startsWith("/")&&(r="/"+r),V.basePath+(r.startsWith("#")?r:"#"+r)}function re(){return ae("/login")}const ie=()=>w(()=>import("./LoginView-DaxEvag8.js"),__vite__mapDeps([0,1,2,3,4,5,6])),E=()=>w(()=>import("./MainLayout-BE6L3XCu.js"),__vite__mapDeps([7,1,8,9,6,2,3,4,10])),ce=()=>w(()=>import("./DashboardView-BM1-V-So.js"),__vite__mapDeps([11,2,1,3,4,8,12,13])),le=()=>w(()=>import("./ApiKeysView-DUk0IljI.js"),__vite__mapDeps([14,2,1,3,4,8,15])),ue=()=>w(()=>import("./AccountsView-dkIreWzq.js"),__vite__mapDeps([16,1,8,2,3,4,17])),de=()=>w(()=>import("./TutorialView-D-C0Do28.js"),__vite__mapDeps([18,1,2,3,4,19])),fe=()=>w(()=>import("./SettingsView-DhzunnrL.js"),__vite__mapDeps([20,1,8,2,3,4,21])),he=()=>w(()=>import("./ApiStatsView-B5a23-WN.js"),__vite__mapDeps([22,1,9,6,3,18,2,4,19,23])),me=[{path:"/",redirect:"/api-stats"},{path:"/login",name:"Login",component:ie,meta:{requiresAuth:!1}},{path:"/api-stats",name:"ApiStats",component:he,meta:{requiresAuth:!1}},{path:"/dashboard",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Dashboard",component:ce}]},{path:"/api-keys",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"ApiKeys",component:le}]},{path:"/accounts",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Accounts",component:ue}]},{path:"/tutorial",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Tutorial",component:de}]},{path:"/settings",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Settings",component:fe}]}],C=K({history:W(V.basePath),routes:me});C.beforeEach((r,t,e)=>{const o=B();console.log("路由导航:",{to:r.path,from:t.path,requiresAuth:r.meta.requiresAuth,isAuthenticated:o.isAuthenticated}),r.path==="/api-stats"||r.path.startsWith("/api-stats")?e():r.meta.requiresAuth&&!o.isAuthenticated?e("/login"):r.path==="/login"&&o.isAuthenticated?e("/dashboard"):e()});const z=V.apiPrefix;function A(r){return r.startsWith("/")||(r="/"+r),z+r}class pe{constructor(){this.baseURL=z}getAuthToken(){return localStorage.getItem("authToken")||null}buildConfig(t={}){const e={headers:{"Content-Type":"application/json",...t.headers},...t},o=this.getAuthToken();return o&&(e.headers.Authorization=`Bearer ${o}`),e}async handleResponse(t){if(t.status===401){const o=window.location.pathname+window.location.hash;throw o.includes("/login")||o.endsWith("/")||(localStorage.removeItem("authToken"),window.location.href=re()),new Error("Unauthorized")}const e=t.headers.get("content-type");if(e&&e.includes("application/json")){const o=await t.json();if(!t.ok)throw new Error(o.message||`HTTP ${t.status}`);return o}if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return t}async get(t,e={}){const o=A(t),s=this.buildConfig({...e,method:"GET"});try{const a=await fetch(o,s);return await this.handleResponse(a)}catch(a){throw console.error("API GET Error:",a),a}}async post(t,e=null,o={}){const s=A(t),a=this.buildConfig({...o,method:"POST",body:e?JSON.stringify(e):void 0});try{const n=await fetch(s,a);return await this.handleResponse(n)}catch(n){throw console.error("API POST Error:",n),n}}async put(t,e=null,o={}){const s=A(t),a=this.buildConfig({...o,method:"PUT",body:e?JSON.stringify(e):void 0});try{const n=await fetch(s,a);return await this.handleResponse(n)}catch(n){throw console.error("API PUT Error:",n),n}}async delete(t,e={}){const o=A(t),s=this.buildConfig({...e,method:"DELETE"});try{const a=await fetch(o,s);return await this.handleResponse(a)}catch(a){throw console.error("API DELETE Error:",a),a}}}const k=new pe,B=F("auth",()=>{const r=_(!1),t=_(localStorage.getItem("authToken")||""),e=_(""),o=_(""),s=_(!1),a=_({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",faviconData:""}),n=_(!0),p=L(()=>!!t.value&&r.value),c=L(()=>t.value),l=L(()=>({username:e.value}));async function d(u){s.value=!0,o.value="";try{const g=await k.post("/web/auth/login",u);g.success?(t.value=g.token,e.value=g.username||u.username,r.value=!0,localStorage.setItem("authToken",g.token),await C.push("/dashboard")):o.value=g.message||"登录失败"}catch(g){o.value=g.message||"登录失败,请检查用户名和密码"}finally{s.value=!1}}function i(){r.value=!1,t.value="",e.value="",localStorage.removeItem("authToken"),C.push("/login")}function m(){t.value&&(r.value=!0,f())}async function f(){try{const u=await k.get("/web/auth/user");u.success&&u.user&&(e.value=u.user.username),(await k.get("/admin/dashboard")).success||i()}catch{i()}}async function v(){n.value=!0;try{const u=await k.get("/admin/oem-settings");if(u.success&&u.data){if(a.value={...a.value,...u.data},u.data.siteIconData||u.data.siteIcon){const g=document.querySelector("link[rel*='icon']")||document.createElement("link");g.type="image/x-icon",g.rel="shortcut icon",g.href=u.data.siteIconData||u.data.siteIcon,document.getElementsByTagName("head")[0].appendChild(g)}u.data.siteName&&(document.title=`${u.data.siteName} - 管理后台`)}}catch(u){console.error("加载OEM设置失败:",u)}finally{n.value=!1}}return{isLoggedIn:r,authToken:t,username:e,loginError:o,loginLoading:s,oemSettings:a,oemLoading:n,isAuthenticated:p,token:c,user:l,login:d,logout:i,checkAuth:m,loadOemSettings:v}}),O=(r,t)=>{const e=r.__vccOpts||r;for(const[o,s]of t)e[o]=s;return e},_e={class:"toast-container"},ge=["onClick"],ve={class:"toast-content"},ye={class:"toast-icon"},we={class:"toast-body"},be={key:0,class:"toast-title"},Te={class:"toast-message"},Ee=["onClick"],Ae={__name:"ToastNotification",setup(r,{expose:t}){const e=_([]);let o=0;const s=l=>{const d={success:"fas fa-check-circle",error:"fas fa-exclamation-circle",warning:"fas fa-exclamation-triangle",info:"fas fa-info-circle"};return d[l]||d.info},a=(l,d="info",i=null,m=5e3)=>{const f=++o,v={id:f,message:l,type:d,title:i,duration:m,isVisible:!1};return e.value.push(v),setTimeout(()=>{v.isVisible=!0},10),m>0&&setTimeout(()=>{n(f)},m),f},n=l=>{const d=e.value.findIndex(i=>i.id===l);if(d>-1){const i=e.value[d];i.isVisible=!1,setTimeout(()=>{const m=e.value.findIndex(f=>f.id===l);m>-1&&e.value.splice(m,1)},300)}},p=()=>{e.value.forEach(l=>{l.isVisible=!1}),setTimeout(()=>{e.value.length=0},300)},c=(l,d="info",i=null,m=5e3)=>a(l,d,i,m);return R(()=>{window.showToast=c}),D(()=>{window.showToast===c&&delete window.showToast}),t({showToast:c,removeToast:n,clearAllToasts:p}),(l,d)=>(y(),q(N,{to:"body"},[h("div",_e,[(y(!0),b(G,null,M(e.value,i=>(y(),b("div",{key:i.id,class:S(["toast",`toast-${i.type}`,i.isVisible?"toast-show":"toast-hide"]),onClick:m=>n(i.id)},[h("div",ve,[h("div",ye,[h("i",{class:S(s(i.type))},null,2)]),h("div",we,[i.title?(y(),b("div",be,T(i.title),1)):x("",!0),h("div",Te,T(i.message),1)]),h("button",{class:"toast-close",onClick:U(m=>n(i.id),["stop"])},d[0]||(d[0]=[h("i",{class:"fas fa-times"},null,-1)]),8,Ee)]),i.duration>0?(y(),b("div",{key:0,class:"toast-progress",style:H({animationDuration:`${i.duration}ms`})},null,4)):x("",!0)],10,ge))),128))])]))}},ke=O(Ae,[["__scopeId","data-v-1a3ab19b"]]),Pe={class:"modal-content w-full max-w-md p-6 mx-auto"},xe={class:"flex items-start gap-4 mb-6"},Ce={class:"flex-1"},Ie={class:"text-lg font-semibold text-gray-900 mb-2"},Le={class:"text-gray-600 leading-relaxed whitespace-pre-line"},Se={class:"flex items-center justify-end gap-3"},Re=["disabled"],Ve=["disabled"],Oe={key:0,class:"loading-spinner mr-2"},$e={__name:"ConfirmDialog",setup(r,{expose:t}){const e=_(!1),o=_(!1),s=_(""),a=_(""),n=_("确认"),p=_("取消");let c=null;const l=(f,v,u="确认",g="取消")=>new Promise(j=>{s.value=f,a.value=v,n.value=u,p.value=g,e.value=!0,o.value=!1,c=j}),d=()=>{o.value||(o.value=!0,setTimeout(()=>{e.value=!1,o.value=!1,c&&(c(!0),c=null)},200))},i=()=>{o.value||(e.value=!1,c&&(c(!1),c=null))},m=f=>{e.value&&(f.key==="Escape"?i():f.key==="Enter"&&!f.shiftKey&&!f.ctrlKey&&!f.altKey&&d())};return R(()=>{window.showConfirm=l,document.addEventListener("keydown",m)}),D(()=>{window.showConfirm===l&&delete window.showConfirm,document.removeEventListener("keydown",m)}),t({showConfirm:l}),(f,v)=>(y(),q(N,{to:"body"},[P(Q,{name:"modal",appear:""},{default:J(()=>[e.value?(y(),b("div",{key:0,class:"fixed inset-0 modal z-[100] flex items-center justify-center p-4",onClick:U(i,["self"])},[h("div",Pe,[h("div",xe,[v[0]||(v[0]=h("div",{class:"flex-shrink-0 w-12 h-12 bg-gradient-to-br from-amber-500 to-amber-600 rounded-xl flex items-center justify-center"},[h("i",{class:"fas fa-exclamation-triangle text-white text-lg"})],-1)),h("div",Ce,[h("h3",Ie,T(s.value),1),h("div",Le,T(a.value),1)])]),h("div",Se,[h("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:o.value,onClick:i},T(p.value),9,Re),h("button",{class:S(["btn btn-warning px-6 py-3",{"opacity-50 cursor-not-allowed":o.value}]),disabled:o.value,onClick:d},[o.value?(y(),b("div",Oe)):x("",!0),X(" "+T(n.value),1)],10,Ve)])])])):x("",!0)]),_:1})]))}},De=O($e,[["__scopeId","data-v-bdb20ffd"]]),qe={id:"app"},Ne={__name:"App",setup(r){const t=B(),e=_(),o=_();return R(()=>{t.checkAuth(),t.loadOemSettings()}),(s,a)=>{const n=Y("router-view");return y(),b("div",qe,[P(n),P(ke,{ref_key:"toastRef",ref:e},null,512),P(De,{ref_key:"confirmRef",ref:o},null,512)])}}},Ue=O(Ne,[["__scopeId","data-v-5cba45f5"]]),I=Z(Ue),ze=ee();I.use(ze);I.use(C);I.use(te,{locale:oe});I.mount("#app");export{O as _,k as a,B as u}; diff --git a/web/admin-spa/dist/assets/index-V6aqLFfH.css b/web/admin-spa/dist/assets/index-V6aqLFfH.css deleted file mode 100644 index 92bf812a..00000000 --- a/web/admin-spa/dist/assets/index-V6aqLFfH.css +++ /dev/null @@ -1,5 +0,0 @@ -.toast-container[data-v-1a3ab19b]{position:fixed;top:20px;right:20px;z-index:9999;display:flex;flex-direction:column;gap:12px;pointer-events:none}.toast[data-v-1a3ab19b]{min-width:320px;max-width:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid #e5e7eb;overflow:hidden;position:relative;pointer-events:auto;cursor:pointer;transform:translate(100%);opacity:0;transition:all .3s cubic-bezier(.4,0,.2,1)}.toast-show[data-v-1a3ab19b]{transform:translate(0);opacity:1}.toast-hide[data-v-1a3ab19b]{transform:translate(100%);opacity:0}.toast-content[data-v-1a3ab19b]{display:flex;align-items:flex-start;padding:16px;gap:12px}.toast-icon[data-v-1a3ab19b]{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-size:14px}.toast-body[data-v-1a3ab19b]{flex:1}.toast-title[data-v-1a3ab19b]{font-weight:600;font-size:14px;line-height:1.4;margin-bottom:4px}.toast-message[data-v-1a3ab19b]{font-size:14px;line-height:1.5;word-wrap:break-word}.toast-close[data-v-1a3ab19b]{flex-shrink:0;width:24px;height:24px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;color:#9ca3af;transition:all .2s ease}.toast-close[data-v-1a3ab19b]:hover{background:#f3f4f6;color:#6b7280}.toast-progress[data-v-1a3ab19b]{position:absolute;bottom:0;left:0;height:3px;background:currentColor;opacity:.3;animation:toast-progress-1a3ab19b linear forwards}@keyframes toast-progress-1a3ab19b{0%{width:100%}to{width:0%}}.toast-success[data-v-1a3ab19b]{border-left:4px solid #10b981}.toast-success .toast-icon[data-v-1a3ab19b]{color:#10b981;background:#d1fae5}.toast-success .toast-title[data-v-1a3ab19b]{color:#065f46}.toast-success .toast-message[data-v-1a3ab19b]{color:#047857}.toast-success .toast-progress[data-v-1a3ab19b]{background:#10b981}.toast-error[data-v-1a3ab19b]{border-left:4px solid #ef4444}.toast-error .toast-icon[data-v-1a3ab19b]{color:#ef4444;background:#fee2e2}.toast-error .toast-title[data-v-1a3ab19b]{color:#991b1b}.toast-error .toast-message[data-v-1a3ab19b]{color:#dc2626}.toast-error .toast-progress[data-v-1a3ab19b]{background:#ef4444}.toast-warning[data-v-1a3ab19b]{border-left:4px solid #f59e0b}.toast-warning .toast-icon[data-v-1a3ab19b]{color:#f59e0b;background:#fef3c7}.toast-warning .toast-title[data-v-1a3ab19b]{color:#92400e}.toast-warning .toast-message[data-v-1a3ab19b]{color:#d97706}.toast-warning .toast-progress[data-v-1a3ab19b]{background:#f59e0b}.toast-info[data-v-1a3ab19b]{border-left:4px solid #3b82f6}.toast-info .toast-icon[data-v-1a3ab19b]{color:#3b82f6;background:#dbeafe}.toast-info .toast-title[data-v-1a3ab19b]{color:#1e40af}.toast-info .toast-message[data-v-1a3ab19b]{color:#2563eb}.toast-info .toast-progress[data-v-1a3ab19b]{background:#3b82f6}@media (max-width: 640px){.toast-container[data-v-1a3ab19b]{top:10px;right:10px;left:10px}.toast[data-v-1a3ab19b]{min-width:auto;max-width:none}}.toast-list-enter-active[data-v-1a3ab19b],.toast-list-leave-active[data-v-1a3ab19b]{transition:all .3s ease}.toast-list-enter-from[data-v-1a3ab19b],.toast-list-leave-to[data-v-1a3ab19b]{opacity:0;transform:translate(100%)}.toast-list-move[data-v-1a3ab19b]{transition:transform .3s ease}.modal[data-v-bdb20ffd]{background:#00000080;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.modal-content[data-v-bdb20ffd]{background:#fff;border-radius:16px;box-shadow:0 20px 64px #00000026;border:1px solid #e5e7eb;max-height:90vh;overflow-y:auto}.btn[data-v-bdb20ffd]{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn[data-v-bdb20ffd]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-danger[data-v-bdb20ffd]{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-danger[data-v-bdb20ffd]:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.btn-danger[data-v-bdb20ffd]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.btn-warning[data-v-bdb20ffd]{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-warning[data-v-bdb20ffd]:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.btn-warning[data-v-bdb20ffd]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(245 158 11 / var(--tw-ring-opacity, 1))}.loading-spinner[data-v-bdb20ffd]{height:1rem;width:1rem}@keyframes spin-bdb20ffd{to{transform:rotate(360deg)}}.loading-spinner[data-v-bdb20ffd]{animation:spin-bdb20ffd 1s linear infinite;border-radius:9999px;border-width:2px;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-border-opacity: 1;border-top-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.modal-enter-active[data-v-bdb20ffd],.modal-leave-active[data-v-bdb20ffd]{transition:all .3s ease}.modal-enter-from[data-v-bdb20ffd],.modal-leave-to[data-v-bdb20ffd]{opacity:0}.modal-enter-active .modal-content[data-v-bdb20ffd],.modal-leave-active .modal-content[data-v-bdb20ffd]{transition:transform .3s ease}.modal-enter-from .modal-content[data-v-bdb20ffd],.modal-leave-to .modal-content[data-v-bdb20ffd]{transform:scale(.9) translateY(-20px)}.modal-content[data-v-bdb20ffd]::-webkit-scrollbar{width:6px}.modal-content[data-v-bdb20ffd]::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px}.modal-content[data-v-bdb20ffd]::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.modal-content[data-v-bdb20ffd]::-webkit-scrollbar-thumb:hover{background:#94a3b8}#app[data-v-5cba45f5]{min-height:100vh}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.right-0{right:0}.right-3{right:.75rem}.top-0{top:0}.top-3{top:.75rem}.top-full{top:100%}.z-50{z-index:50}.z-\[100\]{z-index:100}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-2\.5{margin-left:.625rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-8{margin-right:2rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.table-row{display:table-row}.grid{display:grid}.hidden{display:none}.h-0\.5{height:.125rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.max-h-\[300px\]{max-height:300px}.max-h-\[90vh\]{max-height:90vh}.min-h-\[24px\]{min-height:24px}.min-h-\[32px\]{min-height:32px}.min-h-\[48px\]{min-height:48px}.min-h-\[60px\]{min-height:60px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-24{width:6rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[20px\]{min-width:20px}.min-w-\[32px\]{min-width:32px}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.divide-gray-200\/50>:not([hidden])~:not([hidden]){border-color:#e5e7eb80}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-400{--tw-border-opacity: 1;border-color:rgb(251 191 36 / var(--tw-border-opacity, 1))}.border-blue-100{--tw-border-opacity: 1;border-color:rgb(219 234 254 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-300{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-300\/30{border-color:#d1d5db4d}.border-green-100{--tw-border-opacity: 1;border-color:rgb(220 252 231 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-green-300{--tw-border-opacity: 1;border-color:rgb(134 239 172 / var(--tw-border-opacity, 1))}.border-green-600{--tw-border-opacity: 1;border-color:rgb(22 163 74 / var(--tw-border-opacity, 1))}.border-indigo-100{--tw-border-opacity: 1;border-color:rgb(224 231 255 / var(--tw-border-opacity, 1))}.border-orange-100{--tw-border-opacity: 1;border-color:rgb(255 237 213 / var(--tw-border-opacity, 1))}.border-orange-200{--tw-border-opacity: 1;border-color:rgb(254 215 170 / var(--tw-border-opacity, 1))}.border-purple-100{--tw-border-opacity: 1;border-color:rgb(243 232 255 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-red-500\/30{border-color:#ef44444d}.border-white\/20{border-color:#fff3}.border-yellow-100{--tw-border-opacity: 1;border-color:rgb(254 249 195 / var(--tw-border-opacity, 1))}.border-yellow-200{--tw-border-opacity: 1;border-color:rgb(254 240 138 / var(--tw-border-opacity, 1))}.border-yellow-300{--tw-border-opacity: 1;border-color:rgb(253 224 71 / var(--tw-border-opacity, 1))}.border-t-blue-600{--tw-border-opacity: 1;border-top-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-t-white{--tw-border-opacity: 1;border-top-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-300\/50{background-color:#d1d5db80}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-50\/80{background-color:#f9fafbcc}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-orange-200{--tw-bg-opacity: 1;background-color:rgb(254 215 170 / var(--tw-bg-opacity, 1))}.bg-orange-50{--tw-bg-opacity: 1;background-color:rgb(255 247 237 / var(--tw-bg-opacity, 1))}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-purple-500{--tw-bg-opacity: 1;background-color:rgb(168 85 247 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/20{background-color:#ef444433}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/10{background-color:#ffffff1a}.bg-white\/80{background-color:#fffc}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-yellow-50{--tw-bg-opacity: 1;background-color:rgb(254 252 232 / var(--tw-bg-opacity, 1))}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-amber-500{--tw-gradient-from: #f59e0b var(--tw-gradient-from-position);--tw-gradient-to: rgb(245 158 11 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-50{--tw-gradient-from: #eff6ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-500{--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-500\/20{--tw-gradient-from: rgb(59 130 246 / .2) var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-cyan-500{--tw-gradient-from: #06b6d4 var(--tw-gradient-from-position);--tw-gradient-to: rgb(6 182 212 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-emerald-500{--tw-gradient-from: #10b981 var(--tw-gradient-from-position);--tw-gradient-to: rgb(16 185 129 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-gray-50{--tw-gradient-from: #f9fafb var(--tw-gradient-from-position);--tw-gradient-to: rgb(249 250 251 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-50{--tw-gradient-from: #f0fdf4 var(--tw-gradient-from-position);--tw-gradient-to: rgb(240 253 244 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-500{--tw-gradient-from: #22c55e var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-indigo-50{--tw-gradient-from: #eef2ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(238 242 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-indigo-500{--tw-gradient-from: #6366f1 var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-orange-50{--tw-gradient-from: #fff7ed var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 247 237 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-orange-500{--tw-gradient-from: #f97316 var(--tw-gradient-from-position);--tw-gradient-to: rgb(249 115 22 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-purple-50{--tw-gradient-from: #faf5ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(250 245 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-purple-500{--tw-gradient-from: #a855f7 var(--tw-gradient-from-position);--tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-red-500{--tw-gradient-from: #ef4444 var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-rose-500{--tw-gradient-from: #f43f5e var(--tw-gradient-from-position);--tw-gradient-to: rgb(244 63 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-white{--tw-gradient-from: #fff var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-yellow-400{--tw-gradient-from: #facc15 var(--tw-gradient-from-position);--tw-gradient-to: rgb(250 204 21 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-yellow-50{--tw-gradient-from: #fefce8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(254 252 232 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-yellow-500{--tw-gradient-from: #eab308 var(--tw-gradient-from-position);--tw-gradient-to: rgb(234 179 8 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-amber-50{--tw-gradient-to: #fffbeb var(--tw-gradient-to-position)}.to-amber-600{--tw-gradient-to: #d97706 var(--tw-gradient-to-position)}.to-blue-500{--tw-gradient-to: #3b82f6 var(--tw-gradient-to-position)}.to-blue-600{--tw-gradient-to: #2563eb var(--tw-gradient-to-position)}.to-emerald-50{--tw-gradient-to: #ecfdf5 var(--tw-gradient-to-position)}.to-emerald-500{--tw-gradient-to: #10b981 var(--tw-gradient-to-position)}.to-emerald-600{--tw-gradient-to: #059669 var(--tw-gradient-to-position)}.to-gray-50{--tw-gradient-to: #f9fafb var(--tw-gradient-to-position)}.to-green-600{--tw-gradient-to: #16a34a var(--tw-gradient-to-position)}.to-indigo-50{--tw-gradient-to: #eef2ff var(--tw-gradient-to-position)}.to-indigo-600{--tw-gradient-to: #4f46e5 var(--tw-gradient-to-position)}.to-orange-500{--tw-gradient-to: #f97316 var(--tw-gradient-to-position)}.to-orange-600{--tw-gradient-to: #ea580c var(--tw-gradient-to-position)}.to-pink-50{--tw-gradient-to: #fdf2f8 var(--tw-gradient-to-position)}.to-pink-500{--tw-gradient-to: #ec4899 var(--tw-gradient-to-position)}.to-purple-50{--tw-gradient-to: #faf5ff var(--tw-gradient-to-position)}.to-purple-500{--tw-gradient-to: #a855f7 var(--tw-gradient-to-position)}.to-purple-500\/20{--tw-gradient-to: rgb(168 85 247 / .2) var(--tw-gradient-to-position)}.to-purple-600{--tw-gradient-to: #9333ea var(--tw-gradient-to-position)}.to-red-50{--tw-gradient-to: #fef2f2 var(--tw-gradient-to-position)}.to-rose-600{--tw-gradient-to: #e11d48 var(--tw-gradient-to-position)}.to-slate-50{--tw-gradient-to: #f8fafc var(--tw-gradient-to-position)}.to-yellow-50{--tw-gradient-to: #fefce8 var(--tw-gradient-to-position)}.to-yellow-500{--tw-gradient-to: #eab308 var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-10{padding:2.5rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pr-10{padding-right:2.5rem}.pr-14{padding-right:3.5rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wider{letter-spacing:.05em}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-amber-900{--tw-text-opacity: 1;color:rgb(120 53 15 / var(--tw-text-opacity, 1))}.text-blue-100{--tw-text-opacity: 1;color:rgb(219 234 254 / var(--tw-text-opacity, 1))}.text-blue-200{--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-blue-900{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-green-900{--tw-text-opacity: 1;color:rgb(20 83 45 / var(--tw-text-opacity, 1))}.text-indigo-500{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-indigo-800{--tw-text-opacity: 1;color:rgb(55 48 163 / var(--tw-text-opacity, 1))}.text-orange-500{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.text-orange-600{--tw-text-opacity: 1;color:rgb(234 88 12 / var(--tw-text-opacity, 1))}.text-orange-700{--tw-text-opacity: 1;color:rgb(194 65 12 / var(--tw-text-opacity, 1))}.text-orange-800{--tw-text-opacity: 1;color:rgb(154 52 18 / var(--tw-text-opacity, 1))}.text-purple-500{--tw-text-opacity: 1;color:rgb(168 85 247 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-purple-800{--tw-text-opacity: 1;color:rgb(107 33 168 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-rose-600{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\/70{color:#ffffffb3}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-30{opacity:.3}.opacity-50{opacity:.5}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur: blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.form-input{background:#ffffffe6;border:2px solid rgba(255,255,255,.3);border-radius:12px;padding:8px 12px;font-size:14px;transition:all .3s ease;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}/*! - * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2024 Fonticons, Inc. - */.fa{font-family:var(--fa-style-family, "Font Awesome 6 Free");font-weight:var(--fa-style, 900)}.fas,.far,.fab,.fa-solid,.fa-regular,.fa-brands,.fa{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display, inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fas:before,.far:before,.fab:before,.fa-solid:before,.fa-regular:before,.fa-brands:before,.fa:before{content:var(--fa)}.fa-classic,.fas,.fa-solid,.far,.fa-regular{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin, 2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(-1 * var(--fa-li-width, 2em));position:absolute;text-align:center;width:var(--fa-li-width, 2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color, #eee);border-radius:var(--fa-border-radius, .1em);border-style:var(--fa-border-style, solid);border-width:var(--fa-border-width, .08em);padding:var(--fa-border-padding, .2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin, .3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin, .3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(.28, .84, .42, 1))}.fa-fade{animation-name:fa-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1))}.fa-beat-fade{animation-name:fa-beat-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(.4, 0, .6, 1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-shake{animation-name:fa-shake;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin{animation-name:fa-spin;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 2s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin-reverse{--fa-animation-direction: reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, steps(8))}@media (prefers-reduced-motion: reduce){.fa-beat,.fa-bounce,.fa-fade,.fa-beat-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale, 1.25))}}@keyframes fa-bounce{0%{transform:scale(1) translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x, 1.1),var(--fa-bounce-start-scale-y, .9)) translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x, .9),var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x, 1.05),var(--fa-bounce-land-scale-y, .95)) translateY(0)}57%{transform:scale(1) translateY(var(--fa-bounce-rebound, -.125em))}64%{transform:scale(1) translateY(0)}to{transform:scale(1) translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity, .4)}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity, .4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale, 1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x, 0),var(--fa-flip-y, 1),var(--fa-flip-z, 0),var(--fa-flip-angle, -180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}8%,24%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}40%,to{transform:rotate(0)}}@keyframes fa-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle, 0))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index, auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse, #fff)}.fa-0{--fa: "0"}.fa-1{--fa: "1"}.fa-2{--fa: "2"}.fa-3{--fa: "3"}.fa-4{--fa: "4"}.fa-5{--fa: "5"}.fa-6{--fa: "6"}.fa-7{--fa: "7"}.fa-8{--fa: "8"}.fa-9{--fa: "9"}.fa-fill-drip{--fa: ""}.fa-arrows-to-circle{--fa: ""}.fa-circle-chevron-right,.fa-chevron-circle-right{--fa: ""}.fa-at{--fa: "@"}.fa-trash-can,.fa-trash-alt{--fa: ""}.fa-text-height{--fa: ""}.fa-user-xmark,.fa-user-times{--fa: ""}.fa-stethoscope{--fa: ""}.fa-message,.fa-comment-alt{--fa: ""}.fa-info{--fa: ""}.fa-down-left-and-up-right-to-center,.fa-compress-alt{--fa: ""}.fa-explosion{--fa: ""}.fa-file-lines,.fa-file-alt,.fa-file-text{--fa: ""}.fa-wave-square{--fa: ""}.fa-ring{--fa: ""}.fa-building-un{--fa: ""}.fa-dice-three{--fa: ""}.fa-calendar-days,.fa-calendar-alt{--fa: ""}.fa-anchor-circle-check{--fa: ""}.fa-building-circle-arrow-right{--fa: ""}.fa-volleyball,.fa-volleyball-ball{--fa: ""}.fa-arrows-up-to-line{--fa: ""}.fa-sort-down,.fa-sort-desc{--fa: ""}.fa-circle-minus,.fa-minus-circle{--fa: ""}.fa-door-open{--fa: ""}.fa-right-from-bracket,.fa-sign-out-alt{--fa: ""}.fa-atom{--fa: ""}.fa-soap{--fa: ""}.fa-icons,.fa-heart-music-camera-bolt{--fa: ""}.fa-microphone-lines-slash,.fa-microphone-alt-slash{--fa: ""}.fa-bridge-circle-check{--fa: ""}.fa-pump-medical{--fa: ""}.fa-fingerprint{--fa: ""}.fa-hand-point-right{--fa: ""}.fa-magnifying-glass-location,.fa-search-location{--fa: ""}.fa-forward-step,.fa-step-forward{--fa: ""}.fa-face-smile-beam,.fa-smile-beam{--fa: ""}.fa-flag-checkered{--fa: ""}.fa-football,.fa-football-ball{--fa: ""}.fa-school-circle-exclamation{--fa: ""}.fa-crop{--fa: ""}.fa-angles-down,.fa-angle-double-down{--fa: ""}.fa-users-rectangle{--fa: ""}.fa-people-roof{--fa: ""}.fa-people-line{--fa: ""}.fa-beer-mug-empty,.fa-beer{--fa: ""}.fa-diagram-predecessor{--fa: ""}.fa-arrow-up-long,.fa-long-arrow-up{--fa: ""}.fa-fire-flame-simple,.fa-burn{--fa: ""}.fa-person,.fa-male{--fa: ""}.fa-laptop{--fa: ""}.fa-file-csv{--fa: ""}.fa-menorah{--fa: ""}.fa-truck-plane{--fa: ""}.fa-record-vinyl{--fa: ""}.fa-face-grin-stars,.fa-grin-stars{--fa: ""}.fa-bong{--fa: ""}.fa-spaghetti-monster-flying,.fa-pastafarianism{--fa: ""}.fa-arrow-down-up-across-line{--fa: ""}.fa-spoon,.fa-utensil-spoon{--fa: ""}.fa-jar-wheat{--fa: ""}.fa-envelopes-bulk,.fa-mail-bulk{--fa: ""}.fa-file-circle-exclamation{--fa: ""}.fa-circle-h,.fa-hospital-symbol{--fa: ""}.fa-pager{--fa: ""}.fa-address-book,.fa-contact-book{--fa: ""}.fa-strikethrough{--fa: ""}.fa-k{--fa: "K"}.fa-landmark-flag{--fa: ""}.fa-pencil,.fa-pencil-alt{--fa: ""}.fa-backward{--fa: ""}.fa-caret-right{--fa: ""}.fa-comments{--fa: ""}.fa-paste,.fa-file-clipboard{--fa: ""}.fa-code-pull-request{--fa: ""}.fa-clipboard-list{--fa: ""}.fa-truck-ramp-box,.fa-truck-loading{--fa: ""}.fa-user-check{--fa: ""}.fa-vial-virus{--fa: ""}.fa-sheet-plastic{--fa: ""}.fa-blog{--fa: ""}.fa-user-ninja{--fa: ""}.fa-person-arrow-up-from-line{--fa: ""}.fa-scroll-torah,.fa-torah{--fa: ""}.fa-broom-ball,.fa-quidditch,.fa-quidditch-broom-ball{--fa: ""}.fa-toggle-off{--fa: ""}.fa-box-archive,.fa-archive{--fa: ""}.fa-person-drowning{--fa: ""}.fa-arrow-down-9-1,.fa-sort-numeric-desc,.fa-sort-numeric-down-alt{--fa: ""}.fa-face-grin-tongue-squint,.fa-grin-tongue-squint{--fa: ""}.fa-spray-can{--fa: ""}.fa-truck-monster{--fa: ""}.fa-w{--fa: "W"}.fa-earth-africa,.fa-globe-africa{--fa: ""}.fa-rainbow{--fa: ""}.fa-circle-notch{--fa: ""}.fa-tablet-screen-button,.fa-tablet-alt{--fa: ""}.fa-paw{--fa: ""}.fa-cloud{--fa: ""}.fa-trowel-bricks{--fa: ""}.fa-face-flushed,.fa-flushed{--fa: ""}.fa-hospital-user{--fa: ""}.fa-tent-arrow-left-right{--fa: ""}.fa-gavel,.fa-legal{--fa: ""}.fa-binoculars{--fa: ""}.fa-microphone-slash{--fa: ""}.fa-box-tissue{--fa: ""}.fa-motorcycle{--fa: ""}.fa-bell-concierge,.fa-concierge-bell{--fa: ""}.fa-pen-ruler,.fa-pencil-ruler{--fa: ""}.fa-people-arrows,.fa-people-arrows-left-right{--fa: ""}.fa-mars-and-venus-burst{--fa: ""}.fa-square-caret-right,.fa-caret-square-right{--fa: ""}.fa-scissors,.fa-cut{--fa: ""}.fa-sun-plant-wilt{--fa: ""}.fa-toilets-portable{--fa: ""}.fa-hockey-puck{--fa: ""}.fa-table{--fa: ""}.fa-magnifying-glass-arrow-right{--fa: ""}.fa-tachograph-digital,.fa-digital-tachograph{--fa: ""}.fa-users-slash{--fa: ""}.fa-clover{--fa: ""}.fa-reply,.fa-mail-reply{--fa: ""}.fa-star-and-crescent{--fa: ""}.fa-house-fire{--fa: ""}.fa-square-minus,.fa-minus-square{--fa: ""}.fa-helicopter{--fa: ""}.fa-compass{--fa: ""}.fa-square-caret-down,.fa-caret-square-down{--fa: ""}.fa-file-circle-question{--fa: ""}.fa-laptop-code{--fa: ""}.fa-swatchbook{--fa: ""}.fa-prescription-bottle{--fa: ""}.fa-bars,.fa-navicon{--fa: ""}.fa-people-group{--fa: ""}.fa-hourglass-end,.fa-hourglass-3{--fa: ""}.fa-heart-crack,.fa-heart-broken{--fa: ""}.fa-square-up-right,.fa-external-link-square-alt{--fa: ""}.fa-face-kiss-beam,.fa-kiss-beam{--fa: ""}.fa-film{--fa: ""}.fa-ruler-horizontal{--fa: ""}.fa-people-robbery{--fa: ""}.fa-lightbulb{--fa: ""}.fa-caret-left{--fa: ""}.fa-circle-exclamation,.fa-exclamation-circle{--fa: ""}.fa-school-circle-xmark{--fa: ""}.fa-arrow-right-from-bracket,.fa-sign-out{--fa: ""}.fa-circle-chevron-down,.fa-chevron-circle-down{--fa: ""}.fa-unlock-keyhole,.fa-unlock-alt{--fa: ""}.fa-cloud-showers-heavy{--fa: ""}.fa-headphones-simple,.fa-headphones-alt{--fa: ""}.fa-sitemap{--fa: ""}.fa-circle-dollar-to-slot,.fa-donate{--fa: ""}.fa-memory{--fa: ""}.fa-road-spikes{--fa: ""}.fa-fire-burner{--fa: ""}.fa-flag{--fa: ""}.fa-hanukiah{--fa: ""}.fa-feather{--fa: ""}.fa-volume-low,.fa-volume-down{--fa: ""}.fa-comment-slash{--fa: ""}.fa-cloud-sun-rain{--fa: ""}.fa-compress{--fa: ""}.fa-wheat-awn,.fa-wheat-alt{--fa: ""}.fa-ankh{--fa: ""}.fa-hands-holding-child{--fa: ""}.fa-asterisk{--fa: "*"}.fa-square-check,.fa-check-square{--fa: ""}.fa-peseta-sign{--fa: ""}.fa-heading,.fa-header{--fa: ""}.fa-ghost{--fa: ""}.fa-list,.fa-list-squares{--fa: ""}.fa-square-phone-flip,.fa-phone-square-alt{--fa: ""}.fa-cart-plus{--fa: ""}.fa-gamepad{--fa: ""}.fa-circle-dot,.fa-dot-circle{--fa: ""}.fa-face-dizzy,.fa-dizzy{--fa: ""}.fa-egg{--fa: ""}.fa-house-medical-circle-xmark{--fa: ""}.fa-campground{--fa: ""}.fa-folder-plus{--fa: ""}.fa-futbol,.fa-futbol-ball,.fa-soccer-ball{--fa: ""}.fa-paintbrush,.fa-paint-brush{--fa: ""}.fa-lock{--fa: ""}.fa-gas-pump{--fa: ""}.fa-hot-tub-person,.fa-hot-tub{--fa: ""}.fa-map-location,.fa-map-marked{--fa: ""}.fa-house-flood-water{--fa: ""}.fa-tree{--fa: ""}.fa-bridge-lock{--fa: ""}.fa-sack-dollar{--fa: ""}.fa-pen-to-square,.fa-edit{--fa: ""}.fa-car-side{--fa: ""}.fa-share-nodes,.fa-share-alt{--fa: ""}.fa-heart-circle-minus{--fa: ""}.fa-hourglass-half,.fa-hourglass-2{--fa: ""}.fa-microscope{--fa: ""}.fa-sink{--fa: ""}.fa-bag-shopping,.fa-shopping-bag{--fa: ""}.fa-arrow-down-z-a,.fa-sort-alpha-desc,.fa-sort-alpha-down-alt{--fa: ""}.fa-mitten{--fa: ""}.fa-person-rays{--fa: ""}.fa-users{--fa: ""}.fa-eye-slash{--fa: ""}.fa-flask-vial{--fa: ""}.fa-hand,.fa-hand-paper{--fa: ""}.fa-om{--fa: ""}.fa-worm{--fa: ""}.fa-house-circle-xmark{--fa: ""}.fa-plug{--fa: ""}.fa-chevron-up{--fa: ""}.fa-hand-spock{--fa: ""}.fa-stopwatch{--fa: ""}.fa-face-kiss,.fa-kiss{--fa: ""}.fa-bridge-circle-xmark{--fa: ""}.fa-face-grin-tongue,.fa-grin-tongue{--fa: ""}.fa-chess-bishop{--fa: ""}.fa-face-grin-wink,.fa-grin-wink{--fa: ""}.fa-ear-deaf,.fa-deaf,.fa-deafness,.fa-hard-of-hearing{--fa: ""}.fa-road-circle-check{--fa: ""}.fa-dice-five{--fa: ""}.fa-square-rss,.fa-rss-square{--fa: ""}.fa-land-mine-on{--fa: ""}.fa-i-cursor{--fa: ""}.fa-stamp{--fa: ""}.fa-stairs{--fa: ""}.fa-i{--fa: "I"}.fa-hryvnia-sign,.fa-hryvnia{--fa: ""}.fa-pills{--fa: ""}.fa-face-grin-wide,.fa-grin-alt{--fa: ""}.fa-tooth{--fa: ""}.fa-v{--fa: "V"}.fa-bangladeshi-taka-sign{--fa: ""}.fa-bicycle{--fa: ""}.fa-staff-snake,.fa-rod-asclepius,.fa-rod-snake,.fa-staff-aesculapius{--fa: ""}.fa-head-side-cough-slash{--fa: ""}.fa-truck-medical,.fa-ambulance{--fa: ""}.fa-wheat-awn-circle-exclamation{--fa: ""}.fa-snowman{--fa: ""}.fa-mortar-pestle{--fa: ""}.fa-road-barrier{--fa: ""}.fa-school{--fa: ""}.fa-igloo{--fa: ""}.fa-joint{--fa: ""}.fa-angle-right{--fa: ""}.fa-horse{--fa: ""}.fa-q{--fa: "Q"}.fa-g{--fa: "G"}.fa-notes-medical{--fa: ""}.fa-temperature-half,.fa-temperature-2,.fa-thermometer-2,.fa-thermometer-half{--fa: ""}.fa-dong-sign{--fa: ""}.fa-capsules{--fa: ""}.fa-poo-storm,.fa-poo-bolt{--fa: ""}.fa-face-frown-open,.fa-frown-open{--fa: ""}.fa-hand-point-up{--fa: ""}.fa-money-bill{--fa: ""}.fa-bookmark{--fa: ""}.fa-align-justify{--fa: ""}.fa-umbrella-beach{--fa: ""}.fa-helmet-un{--fa: ""}.fa-bullseye{--fa: ""}.fa-bacon{--fa: ""}.fa-hand-point-down{--fa: ""}.fa-arrow-up-from-bracket{--fa: ""}.fa-folder,.fa-folder-blank{--fa: ""}.fa-file-waveform,.fa-file-medical-alt{--fa: ""}.fa-radiation{--fa: ""}.fa-chart-simple{--fa: ""}.fa-mars-stroke{--fa: ""}.fa-vial{--fa: ""}.fa-gauge,.fa-dashboard,.fa-gauge-med,.fa-tachometer-alt-average{--fa: ""}.fa-wand-magic-sparkles,.fa-magic-wand-sparkles{--fa: ""}.fa-e{--fa: "E"}.fa-pen-clip,.fa-pen-alt{--fa: ""}.fa-bridge-circle-exclamation{--fa: ""}.fa-user{--fa: ""}.fa-school-circle-check{--fa: ""}.fa-dumpster{--fa: ""}.fa-van-shuttle,.fa-shuttle-van{--fa: ""}.fa-building-user{--fa: ""}.fa-square-caret-left,.fa-caret-square-left{--fa: ""}.fa-highlighter{--fa: ""}.fa-key{--fa: ""}.fa-bullhorn{--fa: ""}.fa-globe{--fa: ""}.fa-synagogue{--fa: ""}.fa-person-half-dress{--fa: ""}.fa-road-bridge{--fa: ""}.fa-location-arrow{--fa: ""}.fa-c{--fa: "C"}.fa-tablet-button{--fa: ""}.fa-building-lock{--fa: ""}.fa-pizza-slice{--fa: ""}.fa-money-bill-wave{--fa: ""}.fa-chart-area,.fa-area-chart{--fa: ""}.fa-house-flag{--fa: ""}.fa-person-circle-minus{--fa: ""}.fa-ban,.fa-cancel{--fa: ""}.fa-camera-rotate{--fa: ""}.fa-spray-can-sparkles,.fa-air-freshener{--fa: ""}.fa-star{--fa: ""}.fa-repeat{--fa: ""}.fa-cross{--fa: ""}.fa-box{--fa: ""}.fa-venus-mars{--fa: ""}.fa-arrow-pointer,.fa-mouse-pointer{--fa: ""}.fa-maximize,.fa-expand-arrows-alt{--fa: ""}.fa-charging-station{--fa: ""}.fa-shapes,.fa-triangle-circle-square{--fa: ""}.fa-shuffle,.fa-random{--fa: ""}.fa-person-running,.fa-running{--fa: ""}.fa-mobile-retro{--fa: ""}.fa-grip-lines-vertical{--fa: ""}.fa-spider{--fa: ""}.fa-hands-bound{--fa: ""}.fa-file-invoice-dollar{--fa: ""}.fa-plane-circle-exclamation{--fa: ""}.fa-x-ray{--fa: ""}.fa-spell-check{--fa: ""}.fa-slash{--fa: ""}.fa-computer-mouse,.fa-mouse{--fa: ""}.fa-arrow-right-to-bracket,.fa-sign-in{--fa: ""}.fa-shop-slash,.fa-store-alt-slash{--fa: ""}.fa-server{--fa: ""}.fa-virus-covid-slash{--fa: ""}.fa-shop-lock{--fa: ""}.fa-hourglass-start,.fa-hourglass-1{--fa: ""}.fa-blender-phone{--fa: ""}.fa-building-wheat{--fa: ""}.fa-person-breastfeeding{--fa: ""}.fa-right-to-bracket,.fa-sign-in-alt{--fa: ""}.fa-venus{--fa: ""}.fa-passport{--fa: ""}.fa-thumbtack-slash,.fa-thumb-tack-slash{--fa: ""}.fa-heart-pulse,.fa-heartbeat{--fa: ""}.fa-people-carry-box,.fa-people-carry{--fa: ""}.fa-temperature-high{--fa: ""}.fa-microchip{--fa: ""}.fa-crown{--fa: ""}.fa-weight-hanging{--fa: ""}.fa-xmarks-lines{--fa: ""}.fa-file-prescription{--fa: ""}.fa-weight-scale,.fa-weight{--fa: ""}.fa-user-group,.fa-user-friends{--fa: ""}.fa-arrow-up-a-z,.fa-sort-alpha-up{--fa: ""}.fa-chess-knight{--fa: ""}.fa-face-laugh-squint,.fa-laugh-squint{--fa: ""}.fa-wheelchair{--fa: ""}.fa-circle-arrow-up,.fa-arrow-circle-up{--fa: ""}.fa-toggle-on{--fa: ""}.fa-person-walking,.fa-walking{--fa: ""}.fa-l{--fa: "L"}.fa-fire{--fa: ""}.fa-bed-pulse,.fa-procedures{--fa: ""}.fa-shuttle-space,.fa-space-shuttle{--fa: ""}.fa-face-laugh,.fa-laugh{--fa: ""}.fa-folder-open{--fa: ""}.fa-heart-circle-plus{--fa: ""}.fa-code-fork{--fa: ""}.fa-city{--fa: ""}.fa-microphone-lines,.fa-microphone-alt{--fa: ""}.fa-pepper-hot{--fa: ""}.fa-unlock{--fa: ""}.fa-colon-sign{--fa: ""}.fa-headset{--fa: ""}.fa-store-slash{--fa: ""}.fa-road-circle-xmark{--fa: ""}.fa-user-minus{--fa: ""}.fa-mars-stroke-up,.fa-mars-stroke-v{--fa: ""}.fa-champagne-glasses,.fa-glass-cheers{--fa: ""}.fa-clipboard{--fa: ""}.fa-house-circle-exclamation{--fa: ""}.fa-file-arrow-up,.fa-file-upload{--fa: ""}.fa-wifi,.fa-wifi-3,.fa-wifi-strong{--fa: ""}.fa-bath,.fa-bathtub{--fa: ""}.fa-underline{--fa: ""}.fa-user-pen,.fa-user-edit{--fa: ""}.fa-signature{--fa: ""}.fa-stroopwafel{--fa: ""}.fa-bold{--fa: ""}.fa-anchor-lock{--fa: ""}.fa-building-ngo{--fa: ""}.fa-manat-sign{--fa: ""}.fa-not-equal{--fa: ""}.fa-border-top-left,.fa-border-style{--fa: ""}.fa-map-location-dot,.fa-map-marked-alt{--fa: ""}.fa-jedi{--fa: ""}.fa-square-poll-vertical,.fa-poll{--fa: ""}.fa-mug-hot{--fa: ""}.fa-car-battery,.fa-battery-car{--fa: ""}.fa-gift{--fa: ""}.fa-dice-two{--fa: ""}.fa-chess-queen{--fa: ""}.fa-glasses{--fa: ""}.fa-chess-board{--fa: ""}.fa-building-circle-check{--fa: ""}.fa-person-chalkboard{--fa: ""}.fa-mars-stroke-right,.fa-mars-stroke-h{--fa: ""}.fa-hand-back-fist,.fa-hand-rock{--fa: ""}.fa-square-caret-up,.fa-caret-square-up{--fa: ""}.fa-cloud-showers-water{--fa: ""}.fa-chart-bar,.fa-bar-chart{--fa: ""}.fa-hands-bubbles,.fa-hands-wash{--fa: ""}.fa-less-than-equal{--fa: ""}.fa-train{--fa: ""}.fa-eye-low-vision,.fa-low-vision{--fa: ""}.fa-crow{--fa: ""}.fa-sailboat{--fa: ""}.fa-window-restore{--fa: ""}.fa-square-plus,.fa-plus-square{--fa: ""}.fa-torii-gate{--fa: ""}.fa-frog{--fa: ""}.fa-bucket{--fa: ""}.fa-image{--fa: ""}.fa-microphone{--fa: ""}.fa-cow{--fa: ""}.fa-caret-up{--fa: ""}.fa-screwdriver{--fa: ""}.fa-folder-closed{--fa: ""}.fa-house-tsunami{--fa: ""}.fa-square-nfi{--fa: ""}.fa-arrow-up-from-ground-water{--fa: ""}.fa-martini-glass,.fa-glass-martini-alt{--fa: ""}.fa-square-binary{--fa: ""}.fa-rotate-left,.fa-rotate-back,.fa-rotate-backward,.fa-undo-alt{--fa: ""}.fa-table-columns,.fa-columns{--fa: ""}.fa-lemon{--fa: ""}.fa-head-side-mask{--fa: ""}.fa-handshake{--fa: ""}.fa-gem{--fa: ""}.fa-dolly,.fa-dolly-box{--fa: ""}.fa-smoking{--fa: ""}.fa-minimize,.fa-compress-arrows-alt{--fa: ""}.fa-monument{--fa: ""}.fa-snowplow{--fa: ""}.fa-angles-right,.fa-angle-double-right{--fa: ""}.fa-cannabis{--fa: ""}.fa-circle-play,.fa-play-circle{--fa: ""}.fa-tablets{--fa: ""}.fa-ethernet{--fa: ""}.fa-euro-sign,.fa-eur,.fa-euro{--fa: ""}.fa-chair{--fa: ""}.fa-circle-check,.fa-check-circle{--fa: ""}.fa-circle-stop,.fa-stop-circle{--fa: ""}.fa-compass-drafting,.fa-drafting-compass{--fa: ""}.fa-plate-wheat{--fa: ""}.fa-icicles{--fa: ""}.fa-person-shelter{--fa: ""}.fa-neuter{--fa: ""}.fa-id-badge{--fa: ""}.fa-marker{--fa: ""}.fa-face-laugh-beam,.fa-laugh-beam{--fa: ""}.fa-helicopter-symbol{--fa: ""}.fa-universal-access{--fa: ""}.fa-circle-chevron-up,.fa-chevron-circle-up{--fa: ""}.fa-lari-sign{--fa: ""}.fa-volcano{--fa: ""}.fa-person-walking-dashed-line-arrow-right{--fa: ""}.fa-sterling-sign,.fa-gbp,.fa-pound-sign{--fa: ""}.fa-viruses{--fa: ""}.fa-square-person-confined{--fa: ""}.fa-user-tie{--fa: ""}.fa-arrow-down-long,.fa-long-arrow-down{--fa: ""}.fa-tent-arrow-down-to-line{--fa: ""}.fa-certificate{--fa: ""}.fa-reply-all,.fa-mail-reply-all{--fa: ""}.fa-suitcase{--fa: ""}.fa-person-skating,.fa-skating{--fa: ""}.fa-filter-circle-dollar,.fa-funnel-dollar{--fa: ""}.fa-camera-retro{--fa: ""}.fa-circle-arrow-down,.fa-arrow-circle-down{--fa: ""}.fa-file-import,.fa-arrow-right-to-file{--fa: ""}.fa-square-arrow-up-right,.fa-external-link-square{--fa: ""}.fa-box-open{--fa: ""}.fa-scroll{--fa: ""}.fa-spa{--fa: ""}.fa-location-pin-lock{--fa: ""}.fa-pause{--fa: ""}.fa-hill-avalanche{--fa: ""}.fa-temperature-empty,.fa-temperature-0,.fa-thermometer-0,.fa-thermometer-empty{--fa: ""}.fa-bomb{--fa: ""}.fa-registered{--fa: ""}.fa-address-card,.fa-contact-card,.fa-vcard{--fa: ""}.fa-scale-unbalanced-flip,.fa-balance-scale-right{--fa: ""}.fa-subscript{--fa: ""}.fa-diamond-turn-right,.fa-directions{--fa: ""}.fa-burst{--fa: ""}.fa-house-laptop,.fa-laptop-house{--fa: ""}.fa-face-tired,.fa-tired{--fa: ""}.fa-money-bills{--fa: ""}.fa-smog{--fa: ""}.fa-crutch{--fa: ""}.fa-cloud-arrow-up,.fa-cloud-upload,.fa-cloud-upload-alt{--fa: ""}.fa-palette{--fa: ""}.fa-arrows-turn-right{--fa: ""}.fa-vest{--fa: ""}.fa-ferry{--fa: ""}.fa-arrows-down-to-people{--fa: ""}.fa-seedling,.fa-sprout{--fa: ""}.fa-left-right,.fa-arrows-alt-h{--fa: ""}.fa-boxes-packing{--fa: ""}.fa-circle-arrow-left,.fa-arrow-circle-left{--fa: ""}.fa-group-arrows-rotate{--fa: ""}.fa-bowl-food{--fa: ""}.fa-candy-cane{--fa: ""}.fa-arrow-down-wide-short,.fa-sort-amount-asc,.fa-sort-amount-down{--fa: ""}.fa-cloud-bolt,.fa-thunderstorm{--fa: ""}.fa-text-slash,.fa-remove-format{--fa: ""}.fa-face-smile-wink,.fa-smile-wink{--fa: ""}.fa-file-word{--fa: ""}.fa-file-powerpoint{--fa: ""}.fa-arrows-left-right,.fa-arrows-h{--fa: ""}.fa-house-lock{--fa: ""}.fa-cloud-arrow-down,.fa-cloud-download,.fa-cloud-download-alt{--fa: ""}.fa-children{--fa: ""}.fa-chalkboard,.fa-blackboard{--fa: ""}.fa-user-large-slash,.fa-user-alt-slash{--fa: ""}.fa-envelope-open{--fa: ""}.fa-handshake-simple-slash,.fa-handshake-alt-slash{--fa: ""}.fa-mattress-pillow{--fa: ""}.fa-guarani-sign{--fa: ""}.fa-arrows-rotate,.fa-refresh,.fa-sync{--fa: ""}.fa-fire-extinguisher{--fa: ""}.fa-cruzeiro-sign{--fa: ""}.fa-greater-than-equal{--fa: ""}.fa-shield-halved,.fa-shield-alt{--fa: ""}.fa-book-atlas,.fa-atlas{--fa: ""}.fa-virus{--fa: ""}.fa-envelope-circle-check{--fa: ""}.fa-layer-group{--fa: ""}.fa-arrows-to-dot{--fa: ""}.fa-archway{--fa: ""}.fa-heart-circle-check{--fa: ""}.fa-house-chimney-crack,.fa-house-damage{--fa: ""}.fa-file-zipper,.fa-file-archive{--fa: ""}.fa-square{--fa: ""}.fa-martini-glass-empty,.fa-glass-martini{--fa: ""}.fa-couch{--fa: ""}.fa-cedi-sign{--fa: ""}.fa-italic{--fa: ""}.fa-table-cells-column-lock{--fa: ""}.fa-church{--fa: ""}.fa-comments-dollar{--fa: ""}.fa-democrat{--fa: ""}.fa-z{--fa: "Z"}.fa-person-skiing,.fa-skiing{--fa: ""}.fa-road-lock{--fa: ""}.fa-a{--fa: "A"}.fa-temperature-arrow-down,.fa-temperature-down{--fa: ""}.fa-feather-pointed,.fa-feather-alt{--fa: ""}.fa-p{--fa: "P"}.fa-snowflake{--fa: ""}.fa-newspaper{--fa: ""}.fa-rectangle-ad,.fa-ad{--fa: ""}.fa-circle-arrow-right,.fa-arrow-circle-right{--fa: ""}.fa-filter-circle-xmark{--fa: ""}.fa-locust{--fa: ""}.fa-sort,.fa-unsorted{--fa: ""}.fa-list-ol,.fa-list-1-2,.fa-list-numeric{--fa: ""}.fa-person-dress-burst{--fa: ""}.fa-money-check-dollar,.fa-money-check-alt{--fa: ""}.fa-vector-square{--fa: ""}.fa-bread-slice{--fa: ""}.fa-language{--fa: ""}.fa-face-kiss-wink-heart,.fa-kiss-wink-heart{--fa: ""}.fa-filter{--fa: ""}.fa-question{--fa: "?"}.fa-file-signature{--fa: ""}.fa-up-down-left-right,.fa-arrows-alt{--fa: ""}.fa-house-chimney-user{--fa: ""}.fa-hand-holding-heart{--fa: ""}.fa-puzzle-piece{--fa: ""}.fa-money-check{--fa: ""}.fa-star-half-stroke,.fa-star-half-alt{--fa: ""}.fa-code{--fa: ""}.fa-whiskey-glass,.fa-glass-whiskey{--fa: ""}.fa-building-circle-exclamation{--fa: ""}.fa-magnifying-glass-chart{--fa: ""}.fa-arrow-up-right-from-square,.fa-external-link{--fa: ""}.fa-cubes-stacked{--fa: ""}.fa-won-sign,.fa-krw,.fa-won{--fa: ""}.fa-virus-covid{--fa: ""}.fa-austral-sign{--fa: ""}.fa-f{--fa: "F"}.fa-leaf{--fa: ""}.fa-road{--fa: ""}.fa-taxi,.fa-cab{--fa: ""}.fa-person-circle-plus{--fa: ""}.fa-chart-pie,.fa-pie-chart{--fa: ""}.fa-bolt-lightning{--fa: ""}.fa-sack-xmark{--fa: ""}.fa-file-excel{--fa: ""}.fa-file-contract{--fa: ""}.fa-fish-fins{--fa: ""}.fa-building-flag{--fa: ""}.fa-face-grin-beam,.fa-grin-beam{--fa: ""}.fa-object-ungroup{--fa: ""}.fa-poop{--fa: ""}.fa-location-pin,.fa-map-marker{--fa: ""}.fa-kaaba{--fa: ""}.fa-toilet-paper{--fa: ""}.fa-helmet-safety,.fa-hard-hat,.fa-hat-hard{--fa: ""}.fa-eject{--fa: ""}.fa-circle-right,.fa-arrow-alt-circle-right{--fa: ""}.fa-plane-circle-check{--fa: ""}.fa-face-rolling-eyes,.fa-meh-rolling-eyes{--fa: ""}.fa-object-group{--fa: ""}.fa-chart-line,.fa-line-chart{--fa: ""}.fa-mask-ventilator{--fa: ""}.fa-arrow-right{--fa: ""}.fa-signs-post,.fa-map-signs{--fa: ""}.fa-cash-register{--fa: ""}.fa-person-circle-question{--fa: ""}.fa-h{--fa: "H"}.fa-tarp{--fa: ""}.fa-screwdriver-wrench,.fa-tools{--fa: ""}.fa-arrows-to-eye{--fa: ""}.fa-plug-circle-bolt{--fa: ""}.fa-heart{--fa: ""}.fa-mars-and-venus{--fa: ""}.fa-house-user,.fa-home-user{--fa: ""}.fa-dumpster-fire{--fa: ""}.fa-house-crack{--fa: ""}.fa-martini-glass-citrus,.fa-cocktail{--fa: ""}.fa-face-surprise,.fa-surprise{--fa: ""}.fa-bottle-water{--fa: ""}.fa-circle-pause,.fa-pause-circle{--fa: ""}.fa-toilet-paper-slash{--fa: ""}.fa-apple-whole,.fa-apple-alt{--fa: ""}.fa-kitchen-set{--fa: ""}.fa-r{--fa: "R"}.fa-temperature-quarter,.fa-temperature-1,.fa-thermometer-1,.fa-thermometer-quarter{--fa: ""}.fa-cube{--fa: ""}.fa-bitcoin-sign{--fa: ""}.fa-shield-dog{--fa: ""}.fa-solar-panel{--fa: ""}.fa-lock-open{--fa: ""}.fa-elevator{--fa: ""}.fa-money-bill-transfer{--fa: ""}.fa-money-bill-trend-up{--fa: ""}.fa-house-flood-water-circle-arrow-right{--fa: ""}.fa-square-poll-horizontal,.fa-poll-h{--fa: ""}.fa-circle{--fa: ""}.fa-backward-fast,.fa-fast-backward{--fa: ""}.fa-recycle{--fa: ""}.fa-user-astronaut{--fa: ""}.fa-plane-slash{--fa: ""}.fa-trademark{--fa: ""}.fa-basketball,.fa-basketball-ball{--fa: ""}.fa-satellite-dish{--fa: ""}.fa-circle-up,.fa-arrow-alt-circle-up{--fa: ""}.fa-mobile-screen-button,.fa-mobile-alt{--fa: ""}.fa-volume-high,.fa-volume-up{--fa: ""}.fa-users-rays{--fa: ""}.fa-wallet{--fa: ""}.fa-clipboard-check{--fa: ""}.fa-file-audio{--fa: ""}.fa-burger,.fa-hamburger{--fa: ""}.fa-wrench{--fa: ""}.fa-bugs{--fa: ""}.fa-rupee-sign,.fa-rupee{--fa: ""}.fa-file-image{--fa: ""}.fa-circle-question,.fa-question-circle{--fa: ""}.fa-plane-departure{--fa: ""}.fa-handshake-slash{--fa: ""}.fa-book-bookmark{--fa: ""}.fa-code-branch{--fa: ""}.fa-hat-cowboy{--fa: ""}.fa-bridge{--fa: ""}.fa-phone-flip,.fa-phone-alt{--fa: ""}.fa-truck-front{--fa: ""}.fa-cat{--fa: ""}.fa-anchor-circle-exclamation{--fa: ""}.fa-truck-field{--fa: ""}.fa-route{--fa: ""}.fa-clipboard-question{--fa: ""}.fa-panorama{--fa: ""}.fa-comment-medical{--fa: ""}.fa-teeth-open{--fa: ""}.fa-file-circle-minus{--fa: ""}.fa-tags{--fa: ""}.fa-wine-glass{--fa: ""}.fa-forward-fast,.fa-fast-forward{--fa: ""}.fa-face-meh-blank,.fa-meh-blank{--fa: ""}.fa-square-parking,.fa-parking{--fa: ""}.fa-house-signal{--fa: ""}.fa-bars-progress,.fa-tasks-alt{--fa: ""}.fa-faucet-drip{--fa: ""}.fa-cart-flatbed,.fa-dolly-flatbed{--fa: ""}.fa-ban-smoking,.fa-smoking-ban{--fa: ""}.fa-terminal{--fa: ""}.fa-mobile-button{--fa: ""}.fa-house-medical-flag{--fa: ""}.fa-basket-shopping,.fa-shopping-basket{--fa: ""}.fa-tape{--fa: ""}.fa-bus-simple,.fa-bus-alt{--fa: ""}.fa-eye{--fa: ""}.fa-face-sad-cry,.fa-sad-cry{--fa: ""}.fa-audio-description{--fa: ""}.fa-person-military-to-person{--fa: ""}.fa-file-shield{--fa: ""}.fa-user-slash{--fa: ""}.fa-pen{--fa: ""}.fa-tower-observation{--fa: ""}.fa-file-code{--fa: ""}.fa-signal,.fa-signal-5,.fa-signal-perfect{--fa: ""}.fa-bus{--fa: ""}.fa-heart-circle-xmark{--fa: ""}.fa-house-chimney,.fa-home-lg{--fa: ""}.fa-window-maximize{--fa: ""}.fa-face-frown,.fa-frown{--fa: ""}.fa-prescription{--fa: ""}.fa-shop,.fa-store-alt{--fa: ""}.fa-floppy-disk,.fa-save{--fa: ""}.fa-vihara{--fa: ""}.fa-scale-unbalanced,.fa-balance-scale-left{--fa: ""}.fa-sort-up,.fa-sort-asc{--fa: ""}.fa-comment-dots,.fa-commenting{--fa: ""}.fa-plant-wilt{--fa: ""}.fa-diamond{--fa: ""}.fa-face-grin-squint,.fa-grin-squint{--fa: ""}.fa-hand-holding-dollar,.fa-hand-holding-usd{--fa: ""}.fa-chart-diagram{--fa: ""}.fa-bacterium{--fa: ""}.fa-hand-pointer{--fa: ""}.fa-drum-steelpan{--fa: ""}.fa-hand-scissors{--fa: ""}.fa-hands-praying,.fa-praying-hands{--fa: ""}.fa-arrow-rotate-right,.fa-arrow-right-rotate,.fa-arrow-rotate-forward,.fa-redo{--fa: ""}.fa-biohazard{--fa: ""}.fa-location-crosshairs,.fa-location{--fa: ""}.fa-mars-double{--fa: ""}.fa-child-dress{--fa: ""}.fa-users-between-lines{--fa: ""}.fa-lungs-virus{--fa: ""}.fa-face-grin-tears,.fa-grin-tears{--fa: ""}.fa-phone{--fa: ""}.fa-calendar-xmark,.fa-calendar-times{--fa: ""}.fa-child-reaching{--fa: ""}.fa-head-side-virus{--fa: ""}.fa-user-gear,.fa-user-cog{--fa: ""}.fa-arrow-up-1-9,.fa-sort-numeric-up{--fa: ""}.fa-door-closed{--fa: ""}.fa-shield-virus{--fa: ""}.fa-dice-six{--fa: ""}.fa-mosquito-net{--fa: ""}.fa-file-fragment{--fa: ""}.fa-bridge-water{--fa: ""}.fa-person-booth{--fa: ""}.fa-text-width{--fa: ""}.fa-hat-wizard{--fa: ""}.fa-pen-fancy{--fa: ""}.fa-person-digging,.fa-digging{--fa: ""}.fa-trash{--fa: ""}.fa-gauge-simple,.fa-gauge-simple-med,.fa-tachometer-average{--fa: ""}.fa-book-medical{--fa: ""}.fa-poo{--fa: ""}.fa-quote-right,.fa-quote-right-alt{--fa: ""}.fa-shirt,.fa-t-shirt,.fa-tshirt{--fa: ""}.fa-cubes{--fa: ""}.fa-divide{--fa: ""}.fa-tenge-sign,.fa-tenge{--fa: ""}.fa-headphones{--fa: ""}.fa-hands-holding{--fa: ""}.fa-hands-clapping{--fa: ""}.fa-republican{--fa: ""}.fa-arrow-left{--fa: ""}.fa-person-circle-xmark{--fa: ""}.fa-ruler{--fa: ""}.fa-align-left{--fa: ""}.fa-dice-d6{--fa: ""}.fa-restroom{--fa: ""}.fa-j{--fa: "J"}.fa-users-viewfinder{--fa: ""}.fa-file-video{--fa: ""}.fa-up-right-from-square,.fa-external-link-alt{--fa: ""}.fa-table-cells,.fa-th{--fa: ""}.fa-file-pdf{--fa: ""}.fa-book-bible,.fa-bible{--fa: ""}.fa-o{--fa: "O"}.fa-suitcase-medical,.fa-medkit{--fa: ""}.fa-user-secret{--fa: ""}.fa-otter{--fa: ""}.fa-person-dress,.fa-female{--fa: ""}.fa-comment-dollar{--fa: ""}.fa-business-time,.fa-briefcase-clock{--fa: ""}.fa-table-cells-large,.fa-th-large{--fa: ""}.fa-book-tanakh,.fa-tanakh{--fa: ""}.fa-phone-volume,.fa-volume-control-phone{--fa: ""}.fa-hat-cowboy-side{--fa: ""}.fa-clipboard-user{--fa: ""}.fa-child{--fa: ""}.fa-lira-sign{--fa: ""}.fa-satellite{--fa: ""}.fa-plane-lock{--fa: ""}.fa-tag{--fa: ""}.fa-comment{--fa: ""}.fa-cake-candles,.fa-birthday-cake,.fa-cake{--fa: ""}.fa-envelope{--fa: ""}.fa-angles-up,.fa-angle-double-up{--fa: ""}.fa-paperclip{--fa: ""}.fa-arrow-right-to-city{--fa: ""}.fa-ribbon{--fa: ""}.fa-lungs{--fa: ""}.fa-arrow-up-9-1,.fa-sort-numeric-up-alt{--fa: ""}.fa-litecoin-sign{--fa: ""}.fa-border-none{--fa: ""}.fa-circle-nodes{--fa: ""}.fa-parachute-box{--fa: ""}.fa-indent{--fa: ""}.fa-truck-field-un{--fa: ""}.fa-hourglass,.fa-hourglass-empty{--fa: ""}.fa-mountain{--fa: ""}.fa-user-doctor,.fa-user-md{--fa: ""}.fa-circle-info,.fa-info-circle{--fa: ""}.fa-cloud-meatball{--fa: ""}.fa-camera,.fa-camera-alt{--fa: ""}.fa-square-virus{--fa: ""}.fa-meteor{--fa: ""}.fa-car-on{--fa: ""}.fa-sleigh{--fa: ""}.fa-arrow-down-1-9,.fa-sort-numeric-asc,.fa-sort-numeric-down{--fa: ""}.fa-hand-holding-droplet,.fa-hand-holding-water{--fa: ""}.fa-water{--fa: ""}.fa-calendar-check{--fa: ""}.fa-braille{--fa: ""}.fa-prescription-bottle-medical,.fa-prescription-bottle-alt{--fa: ""}.fa-landmark{--fa: ""}.fa-truck{--fa: ""}.fa-crosshairs{--fa: ""}.fa-person-cane{--fa: ""}.fa-tent{--fa: ""}.fa-vest-patches{--fa: ""}.fa-check-double{--fa: ""}.fa-arrow-down-a-z,.fa-sort-alpha-asc,.fa-sort-alpha-down{--fa: ""}.fa-money-bill-wheat{--fa: ""}.fa-cookie{--fa: ""}.fa-arrow-rotate-left,.fa-arrow-left-rotate,.fa-arrow-rotate-back,.fa-arrow-rotate-backward,.fa-undo{--fa: ""}.fa-hard-drive,.fa-hdd{--fa: ""}.fa-face-grin-squint-tears,.fa-grin-squint-tears{--fa: ""}.fa-dumbbell{--fa: ""}.fa-rectangle-list,.fa-list-alt{--fa: ""}.fa-tarp-droplet{--fa: ""}.fa-house-medical-circle-check{--fa: ""}.fa-person-skiing-nordic,.fa-skiing-nordic{--fa: ""}.fa-calendar-plus{--fa: ""}.fa-plane-arrival{--fa: ""}.fa-circle-left,.fa-arrow-alt-circle-left{--fa: ""}.fa-train-subway,.fa-subway{--fa: ""}.fa-chart-gantt{--fa: ""}.fa-indian-rupee-sign,.fa-indian-rupee,.fa-inr{--fa: ""}.fa-crop-simple,.fa-crop-alt{--fa: ""}.fa-money-bill-1,.fa-money-bill-alt{--fa: ""}.fa-left-long,.fa-long-arrow-alt-left{--fa: ""}.fa-dna{--fa: ""}.fa-virus-slash{--fa: ""}.fa-minus,.fa-subtract{--fa: ""}.fa-chess{--fa: ""}.fa-arrow-left-long,.fa-long-arrow-left{--fa: ""}.fa-plug-circle-check{--fa: ""}.fa-street-view{--fa: ""}.fa-franc-sign{--fa: ""}.fa-volume-off{--fa: ""}.fa-hands-asl-interpreting,.fa-american-sign-language-interpreting,.fa-asl-interpreting,.fa-hands-american-sign-language-interpreting{--fa: ""}.fa-gear,.fa-cog{--fa: ""}.fa-droplet-slash,.fa-tint-slash{--fa: ""}.fa-mosque{--fa: ""}.fa-mosquito{--fa: ""}.fa-star-of-david{--fa: ""}.fa-person-military-rifle{--fa: ""}.fa-cart-shopping,.fa-shopping-cart{--fa: ""}.fa-vials{--fa: ""}.fa-plug-circle-plus{--fa: ""}.fa-place-of-worship{--fa: ""}.fa-grip-vertical{--fa: ""}.fa-hexagon-nodes{--fa: ""}.fa-arrow-turn-up,.fa-level-up{--fa: ""}.fa-u{--fa: "U"}.fa-square-root-variable,.fa-square-root-alt{--fa: ""}.fa-clock,.fa-clock-four{--fa: ""}.fa-backward-step,.fa-step-backward{--fa: ""}.fa-pallet{--fa: ""}.fa-faucet{--fa: ""}.fa-baseball-bat-ball{--fa: ""}.fa-s{--fa: "S"}.fa-timeline{--fa: ""}.fa-keyboard{--fa: ""}.fa-caret-down{--fa: ""}.fa-house-chimney-medical,.fa-clinic-medical{--fa: ""}.fa-temperature-three-quarters,.fa-temperature-3,.fa-thermometer-3,.fa-thermometer-three-quarters{--fa: ""}.fa-mobile-screen,.fa-mobile-android-alt{--fa: ""}.fa-plane-up{--fa: ""}.fa-piggy-bank{--fa: ""}.fa-battery-half,.fa-battery-3{--fa: ""}.fa-mountain-city{--fa: ""}.fa-coins{--fa: ""}.fa-khanda{--fa: ""}.fa-sliders,.fa-sliders-h{--fa: ""}.fa-folder-tree{--fa: ""}.fa-network-wired{--fa: ""}.fa-map-pin{--fa: ""}.fa-hamsa{--fa: ""}.fa-cent-sign{--fa: ""}.fa-flask{--fa: ""}.fa-person-pregnant{--fa: ""}.fa-wand-sparkles{--fa: ""}.fa-ellipsis-vertical,.fa-ellipsis-v{--fa: ""}.fa-ticket{--fa: ""}.fa-power-off{--fa: ""}.fa-right-long,.fa-long-arrow-alt-right{--fa: ""}.fa-flag-usa{--fa: ""}.fa-laptop-file{--fa: ""}.fa-tty,.fa-teletype{--fa: ""}.fa-diagram-next{--fa: ""}.fa-person-rifle{--fa: ""}.fa-house-medical-circle-exclamation{--fa: ""}.fa-closed-captioning{--fa: ""}.fa-person-hiking,.fa-hiking{--fa: ""}.fa-venus-double{--fa: ""}.fa-images{--fa: ""}.fa-calculator{--fa: ""}.fa-people-pulling{--fa: ""}.fa-n{--fa: "N"}.fa-cable-car,.fa-tram{--fa: ""}.fa-cloud-rain{--fa: ""}.fa-building-circle-xmark{--fa: ""}.fa-ship{--fa: ""}.fa-arrows-down-to-line{--fa: ""}.fa-download{--fa: ""}.fa-face-grin,.fa-grin{--fa: ""}.fa-delete-left,.fa-backspace{--fa: ""}.fa-eye-dropper,.fa-eye-dropper-empty,.fa-eyedropper{--fa: ""}.fa-file-circle-check{--fa: ""}.fa-forward{--fa: ""}.fa-mobile,.fa-mobile-android,.fa-mobile-phone{--fa: ""}.fa-face-meh,.fa-meh{--fa: ""}.fa-align-center{--fa: ""}.fa-book-skull,.fa-book-dead{--fa: ""}.fa-id-card,.fa-drivers-license{--fa: ""}.fa-outdent,.fa-dedent{--fa: ""}.fa-heart-circle-exclamation{--fa: ""}.fa-house,.fa-home,.fa-home-alt,.fa-home-lg-alt{--fa: ""}.fa-calendar-week{--fa: ""}.fa-laptop-medical{--fa: ""}.fa-b{--fa: "B"}.fa-file-medical{--fa: ""}.fa-dice-one{--fa: ""}.fa-kiwi-bird{--fa: ""}.fa-arrow-right-arrow-left,.fa-exchange{--fa: ""}.fa-rotate-right,.fa-redo-alt,.fa-rotate-forward{--fa: ""}.fa-utensils,.fa-cutlery{--fa: ""}.fa-arrow-up-wide-short,.fa-sort-amount-up{--fa: ""}.fa-mill-sign{--fa: ""}.fa-bowl-rice{--fa: ""}.fa-skull{--fa: ""}.fa-tower-broadcast,.fa-broadcast-tower{--fa: ""}.fa-truck-pickup{--fa: ""}.fa-up-long,.fa-long-arrow-alt-up{--fa: ""}.fa-stop{--fa: ""}.fa-code-merge{--fa: ""}.fa-upload{--fa: ""}.fa-hurricane{--fa: ""}.fa-mound{--fa: ""}.fa-toilet-portable{--fa: ""}.fa-compact-disc{--fa: ""}.fa-file-arrow-down,.fa-file-download{--fa: ""}.fa-caravan{--fa: ""}.fa-shield-cat{--fa: ""}.fa-bolt,.fa-zap{--fa: ""}.fa-glass-water{--fa: ""}.fa-oil-well{--fa: ""}.fa-vault{--fa: ""}.fa-mars{--fa: ""}.fa-toilet{--fa: ""}.fa-plane-circle-xmark{--fa: ""}.fa-yen-sign,.fa-cny,.fa-jpy,.fa-rmb,.fa-yen{--fa: ""}.fa-ruble-sign,.fa-rouble,.fa-rub,.fa-ruble{--fa: ""}.fa-sun{--fa: ""}.fa-guitar{--fa: ""}.fa-face-laugh-wink,.fa-laugh-wink{--fa: ""}.fa-horse-head{--fa: ""}.fa-bore-hole{--fa: ""}.fa-industry{--fa: ""}.fa-circle-down,.fa-arrow-alt-circle-down{--fa: ""}.fa-arrows-turn-to-dots{--fa: ""}.fa-florin-sign{--fa: ""}.fa-arrow-down-short-wide,.fa-sort-amount-desc,.fa-sort-amount-down-alt{--fa: ""}.fa-less-than{--fa: "<"}.fa-angle-down{--fa: ""}.fa-car-tunnel{--fa: ""}.fa-head-side-cough{--fa: ""}.fa-grip-lines{--fa: ""}.fa-thumbs-down{--fa: ""}.fa-user-lock{--fa: ""}.fa-arrow-right-long,.fa-long-arrow-right{--fa: ""}.fa-anchor-circle-xmark{--fa: ""}.fa-ellipsis,.fa-ellipsis-h{--fa: ""}.fa-chess-pawn{--fa: ""}.fa-kit-medical,.fa-first-aid{--fa: ""}.fa-person-through-window{--fa: ""}.fa-toolbox{--fa: ""}.fa-hands-holding-circle{--fa: ""}.fa-bug{--fa: ""}.fa-credit-card,.fa-credit-card-alt{--fa: ""}.fa-car,.fa-automobile{--fa: ""}.fa-hand-holding-hand{--fa: ""}.fa-book-open-reader,.fa-book-reader{--fa: ""}.fa-mountain-sun{--fa: ""}.fa-arrows-left-right-to-line{--fa: ""}.fa-dice-d20{--fa: ""}.fa-truck-droplet{--fa: ""}.fa-file-circle-xmark{--fa: ""}.fa-temperature-arrow-up,.fa-temperature-up{--fa: ""}.fa-medal{--fa: ""}.fa-bed{--fa: ""}.fa-square-h,.fa-h-square{--fa: ""}.fa-podcast{--fa: ""}.fa-temperature-full,.fa-temperature-4,.fa-thermometer-4,.fa-thermometer-full{--fa: ""}.fa-bell{--fa: ""}.fa-superscript{--fa: ""}.fa-plug-circle-xmark{--fa: ""}.fa-star-of-life{--fa: ""}.fa-phone-slash{--fa: ""}.fa-paint-roller{--fa: ""}.fa-handshake-angle,.fa-hands-helping{--fa: ""}.fa-location-dot,.fa-map-marker-alt{--fa: ""}.fa-file{--fa: ""}.fa-greater-than{--fa: ">"}.fa-person-swimming,.fa-swimmer{--fa: ""}.fa-arrow-down{--fa: ""}.fa-droplet,.fa-tint{--fa: ""}.fa-eraser{--fa: ""}.fa-earth-americas,.fa-earth,.fa-earth-america,.fa-globe-americas{--fa: ""}.fa-person-burst{--fa: ""}.fa-dove{--fa: ""}.fa-battery-empty,.fa-battery-0{--fa: ""}.fa-socks{--fa: ""}.fa-inbox{--fa: ""}.fa-section{--fa: ""}.fa-gauge-high,.fa-tachometer-alt,.fa-tachometer-alt-fast{--fa: ""}.fa-envelope-open-text{--fa: ""}.fa-hospital,.fa-hospital-alt,.fa-hospital-wide{--fa: ""}.fa-wine-bottle{--fa: ""}.fa-chess-rook{--fa: ""}.fa-bars-staggered,.fa-reorder,.fa-stream{--fa: ""}.fa-dharmachakra{--fa: ""}.fa-hotdog{--fa: ""}.fa-person-walking-with-cane,.fa-blind{--fa: ""}.fa-drum{--fa: ""}.fa-ice-cream{--fa: ""}.fa-heart-circle-bolt{--fa: ""}.fa-fax{--fa: ""}.fa-paragraph{--fa: ""}.fa-check-to-slot,.fa-vote-yea{--fa: ""}.fa-star-half{--fa: ""}.fa-boxes-stacked,.fa-boxes,.fa-boxes-alt{--fa: ""}.fa-link,.fa-chain{--fa: ""}.fa-ear-listen,.fa-assistive-listening-systems{--fa: ""}.fa-tree-city{--fa: ""}.fa-play{--fa: ""}.fa-font{--fa: ""}.fa-table-cells-row-lock{--fa: ""}.fa-rupiah-sign{--fa: ""}.fa-magnifying-glass,.fa-search{--fa: ""}.fa-table-tennis-paddle-ball,.fa-ping-pong-paddle-ball,.fa-table-tennis{--fa: ""}.fa-person-dots-from-line,.fa-diagnoses{--fa: ""}.fa-trash-can-arrow-up,.fa-trash-restore-alt{--fa: ""}.fa-naira-sign{--fa: ""}.fa-cart-arrow-down{--fa: ""}.fa-walkie-talkie{--fa: ""}.fa-file-pen,.fa-file-edit{--fa: ""}.fa-receipt{--fa: ""}.fa-square-pen,.fa-pen-square,.fa-pencil-square{--fa: ""}.fa-suitcase-rolling{--fa: ""}.fa-person-circle-exclamation{--fa: ""}.fa-chevron-down{--fa: ""}.fa-battery-full,.fa-battery,.fa-battery-5{--fa: ""}.fa-skull-crossbones{--fa: ""}.fa-code-compare{--fa: ""}.fa-list-ul,.fa-list-dots{--fa: ""}.fa-school-lock{--fa: ""}.fa-tower-cell{--fa: ""}.fa-down-long,.fa-long-arrow-alt-down{--fa: ""}.fa-ranking-star{--fa: ""}.fa-chess-king{--fa: ""}.fa-person-harassing{--fa: ""}.fa-brazilian-real-sign{--fa: ""}.fa-landmark-dome,.fa-landmark-alt{--fa: ""}.fa-arrow-up{--fa: ""}.fa-tv,.fa-television,.fa-tv-alt{--fa: ""}.fa-shrimp{--fa: ""}.fa-list-check,.fa-tasks{--fa: ""}.fa-jug-detergent{--fa: ""}.fa-circle-user,.fa-user-circle{--fa: ""}.fa-user-shield{--fa: ""}.fa-wind{--fa: ""}.fa-car-burst,.fa-car-crash{--fa: ""}.fa-y{--fa: "Y"}.fa-person-snowboarding,.fa-snowboarding{--fa: ""}.fa-truck-fast,.fa-shipping-fast{--fa: ""}.fa-fish{--fa: ""}.fa-user-graduate{--fa: ""}.fa-circle-half-stroke,.fa-adjust{--fa: ""}.fa-clapperboard{--fa: ""}.fa-circle-radiation,.fa-radiation-alt{--fa: ""}.fa-baseball,.fa-baseball-ball{--fa: ""}.fa-jet-fighter-up{--fa: ""}.fa-diagram-project,.fa-project-diagram{--fa: ""}.fa-copy{--fa: ""}.fa-volume-xmark,.fa-volume-mute,.fa-volume-times{--fa: ""}.fa-hand-sparkles{--fa: ""}.fa-grip,.fa-grip-horizontal{--fa: ""}.fa-share-from-square,.fa-share-square{--fa: ""}.fa-child-combatant,.fa-child-rifle{--fa: ""}.fa-gun{--fa: ""}.fa-square-phone,.fa-phone-square{--fa: ""}.fa-plus,.fa-add{--fa: "+"}.fa-expand{--fa: ""}.fa-computer{--fa: ""}.fa-xmark,.fa-close,.fa-multiply,.fa-remove,.fa-times{--fa: ""}.fa-arrows-up-down-left-right,.fa-arrows{--fa: ""}.fa-chalkboard-user,.fa-chalkboard-teacher{--fa: ""}.fa-peso-sign{--fa: ""}.fa-building-shield{--fa: ""}.fa-baby{--fa: ""}.fa-users-line{--fa: ""}.fa-quote-left,.fa-quote-left-alt{--fa: ""}.fa-tractor{--fa: ""}.fa-trash-arrow-up,.fa-trash-restore{--fa: ""}.fa-arrow-down-up-lock{--fa: ""}.fa-lines-leaning{--fa: ""}.fa-ruler-combined{--fa: ""}.fa-copyright{--fa: ""}.fa-equals{--fa: "="}.fa-blender{--fa: ""}.fa-teeth{--fa: ""}.fa-shekel-sign,.fa-ils,.fa-shekel,.fa-sheqel,.fa-sheqel-sign{--fa: ""}.fa-map{--fa: ""}.fa-rocket{--fa: ""}.fa-photo-film,.fa-photo-video{--fa: ""}.fa-folder-minus{--fa: ""}.fa-hexagon-nodes-bolt{--fa: ""}.fa-store{--fa: ""}.fa-arrow-trend-up{--fa: ""}.fa-plug-circle-minus{--fa: ""}.fa-sign-hanging,.fa-sign{--fa: ""}.fa-bezier-curve{--fa: ""}.fa-bell-slash{--fa: ""}.fa-tablet,.fa-tablet-android{--fa: ""}.fa-school-flag{--fa: ""}.fa-fill{--fa: ""}.fa-angle-up{--fa: ""}.fa-drumstick-bite{--fa: ""}.fa-holly-berry{--fa: ""}.fa-chevron-left{--fa: ""}.fa-bacteria{--fa: ""}.fa-hand-lizard{--fa: ""}.fa-notdef{--fa: ""}.fa-disease{--fa: ""}.fa-briefcase-medical{--fa: ""}.fa-genderless{--fa: ""}.fa-chevron-right{--fa: ""}.fa-retweet{--fa: ""}.fa-car-rear,.fa-car-alt{--fa: ""}.fa-pump-soap{--fa: ""}.fa-video-slash{--fa: ""}.fa-battery-quarter,.fa-battery-2{--fa: ""}.fa-radio{--fa: ""}.fa-baby-carriage,.fa-carriage-baby{--fa: ""}.fa-traffic-light{--fa: ""}.fa-thermometer{--fa: ""}.fa-vr-cardboard{--fa: ""}.fa-hand-middle-finger{--fa: ""}.fa-percent,.fa-percentage{--fa: "%"}.fa-truck-moving{--fa: ""}.fa-glass-water-droplet{--fa: ""}.fa-display{--fa: ""}.fa-face-smile,.fa-smile{--fa: ""}.fa-thumbtack,.fa-thumb-tack{--fa: ""}.fa-trophy{--fa: ""}.fa-person-praying,.fa-pray{--fa: ""}.fa-hammer{--fa: ""}.fa-hand-peace{--fa: ""}.fa-rotate,.fa-sync-alt{--fa: ""}.fa-spinner{--fa: ""}.fa-robot{--fa: ""}.fa-peace{--fa: ""}.fa-gears,.fa-cogs{--fa: ""}.fa-warehouse{--fa: ""}.fa-arrow-up-right-dots{--fa: ""}.fa-splotch{--fa: ""}.fa-face-grin-hearts,.fa-grin-hearts{--fa: ""}.fa-dice-four{--fa: ""}.fa-sim-card{--fa: ""}.fa-transgender,.fa-transgender-alt{--fa: ""}.fa-mercury{--fa: ""}.fa-arrow-turn-down,.fa-level-down{--fa: ""}.fa-person-falling-burst{--fa: ""}.fa-award{--fa: ""}.fa-ticket-simple,.fa-ticket-alt{--fa: ""}.fa-building{--fa: ""}.fa-angles-left,.fa-angle-double-left{--fa: ""}.fa-qrcode{--fa: ""}.fa-clock-rotate-left,.fa-history{--fa: ""}.fa-face-grin-beam-sweat,.fa-grin-beam-sweat{--fa: ""}.fa-file-export,.fa-arrow-right-from-file{--fa: ""}.fa-shield,.fa-shield-blank{--fa: ""}.fa-arrow-up-short-wide,.fa-sort-amount-up-alt{--fa: ""}.fa-comment-nodes{--fa: ""}.fa-house-medical{--fa: ""}.fa-golf-ball-tee,.fa-golf-ball{--fa: ""}.fa-circle-chevron-left,.fa-chevron-circle-left{--fa: ""}.fa-house-chimney-window{--fa: ""}.fa-pen-nib{--fa: ""}.fa-tent-arrow-turn-left{--fa: ""}.fa-tents{--fa: ""}.fa-wand-magic,.fa-magic{--fa: ""}.fa-dog{--fa: ""}.fa-carrot{--fa: ""}.fa-moon{--fa: ""}.fa-wine-glass-empty,.fa-wine-glass-alt{--fa: ""}.fa-cheese{--fa: ""}.fa-yin-yang{--fa: ""}.fa-music{--fa: ""}.fa-code-commit{--fa: ""}.fa-temperature-low{--fa: ""}.fa-person-biking,.fa-biking{--fa: ""}.fa-broom{--fa: ""}.fa-shield-heart{--fa: ""}.fa-gopuram{--fa: ""}.fa-earth-oceania,.fa-globe-oceania{--fa: ""}.fa-square-xmark,.fa-times-square,.fa-xmark-square{--fa: ""}.fa-hashtag{--fa: "#"}.fa-up-right-and-down-left-from-center,.fa-expand-alt{--fa: ""}.fa-oil-can{--fa: ""}.fa-t{--fa: "T"}.fa-hippo{--fa: ""}.fa-chart-column{--fa: ""}.fa-infinity{--fa: ""}.fa-vial-circle-check{--fa: ""}.fa-person-arrow-down-to-line{--fa: ""}.fa-voicemail{--fa: ""}.fa-fan{--fa: ""}.fa-person-walking-luggage{--fa: ""}.fa-up-down,.fa-arrows-alt-v{--fa: ""}.fa-cloud-moon-rain{--fa: ""}.fa-calendar{--fa: ""}.fa-trailer{--fa: ""}.fa-bahai,.fa-haykal{--fa: ""}.fa-sd-card{--fa: ""}.fa-dragon{--fa: ""}.fa-shoe-prints{--fa: ""}.fa-circle-plus,.fa-plus-circle{--fa: ""}.fa-face-grin-tongue-wink,.fa-grin-tongue-wink{--fa: ""}.fa-hand-holding{--fa: ""}.fa-plug-circle-exclamation{--fa: ""}.fa-link-slash,.fa-chain-broken,.fa-chain-slash,.fa-unlink{--fa: ""}.fa-clone{--fa: ""}.fa-person-walking-arrow-loop-left{--fa: ""}.fa-arrow-up-z-a,.fa-sort-alpha-up-alt{--fa: ""}.fa-fire-flame-curved,.fa-fire-alt{--fa: ""}.fa-tornado{--fa: ""}.fa-file-circle-plus{--fa: ""}.fa-book-quran,.fa-quran{--fa: ""}.fa-anchor{--fa: ""}.fa-border-all{--fa: ""}.fa-face-angry,.fa-angry{--fa: ""}.fa-cookie-bite{--fa: ""}.fa-arrow-trend-down{--fa: ""}.fa-rss,.fa-feed{--fa: ""}.fa-draw-polygon{--fa: ""}.fa-scale-balanced,.fa-balance-scale{--fa: ""}.fa-gauge-simple-high,.fa-tachometer,.fa-tachometer-fast{--fa: ""}.fa-shower{--fa: ""}.fa-desktop,.fa-desktop-alt{--fa: ""}.fa-m{--fa: "M"}.fa-table-list,.fa-th-list{--fa: ""}.fa-comment-sms,.fa-sms{--fa: ""}.fa-book{--fa: ""}.fa-user-plus{--fa: ""}.fa-check{--fa: ""}.fa-battery-three-quarters,.fa-battery-4{--fa: ""}.fa-house-circle-check{--fa: ""}.fa-angle-left{--fa: ""}.fa-diagram-successor{--fa: ""}.fa-truck-arrow-right{--fa: ""}.fa-arrows-split-up-and-left{--fa: ""}.fa-hand-fist,.fa-fist-raised{--fa: ""}.fa-cloud-moon{--fa: ""}.fa-briefcase{--fa: ""}.fa-person-falling{--fa: ""}.fa-image-portrait,.fa-portrait{--fa: ""}.fa-user-tag{--fa: ""}.fa-rug{--fa: ""}.fa-earth-europe,.fa-globe-europe{--fa: ""}.fa-cart-flatbed-suitcase,.fa-luggage-cart{--fa: ""}.fa-rectangle-xmark,.fa-rectangle-times,.fa-times-rectangle,.fa-window-close{--fa: ""}.fa-baht-sign{--fa: ""}.fa-book-open{--fa: ""}.fa-book-journal-whills,.fa-journal-whills{--fa: ""}.fa-handcuffs{--fa: ""}.fa-triangle-exclamation,.fa-exclamation-triangle,.fa-warning{--fa: ""}.fa-database{--fa: ""}.fa-share,.fa-mail-forward{--fa: ""}.fa-bottle-droplet{--fa: ""}.fa-mask-face{--fa: ""}.fa-hill-rockslide{--fa: ""}.fa-right-left,.fa-exchange-alt{--fa: ""}.fa-paper-plane{--fa: ""}.fa-road-circle-exclamation{--fa: ""}.fa-dungeon{--fa: ""}.fa-align-right{--fa: ""}.fa-money-bill-1-wave,.fa-money-bill-wave-alt{--fa: ""}.fa-life-ring{--fa: ""}.fa-hands,.fa-sign-language,.fa-signing{--fa: ""}.fa-calendar-day{--fa: ""}.fa-water-ladder,.fa-ladder-water,.fa-swimming-pool{--fa: ""}.fa-arrows-up-down,.fa-arrows-v{--fa: ""}.fa-face-grimace,.fa-grimace{--fa: ""}.fa-wheelchair-move,.fa-wheelchair-alt{--fa: ""}.fa-turn-down,.fa-level-down-alt{--fa: ""}.fa-person-walking-arrow-right{--fa: ""}.fa-square-envelope,.fa-envelope-square{--fa: ""}.fa-dice{--fa: ""}.fa-bowling-ball{--fa: ""}.fa-brain{--fa: ""}.fa-bandage,.fa-band-aid{--fa: ""}.fa-calendar-minus{--fa: ""}.fa-circle-xmark,.fa-times-circle,.fa-xmark-circle{--fa: ""}.fa-gifts{--fa: ""}.fa-hotel{--fa: ""}.fa-earth-asia,.fa-globe-asia{--fa: ""}.fa-id-card-clip,.fa-id-card-alt{--fa: ""}.fa-magnifying-glass-plus,.fa-search-plus{--fa: ""}.fa-thumbs-up{--fa: ""}.fa-user-clock{--fa: ""}.fa-hand-dots,.fa-allergies{--fa: ""}.fa-file-invoice{--fa: ""}.fa-window-minimize{--fa: ""}.fa-mug-saucer,.fa-coffee{--fa: ""}.fa-brush{--fa: ""}.fa-file-half-dashed{--fa: ""}.fa-mask{--fa: ""}.fa-magnifying-glass-minus,.fa-search-minus{--fa: ""}.fa-ruler-vertical{--fa: ""}.fa-user-large,.fa-user-alt{--fa: ""}.fa-train-tram{--fa: ""}.fa-user-nurse{--fa: ""}.fa-syringe{--fa: ""}.fa-cloud-sun{--fa: ""}.fa-stopwatch-20{--fa: ""}.fa-square-full{--fa: ""}.fa-magnet{--fa: ""}.fa-jar{--fa: ""}.fa-note-sticky,.fa-sticky-note{--fa: ""}.fa-bug-slash{--fa: ""}.fa-arrow-up-from-water-pump{--fa: ""}.fa-bone{--fa: ""}.fa-table-cells-row-unlock{--fa: ""}.fa-user-injured{--fa: ""}.fa-face-sad-tear,.fa-sad-tear{--fa: ""}.fa-plane{--fa: ""}.fa-tent-arrows-down{--fa: ""}.fa-exclamation{--fa: "!"}.fa-arrows-spin{--fa: ""}.fa-print{--fa: ""}.fa-turkish-lira-sign,.fa-try,.fa-turkish-lira{--fa: ""}.fa-dollar-sign,.fa-dollar,.fa-usd{--fa: "$"}.fa-x{--fa: "X"}.fa-magnifying-glass-dollar,.fa-search-dollar{--fa: ""}.fa-users-gear,.fa-users-cog{--fa: ""}.fa-person-military-pointing{--fa: ""}.fa-building-columns,.fa-bank,.fa-institution,.fa-museum,.fa-university{--fa: ""}.fa-umbrella{--fa: ""}.fa-trowel{--fa: ""}.fa-d{--fa: "D"}.fa-stapler{--fa: ""}.fa-masks-theater,.fa-theater-masks{--fa: ""}.fa-kip-sign{--fa: ""}.fa-hand-point-left{--fa: ""}.fa-handshake-simple,.fa-handshake-alt{--fa: ""}.fa-jet-fighter,.fa-fighter-jet{--fa: ""}.fa-square-share-nodes,.fa-share-alt-square{--fa: ""}.fa-barcode{--fa: ""}.fa-plus-minus{--fa: ""}.fa-video,.fa-video-camera{--fa: ""}.fa-graduation-cap,.fa-mortar-board{--fa: ""}.fa-hand-holding-medical{--fa: ""}.fa-person-circle-check{--fa: ""}.fa-turn-up,.fa-level-up-alt{--fa: ""}.sr-only,.fa-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.sr-only-focusable:not(:focus),.fa-sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:root,:host{--fa-style-family-brands: "Font Awesome 6 Brands";--fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(/admin-next/assets/fa-brands-400-D_cYUPeE.woff2) format("woff2"),url(/admin-next/assets/fa-brands-400-D1LuMI3I.ttf) format("truetype")}.fab,.fa-brands{font-weight:400}.fa-monero{--fa: ""}.fa-hooli{--fa: ""}.fa-yelp{--fa: ""}.fa-cc-visa{--fa: ""}.fa-lastfm{--fa: ""}.fa-shopware{--fa: ""}.fa-creative-commons-nc{--fa: ""}.fa-aws{--fa: ""}.fa-redhat{--fa: ""}.fa-yoast{--fa: ""}.fa-cloudflare{--fa: ""}.fa-ups{--fa: ""}.fa-pixiv{--fa: ""}.fa-wpexplorer{--fa: ""}.fa-dyalog{--fa: ""}.fa-bity{--fa: ""}.fa-stackpath{--fa: ""}.fa-buysellads{--fa: ""}.fa-first-order{--fa: ""}.fa-modx{--fa: ""}.fa-guilded{--fa: ""}.fa-vnv{--fa: ""}.fa-square-js,.fa-js-square{--fa: ""}.fa-microsoft{--fa: ""}.fa-qq{--fa: ""}.fa-orcid{--fa: ""}.fa-java{--fa: ""}.fa-invision{--fa: ""}.fa-creative-commons-pd-alt{--fa: ""}.fa-centercode{--fa: ""}.fa-glide-g{--fa: ""}.fa-drupal{--fa: ""}.fa-jxl{--fa: ""}.fa-dart-lang{--fa: ""}.fa-hire-a-helper{--fa: ""}.fa-creative-commons-by{--fa: ""}.fa-unity{--fa: ""}.fa-whmcs{--fa: ""}.fa-rocketchat{--fa: ""}.fa-vk{--fa: ""}.fa-untappd{--fa: ""}.fa-mailchimp{--fa: ""}.fa-css3-alt{--fa: ""}.fa-square-reddit,.fa-reddit-square{--fa: ""}.fa-vimeo-v{--fa: ""}.fa-contao{--fa: ""}.fa-square-font-awesome{--fa: ""}.fa-deskpro{--fa: ""}.fa-brave{--fa: ""}.fa-sistrix{--fa: ""}.fa-square-instagram,.fa-instagram-square{--fa: ""}.fa-battle-net{--fa: ""}.fa-the-red-yeti{--fa: ""}.fa-square-hacker-news,.fa-hacker-news-square{--fa: ""}.fa-edge{--fa: ""}.fa-threads{--fa: ""}.fa-napster{--fa: ""}.fa-square-snapchat,.fa-snapchat-square{--fa: ""}.fa-google-plus-g{--fa: ""}.fa-artstation{--fa: ""}.fa-markdown{--fa: ""}.fa-sourcetree{--fa: ""}.fa-google-plus{--fa: ""}.fa-diaspora{--fa: ""}.fa-foursquare{--fa: ""}.fa-stack-overflow{--fa: ""}.fa-github-alt{--fa: ""}.fa-phoenix-squadron{--fa: ""}.fa-pagelines{--fa: ""}.fa-algolia{--fa: ""}.fa-red-river{--fa: ""}.fa-creative-commons-sa{--fa: ""}.fa-safari{--fa: ""}.fa-google{--fa: ""}.fa-square-font-awesome-stroke,.fa-font-awesome-alt{--fa: ""}.fa-atlassian{--fa: ""}.fa-linkedin-in{--fa: ""}.fa-digital-ocean{--fa: ""}.fa-nimblr{--fa: ""}.fa-chromecast{--fa: ""}.fa-evernote{--fa: ""}.fa-hacker-news{--fa: ""}.fa-creative-commons-sampling{--fa: ""}.fa-adversal{--fa: ""}.fa-creative-commons{--fa: ""}.fa-watchman-monitoring{--fa: ""}.fa-fonticons{--fa: ""}.fa-weixin{--fa: ""}.fa-shirtsinbulk{--fa: ""}.fa-codepen{--fa: ""}.fa-git-alt{--fa: ""}.fa-lyft{--fa: ""}.fa-rev{--fa: ""}.fa-windows{--fa: ""}.fa-wizards-of-the-coast{--fa: ""}.fa-square-viadeo,.fa-viadeo-square{--fa: ""}.fa-meetup{--fa: ""}.fa-centos{--fa: ""}.fa-adn{--fa: ""}.fa-cloudsmith{--fa: ""}.fa-opensuse{--fa: ""}.fa-pied-piper-alt{--fa: ""}.fa-square-dribbble,.fa-dribbble-square{--fa: ""}.fa-codiepie{--fa: ""}.fa-node{--fa: ""}.fa-mix{--fa: ""}.fa-steam{--fa: ""}.fa-cc-apple-pay{--fa: ""}.fa-scribd{--fa: ""}.fa-debian{--fa: ""}.fa-openid{--fa: ""}.fa-instalod{--fa: ""}.fa-files-pinwheel{--fa: ""}.fa-expeditedssl{--fa: ""}.fa-sellcast{--fa: ""}.fa-square-twitter,.fa-twitter-square{--fa: ""}.fa-r-project{--fa: ""}.fa-delicious{--fa: ""}.fa-freebsd{--fa: ""}.fa-vuejs{--fa: ""}.fa-accusoft{--fa: ""}.fa-ioxhost{--fa: ""}.fa-fonticons-fi{--fa: ""}.fa-app-store{--fa: ""}.fa-cc-mastercard{--fa: ""}.fa-itunes-note{--fa: ""}.fa-golang{--fa: ""}.fa-kickstarter,.fa-square-kickstarter{--fa: ""}.fa-grav{--fa: ""}.fa-weibo{--fa: ""}.fa-uncharted{--fa: ""}.fa-firstdraft{--fa: ""}.fa-square-youtube,.fa-youtube-square{--fa: ""}.fa-wikipedia-w{--fa: ""}.fa-wpressr,.fa-rendact{--fa: ""}.fa-angellist{--fa: ""}.fa-galactic-republic{--fa: ""}.fa-nfc-directional{--fa: ""}.fa-skype{--fa: ""}.fa-joget{--fa: ""}.fa-fedora{--fa: ""}.fa-stripe-s{--fa: ""}.fa-meta{--fa: ""}.fa-laravel{--fa: ""}.fa-hotjar{--fa: ""}.fa-bluetooth-b{--fa: ""}.fa-square-letterboxd{--fa: ""}.fa-sticker-mule{--fa: ""}.fa-creative-commons-zero{--fa: ""}.fa-hips{--fa: ""}.fa-css{--fa: ""}.fa-behance{--fa: ""}.fa-reddit{--fa: ""}.fa-discord{--fa: ""}.fa-chrome{--fa: ""}.fa-app-store-ios{--fa: ""}.fa-cc-discover{--fa: ""}.fa-wpbeginner{--fa: ""}.fa-confluence{--fa: ""}.fa-shoelace{--fa: ""}.fa-mdb{--fa: ""}.fa-dochub{--fa: ""}.fa-accessible-icon{--fa: ""}.fa-ebay{--fa: ""}.fa-amazon{--fa: ""}.fa-unsplash{--fa: ""}.fa-yarn{--fa: ""}.fa-square-steam,.fa-steam-square{--fa: ""}.fa-500px{--fa: ""}.fa-square-vimeo,.fa-vimeo-square{--fa: ""}.fa-asymmetrik{--fa: ""}.fa-font-awesome,.fa-font-awesome-flag,.fa-font-awesome-logo-full{--fa: ""}.fa-gratipay{--fa: ""}.fa-apple{--fa: ""}.fa-hive{--fa: ""}.fa-gitkraken{--fa: ""}.fa-keybase{--fa: ""}.fa-apple-pay{--fa: ""}.fa-padlet{--fa: ""}.fa-amazon-pay{--fa: ""}.fa-square-github,.fa-github-square{--fa: ""}.fa-stumbleupon{--fa: ""}.fa-fedex{--fa: ""}.fa-phoenix-framework{--fa: ""}.fa-shopify{--fa: ""}.fa-neos{--fa: ""}.fa-square-threads{--fa: ""}.fa-hackerrank{--fa: ""}.fa-researchgate{--fa: ""}.fa-swift{--fa: ""}.fa-angular{--fa: ""}.fa-speakap{--fa: ""}.fa-angrycreative{--fa: ""}.fa-y-combinator{--fa: ""}.fa-empire{--fa: ""}.fa-envira{--fa: ""}.fa-google-scholar{--fa: ""}.fa-square-gitlab,.fa-gitlab-square{--fa: ""}.fa-studiovinari{--fa: ""}.fa-pied-piper{--fa: ""}.fa-wordpress{--fa: ""}.fa-product-hunt{--fa: ""}.fa-firefox{--fa: ""}.fa-linode{--fa: ""}.fa-goodreads{--fa: ""}.fa-square-odnoklassniki,.fa-odnoklassniki-square{--fa: ""}.fa-jsfiddle{--fa: ""}.fa-sith{--fa: ""}.fa-themeisle{--fa: ""}.fa-page4{--fa: ""}.fa-hashnode{--fa: ""}.fa-react{--fa: ""}.fa-cc-paypal{--fa: ""}.fa-squarespace{--fa: ""}.fa-cc-stripe{--fa: ""}.fa-creative-commons-share{--fa: ""}.fa-bitcoin{--fa: ""}.fa-keycdn{--fa: ""}.fa-opera{--fa: ""}.fa-itch-io{--fa: ""}.fa-umbraco{--fa: ""}.fa-galactic-senate{--fa: ""}.fa-ubuntu{--fa: ""}.fa-draft2digital{--fa: ""}.fa-stripe{--fa: ""}.fa-houzz{--fa: ""}.fa-gg{--fa: ""}.fa-dhl{--fa: ""}.fa-square-pinterest,.fa-pinterest-square{--fa: ""}.fa-xing{--fa: ""}.fa-blackberry{--fa: ""}.fa-creative-commons-pd{--fa: ""}.fa-playstation{--fa: ""}.fa-quinscape{--fa: ""}.fa-less{--fa: ""}.fa-blogger-b{--fa: ""}.fa-opencart{--fa: ""}.fa-vine{--fa: ""}.fa-signal-messenger{--fa: ""}.fa-paypal{--fa: ""}.fa-gitlab{--fa: ""}.fa-typo3{--fa: ""}.fa-reddit-alien{--fa: ""}.fa-yahoo{--fa: ""}.fa-dailymotion{--fa: ""}.fa-affiliatetheme{--fa: ""}.fa-pied-piper-pp{--fa: ""}.fa-bootstrap{--fa: ""}.fa-odnoklassniki{--fa: ""}.fa-nfc-symbol{--fa: ""}.fa-mintbit{--fa: ""}.fa-ethereum{--fa: ""}.fa-speaker-deck{--fa: ""}.fa-creative-commons-nc-eu{--fa: ""}.fa-patreon{--fa: ""}.fa-avianex{--fa: ""}.fa-ello{--fa: ""}.fa-gofore{--fa: ""}.fa-bimobject{--fa: ""}.fa-brave-reverse{--fa: ""}.fa-facebook-f{--fa: ""}.fa-square-google-plus,.fa-google-plus-square{--fa: ""}.fa-web-awesome{--fa: ""}.fa-mandalorian{--fa: ""}.fa-first-order-alt{--fa: ""}.fa-osi{--fa: ""}.fa-google-wallet{--fa: ""}.fa-d-and-d-beyond{--fa: ""}.fa-periscope{--fa: ""}.fa-fulcrum{--fa: ""}.fa-cloudscale{--fa: ""}.fa-forumbee{--fa: ""}.fa-mizuni{--fa: ""}.fa-schlix{--fa: ""}.fa-square-xing,.fa-xing-square{--fa: ""}.fa-bandcamp{--fa: ""}.fa-wpforms{--fa: ""}.fa-cloudversify{--fa: ""}.fa-usps{--fa: ""}.fa-megaport{--fa: ""}.fa-magento{--fa: ""}.fa-spotify{--fa: ""}.fa-optin-monster{--fa: ""}.fa-fly{--fa: ""}.fa-square-bluesky{--fa: ""}.fa-aviato{--fa: ""}.fa-itunes{--fa: ""}.fa-cuttlefish{--fa: ""}.fa-blogger{--fa: ""}.fa-flickr{--fa: ""}.fa-viber{--fa: ""}.fa-soundcloud{--fa: ""}.fa-digg{--fa: ""}.fa-tencent-weibo{--fa: ""}.fa-letterboxd{--fa: ""}.fa-symfony{--fa: ""}.fa-maxcdn{--fa: ""}.fa-etsy{--fa: ""}.fa-facebook-messenger{--fa: ""}.fa-audible{--fa: ""}.fa-think-peaks{--fa: ""}.fa-bilibili{--fa: ""}.fa-erlang{--fa: ""}.fa-x-twitter{--fa: ""}.fa-cotton-bureau{--fa: ""}.fa-dashcube{--fa: ""}.fa-42-group,.fa-innosoft{--fa: ""}.fa-stack-exchange{--fa: ""}.fa-elementor{--fa: ""}.fa-square-pied-piper,.fa-pied-piper-square{--fa: ""}.fa-creative-commons-nd{--fa: ""}.fa-palfed{--fa: ""}.fa-superpowers{--fa: ""}.fa-resolving{--fa: ""}.fa-xbox{--fa: ""}.fa-square-web-awesome-stroke{--fa: ""}.fa-searchengin{--fa: ""}.fa-tiktok{--fa: ""}.fa-square-facebook,.fa-facebook-square{--fa: ""}.fa-renren{--fa: ""}.fa-linux{--fa: ""}.fa-glide{--fa: ""}.fa-linkedin{--fa: ""}.fa-hubspot{--fa: ""}.fa-deploydog{--fa: ""}.fa-twitch{--fa: ""}.fa-flutter{--fa: ""}.fa-ravelry{--fa: ""}.fa-mixer{--fa: ""}.fa-square-lastfm,.fa-lastfm-square{--fa: ""}.fa-vimeo{--fa: ""}.fa-mendeley{--fa: ""}.fa-uniregistry{--fa: ""}.fa-figma{--fa: ""}.fa-creative-commons-remix{--fa: ""}.fa-cc-amazon-pay{--fa: ""}.fa-dropbox{--fa: ""}.fa-instagram{--fa: ""}.fa-cmplid{--fa: ""}.fa-upwork{--fa: ""}.fa-facebook{--fa: ""}.fa-gripfire{--fa: ""}.fa-jedi-order{--fa: ""}.fa-uikit{--fa: ""}.fa-fort-awesome-alt{--fa: ""}.fa-phabricator{--fa: ""}.fa-ussunnah{--fa: ""}.fa-earlybirds{--fa: ""}.fa-trade-federation{--fa: ""}.fa-autoprefixer{--fa: ""}.fa-whatsapp{--fa: ""}.fa-square-upwork{--fa: ""}.fa-slideshare{--fa: ""}.fa-google-play{--fa: ""}.fa-viadeo{--fa: ""}.fa-line{--fa: ""}.fa-google-drive{--fa: ""}.fa-servicestack{--fa: ""}.fa-simplybuilt{--fa: ""}.fa-bitbucket{--fa: ""}.fa-imdb{--fa: ""}.fa-deezer{--fa: ""}.fa-raspberry-pi{--fa: ""}.fa-jira{--fa: ""}.fa-docker{--fa: ""}.fa-screenpal{--fa: ""}.fa-bluetooth{--fa: ""}.fa-gitter{--fa: ""}.fa-d-and-d{--fa: ""}.fa-microblog{--fa: ""}.fa-cc-diners-club{--fa: ""}.fa-gg-circle{--fa: ""}.fa-pied-piper-hat{--fa: ""}.fa-kickstarter-k{--fa: ""}.fa-yandex{--fa: ""}.fa-readme{--fa: ""}.fa-html5{--fa: ""}.fa-sellsy{--fa: ""}.fa-square-web-awesome{--fa: ""}.fa-sass{--fa: ""}.fa-wirsindhandwerk,.fa-wsh{--fa: ""}.fa-buromobelexperte{--fa: ""}.fa-salesforce{--fa: ""}.fa-octopus-deploy{--fa: ""}.fa-medapps{--fa: ""}.fa-ns8{--fa: ""}.fa-pinterest-p{--fa: ""}.fa-apper{--fa: ""}.fa-fort-awesome{--fa: ""}.fa-waze{--fa: ""}.fa-bluesky{--fa: ""}.fa-cc-jcb{--fa: ""}.fa-snapchat,.fa-snapchat-ghost{--fa: ""}.fa-fantasy-flight-games{--fa: ""}.fa-rust{--fa: ""}.fa-wix{--fa: ""}.fa-square-behance,.fa-behance-square{--fa: ""}.fa-supple{--fa: ""}.fa-webflow{--fa: ""}.fa-rebel{--fa: ""}.fa-css3{--fa: ""}.fa-staylinked{--fa: ""}.fa-kaggle{--fa: ""}.fa-space-awesome{--fa: ""}.fa-deviantart{--fa: ""}.fa-cpanel{--fa: ""}.fa-goodreads-g{--fa: ""}.fa-square-git,.fa-git-square{--fa: ""}.fa-square-tumblr,.fa-tumblr-square{--fa: ""}.fa-trello{--fa: ""}.fa-creative-commons-nc-jp{--fa: ""}.fa-get-pocket{--fa: ""}.fa-perbyte{--fa: ""}.fa-grunt{--fa: ""}.fa-weebly{--fa: ""}.fa-connectdevelop{--fa: ""}.fa-leanpub{--fa: ""}.fa-black-tie{--fa: ""}.fa-themeco{--fa: ""}.fa-python{--fa: ""}.fa-android{--fa: ""}.fa-bots{--fa: ""}.fa-free-code-camp{--fa: ""}.fa-hornbill{--fa: ""}.fa-js{--fa: ""}.fa-ideal{--fa: ""}.fa-git{--fa: ""}.fa-dev{--fa: ""}.fa-sketch{--fa: ""}.fa-yandex-international{--fa: ""}.fa-cc-amex{--fa: ""}.fa-uber{--fa: ""}.fa-github{--fa: ""}.fa-php{--fa: ""}.fa-alipay{--fa: ""}.fa-youtube{--fa: ""}.fa-skyatlas{--fa: ""}.fa-firefox-browser{--fa: ""}.fa-replyd{--fa: ""}.fa-suse{--fa: ""}.fa-jenkins{--fa: ""}.fa-twitter{--fa: ""}.fa-rockrms{--fa: ""}.fa-pinterest{--fa: ""}.fa-buffer{--fa: ""}.fa-npm{--fa: ""}.fa-yammer{--fa: ""}.fa-btc{--fa: ""}.fa-dribbble{--fa: ""}.fa-stumbleupon-circle{--fa: ""}.fa-internet-explorer{--fa: ""}.fa-stubber{--fa: ""}.fa-telegram,.fa-telegram-plane{--fa: ""}.fa-old-republic{--fa: ""}.fa-odysee{--fa: ""}.fa-square-whatsapp,.fa-whatsapp-square{--fa: ""}.fa-node-js{--fa: ""}.fa-edge-legacy{--fa: ""}.fa-slack,.fa-slack-hash{--fa: ""}.fa-medrt{--fa: ""}.fa-usb{--fa: ""}.fa-tumblr{--fa: ""}.fa-vaadin{--fa: ""}.fa-quora{--fa: ""}.fa-square-x-twitter{--fa: ""}.fa-reacteurope{--fa: ""}.fa-medium,.fa-medium-m{--fa: ""}.fa-amilia{--fa: ""}.fa-mixcloud{--fa: ""}.fa-flipboard{--fa: ""}.fa-viacoin{--fa: ""}.fa-critical-role{--fa: ""}.fa-sitrox{--fa: ""}.fa-discourse{--fa: ""}.fa-joomla{--fa: ""}.fa-mastodon{--fa: ""}.fa-airbnb{--fa: ""}.fa-wolf-pack-battalion{--fa: ""}.fa-buy-n-large{--fa: ""}.fa-gulp{--fa: ""}.fa-creative-commons-sampling-plus{--fa: ""}.fa-strava{--fa: ""}.fa-ember{--fa: ""}.fa-canadian-maple-leaf{--fa: ""}.fa-teamspeak{--fa: ""}.fa-pushed{--fa: ""}.fa-wordpress-simple{--fa: ""}.fa-nutritionix{--fa: ""}.fa-wodu{--fa: ""}.fa-google-pay{--fa: ""}.fa-intercom{--fa: ""}.fa-zhihu{--fa: ""}.fa-korvue{--fa: ""}.fa-pix{--fa: ""}.fa-steam-symbol{--fa: ""}:root,:host{--fa-style-family-classic: "Font Awesome 6 Free";--fa-font-regular: normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(/admin-next/assets/fa-regular-400-BjRzuEpd.woff2) format("woff2"),url(/admin-next/assets/fa-regular-400-DZaxPHgR.ttf) format("truetype")}.far,.fa-regular{font-weight:400}:root,:host{--fa-style-family-classic: "Font Awesome 6 Free";--fa-font-solid: normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(/admin-next/assets/fa-solid-900-CTAAxXor.woff2) format("woff2"),url(/admin-next/assets/fa-solid-900-D0aA9rwL.ttf) format("truetype")}.fas,.fa-solid{font-weight:900}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(/admin-next/assets/fa-brands-400-D_cYUPeE.woff2) format("woff2"),url(/admin-next/assets/fa-brands-400-D1LuMI3I.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(/admin-next/assets/fa-solid-900-CTAAxXor.woff2) format("woff2"),url(/admin-next/assets/fa-solid-900-D0aA9rwL.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(/admin-next/assets/fa-regular-400-BjRzuEpd.woff2) format("woff2"),url(/admin-next/assets/fa-regular-400-DZaxPHgR.ttf) format("truetype")}@font-face{font-family:FontAwesome;font-display:block;src:url(/admin-next/assets/fa-solid-900-CTAAxXor.woff2) format("woff2"),url(/admin-next/assets/fa-solid-900-D0aA9rwL.ttf) format("truetype")}@font-face{font-family:FontAwesome;font-display:block;src:url(/admin-next/assets/fa-brands-400-D_cYUPeE.woff2) format("woff2"),url(/admin-next/assets/fa-brands-400-D1LuMI3I.ttf) format("truetype")}@font-face{font-family:FontAwesome;font-display:block;src:url(/admin-next/assets/fa-regular-400-BjRzuEpd.woff2) format("woff2"),url(/admin-next/assets/fa-regular-400-DZaxPHgR.ttf) format("truetype");unicode-range:U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC}@font-face{font-family:FontAwesome;font-display:block;src:url(/admin-next/assets/fa-v4compatibility-C9RhG_FT.woff2) format("woff2"),url(/admin-next/assets/fa-v4compatibility-CCth-dXg.ttf) format("truetype");unicode-range:U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A}.el-button--primary{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);border-color:transparent}.el-button--primary:hover,.el-button--primary:focus{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);opacity:.9}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:left-\[2px\]:after{content:var(--tw-content);left:2px}.after\:top-0\.5:after{content:var(--tw-content);top:.125rem}.after\:h-4:after{content:var(--tw-content);height:1rem}.after\:w-4:after{content:var(--tw-content);width:1rem}.after\:rounded-full:after{content:var(--tw-content);border-radius:9999px}.after\:bg-white:after{content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.after\:shadow-sm:after{content:var(--tw-content);--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.after\:transition-transform:after{content:var(--tw-content);transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.after\:duration-200:after{content:var(--tw-content);transition-duration:.2s}.after\:content-\[\'\'\]:after{--tw-content: "";content:var(--tw-content)}.hover\:border-gray-300:hover{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.hover\:border-gray-400:hover{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}.hover\:border-indigo-300:hover{--tw-border-opacity: 1;border-color:rgb(165 180 252 / var(--tw-border-opacity, 1))}.hover\:bg-amber-700:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-100:hover{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-200:hover{--tw-bg-opacity: 1;background-color:rgb(191 219 254 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.hover\:bg-green-200:hover{--tw-bg-opacity: 1;background-color:rgb(187 247 208 / var(--tw-bg-opacity, 1))}.hover\:bg-green-50:hover{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.hover\:bg-green-600:hover{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.hover\:bg-green-700:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.hover\:bg-orange-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 215 170 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-200:hover{--tw-bg-opacity: 1;background-color:rgb(233 213 255 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-50:hover{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.hover\:bg-red-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 202 202 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-white\/10:hover{background-color:#ffffff1a}.hover\:bg-white\/50:hover{background-color:#ffffff80}.hover\:from-yellow-600:hover{--tw-gradient-from: #ca8a04 var(--tw-gradient-from-position);--tw-gradient-to: rgb(202 138 4 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:to-orange-600:hover{--tw-gradient-to: #ea580c var(--tw-gradient-to-position)}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-blue-900:hover{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.hover\:text-green-700:hover{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.hover\:text-green-900:hover{--tw-text-opacity: 1;color:rgb(20 83 45 / var(--tw-text-opacity, 1))}.hover\:text-indigo-800:hover{--tw-text-opacity: 1;color:rgb(55 48 163 / var(--tw-text-opacity, 1))}.hover\:text-purple-900:hover{--tw-text-opacity: 1;color:rgb(88 28 135 / var(--tw-text-opacity, 1))}.hover\:text-red-800:hover{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.hover\:text-red-900:hover{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.peer:checked~.peer-checked\:bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.peer:checked~.peer-checked\:after\:translate-x-4:after{content:var(--tw-content);--tw-translate-x: 1rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.peer:focus~.peer-focus\:outline-none{outline:2px solid transparent;outline-offset:2px}.peer:focus~.peer-focus\:ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.peer:focus~.peer-focus\:ring-blue-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity, 1))}@media (min-width: 640px){.sm\:flex-row{flex-direction:row}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}}@media (min-width: 1024px){.lg\:col-span-1{grid-column:span 1 / span 1}.lg\:col-span-3{grid-column:span 3 / span 3}.lg\:block{display:block}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-between{justify-content:space-between}}@media (min-width: 1280px){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}:root{--primary-color: #667eea;--secondary-color: #764ba2;--accent-color: #f093fb;--success-color: #10b981;--warning-color: #f59e0b;--error-color: #ef4444;--surface-color: rgba(255, 255, 255, .95);--glass-color: rgba(255, 255, 255, .1);--text-primary: #1f2937;--text-secondary: #6b7280;--border-color: rgba(255, 255, 255, .2)}body,div,button,input,select,textarea,table,tr,td,th,span,p,h1,h2,h3,h4,h5,h6{transition:all .3s cubic-bezier(.4,0,.2,1)}body{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 50%,var(--accent-color) 100%);background-attachment:fixed;min-height:100vh;margin:0;overflow-x:hidden}body:before{content:"";position:fixed;top:0;left:0;right:0;bottom:0;background:radial-gradient(circle at 20% 80%,rgba(240,147,251,.2) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(102,126,234,.2) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(118,75,162,.1) 0%,transparent 50%);pointer-events:none;z-index:-1}.glass{background:var(--glass-color);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border:1px solid var(--border-color);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a,inset 0 1px #ffffff1a}.glass-strong{background:var(--surface-color);-webkit-backdrop-filter:blur(25px);backdrop-filter:blur(25px);border:1px solid rgba(255,255,255,.3);box-shadow:0 25px 50px -12px #00000040,0 0 0 1px #ffffff0d,inset 0 1px #ffffff1a}.tab-btn{position:relative;overflow:hidden;border-radius:12px;font-weight:500;letter-spacing:.025em}.tab-btn:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent);transition:left .5s}.tab-btn:hover:before{left:100%}.tab-btn.active{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);color:#fff;box-shadow:0 10px 15px -3px #667eea4d,0 4px 6px -2px #667eea0d;transform:translateY(-1px)}.card{background:var(--surface-color);border-radius:16px;border:1px solid rgba(255,255,255,.2);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;overflow:hidden;position:relative}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent)}.stat-card{background:linear-gradient(135deg,#fffffff2,#fffc);border-radius:20px;border:1px solid rgba(255,255,255,.3);padding:24px;position:relative;overflow:hidden;transition:all .3s ease}.stat-card:before{content:"";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:radial-gradient(circle,rgba(255,255,255,.1) 0%,transparent 70%);opacity:0;transition:opacity .3s ease}.stat-card:hover{transform:translateY(-4px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.stat-card:hover:before{opacity:1}.stat-icon{width:56px;height:56px;border-radius:16px;display:flex;align-items:center;justify-content:center;font-size:24px;color:#fff;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.btn{font-weight:500;border-radius:12px;border:none;cursor:pointer;transition:all .3s ease;position:relative;overflow:hidden;letter-spacing:.025em}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#fff3;border-radius:50%;transform:translate(-50%,-50%);transition:width .3s ease,height .3s ease}.btn:active:before{width:300px;height:300px}.btn-primary{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);color:#fff;box-shadow:0 10px 15px -3px #667eea4d,0 4px 6px -2px #667eea0d}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 20px 25px -5px #667eea4d,0 10px 10px -5px #667eea1a}.btn-success{background:linear-gradient(135deg,var(--success-color) 0%,#059669 100%);color:#fff;box-shadow:0 10px 15px -3px #10b9814d,0 4px 6px -2px #10b9810d}.btn-success:hover{transform:translateY(-1px);box-shadow:0 20px 25px -5px #10b9814d,0 10px 10px -5px #10b9811a}.btn-danger{background:linear-gradient(135deg,var(--error-color) 0%,#dc2626 100%);color:#fff;box-shadow:0 10px 15px -3px #ef44444d,0 4px 6px -2px #ef44440d}.btn-danger:hover{transform:translateY(-1px);box-shadow:0 20px 25px -5px #ef44444d,0 10px 10px -5px #ef44441a}.form-input{background:#ffffffe6;border:2px solid rgba(255,255,255,.3);border-radius:12px;padding:16px;font-size:16px;transition:all .3s ease;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.form-input:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px #667eea1a,0 10px 15px -3px #0000001a;background:#fffffff2}.table-container{background:#fffffff2;border-radius:16px;overflow:hidden;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.table-row{transition:all .2s ease}.table-row:hover{background:#667eea0d;transform:scale(1.005)}.modal{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:#0006}.modal-content{background:#fffffff2;border-radius:24px;border:1px solid rgba(255,255,255,.3);box-shadow:0 25px 50px -12px #00000040,0 0 0 1px #ffffff0d;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}.header-title{background:linear-gradient(135deg,var(--primary-color) 0%,var(--secondary-color) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:700;letter-spacing:-.025em}.loading-spinner{display:inline-block;width:20px;height:20px;border:2px solid rgba(255,255,255,.3);border-radius:50%;border-top:2px solid white;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.fade-enter-active,.fade-leave-active{transition:opacity .3s ease}.fade-enter-from,.fade-leave-to{opacity:0}.slide-up-enter-active,.slide-up-leave-active{transition:all .3s ease}.slide-up-enter-from{opacity:0;transform:translateY(30px)}.slide-up-leave-to{opacity:0;transform:translateY(-30px)}.toast{position:fixed;top:80px;right:20px;z-index:1000;min-width:320px;max-width:500px;transform:translate(100%);transition:transform .3s ease-in-out}.toast.show{transform:translate(0)}.toast-success{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border:1px solid rgba(16,185,129,.3)}.toast-error{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border:1px solid rgba(239,68,68,.3)}.toast-info{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border:1px solid rgba(59,130,246,.3)}.toast-warning{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border:1px solid rgba(245,158,11,.3)}[v-cloak]{display:none}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:rgba(102,126,234,.3) rgba(102,126,234,.05)}.custom-scrollbar::-webkit-scrollbar{width:8px;height:8px}.custom-scrollbar::-webkit-scrollbar-track{background:#667eea0d;border-radius:10px}.custom-scrollbar::-webkit-scrollbar-thumb{background:linear-gradient(135deg,#667eea66,#764ba266);border-radius:10px;-webkit-transition:background .3s ease;transition:background .3s ease}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,#667eea99,#764ba299)}.custom-scrollbar::-webkit-scrollbar-thumb:active{background:linear-gradient(135deg,#667eeacc,#764ba2cc)}.modal-scroll-content{max-height:calc(90vh - 160px);overflow-y:auto;padding-right:8px}@media (max-width: 768px){.glass,.glass-strong{margin:16px;border-radius:20px}.stat-card{padding:16px}.tab-btn{font-size:14px;padding:12px 8px}.modal-scroll-content{max-height:calc(85vh - 120px)}}@keyframes pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.1);opacity:.8}to{transform:scale(1);opacity:1}}.animate-pulse{animation:pulse 2s infinite}.user-menu-dropdown{min-width:240px;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.tab-content{animation:fadeIn .3s ease-in-out}@keyframes fadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}} diff --git a/web/admin-spa/dist/index.html b/web/admin-spa/dist/index.html deleted file mode 100644 index d15687bd..00000000 --- a/web/admin-spa/dist/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - Claude Relay Service - 管理后台 - - - - - - - - - - - - - - - - - - - - - - -
- - \ No newline at end of file diff --git a/web/admin-spa/src/components/accounts/AccountForm.vue b/web/admin-spa/src/components/accounts/AccountForm.vue index 6bc82c6b..eb252e55 100644 --- a/web/admin-spa/src/components/accounts/AccountForm.vue +++ b/web/admin-spa/src/components/accounts/AccountForm.vue @@ -183,7 +183,9 @@ class="form-input flex-1" required > - + - + @@ -288,92 +295,36 @@
- -
-

- - 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 -

-
- - -
-
- - - - -
-
- - - - - -
+ +
- -
+