fix: 充值页改为浅色风格,仅支付宝,余额401显示新用户提示

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hfshfg
2026-04-06 16:52:39 +08:00
parent 6598eaaa35
commit e9c508a27e

View File

@@ -7,254 +7,273 @@
<style> <style>
*{margin:0;padding:0;box-sizing:border-box} *{margin:0;padding:0;box-sizing:border-box}
:root{ :root{
--bg:#09090b; --bg:#f5f5f7;
--card:#18181b; --surface:#ffffff;
--card-hover:#1c1c20; --border:#e5e5e5;
--border:#27272a; --border-hover:#d0d0d0;
--border-active:#3f3f46; --text:#1a1a1a;
--text:#fafafa; --text-muted:#6b7280;
--text-muted:#a1a1aa; --text-dim:#9ca3af;
--text-dim:#52525b; --blue:#2563eb;
--blue:#3b82f6; --blue-light:#eff6ff;
--blue-glow:rgba(59,130,246,0.12); --blue-border:#bfdbfe;
--green:#22c55e; --green:#16a34a;
--green-glow:rgba(34,197,94,0.12); --green-light:#f0fdf4;
--orange:#f97316; --green-border:#bbf7d0;
--orange-dark:#ea580c; --orange:#ea580c;
--orange-glow:rgba(249,115,22,0.15); --orange-light:#fff7ed;
--yellow:#eab308; --orange-border:#fed7aa;
--red:#ef4444; --red:#dc2626;
--radius:12px; --yellow:#d97706;
--radius:14px;
--shadow:0 1px 3px rgba(0,0,0,0.08),0 1px 2px rgba(0,0,0,0.04);
--shadow-hover:0 4px 12px rgba(0,0,0,0.1),0 2px 4px rgba(0,0,0,0.06);
} }
body{font-family:-apple-system,"Microsoft YaHei","PingFang SC",sans-serif;background:var(--bg);color:var(--text);min-height:100vh} body{font-family:-apple-system,"Microsoft YaHei","PingFang SC",sans-serif;background:var(--bg);color:var(--text);min-height:100vh}
.header{padding:20px 28px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:14px;background:var(--card)} /* Header */
.logo{width:40px;height:40px;border-radius:10px;border:1px solid var(--border)} .header{
.header-title{font-size:1.05em;font-weight:700;color:var(--text)} background:var(--surface);
.header-sub{font-size:.78em;color:var(--text-muted);margin-top:2px} border-bottom:1px solid var(--border);
padding:0 28px;height:56px;
display:flex;align-items:center;justify-content:space-between;
position:sticky;top:0;z-index:10;
}
.header-left{display:flex;align-items:center;gap:10px}
.logo{width:28px;height:28px;border-radius:7px;border:1px solid var(--border)}
.header-title{font-size:.95em;font-weight:700;color:var(--text)}
.header-badge{
font-size:.68em;padding:2px 8px;border-radius:20px;font-weight:600;
background:var(--orange-light);color:var(--orange);border:1px solid var(--orange-border);
}
/* Layout */
.container{max-width:520px;margin:0 auto;padding:28px 20px 80px} .container{max-width:520px;margin:0 auto;padding:28px 20px 80px}
/* Section toggle */
.section{display:none} .section{display:none}
.section.active{display:block} .section.active{display:block}
/* 余额卡片 */ /* Key 手动输入 */
.balance-card{ .key-input-card{
background:linear-gradient(135deg,rgba(249,115,22,0.08) 0%,var(--card) 100%); background:var(--surface);border:1.5px solid var(--border);
border:1px solid rgba(249,115,22,0.3);
border-radius:var(--radius);
padding:20px;
margin-bottom:20px;
position:relative;overflow:hidden;
}
.balance-card::before{
content:'';position:absolute;inset:0;
background:linear-gradient(90deg,var(--orange-glow) 0%,transparent 60%);
pointer-events:none;
}
.balance-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.balance-title{font-size:.82em;font-weight:700;color:var(--orange);display:flex;align-items:center;gap:6px}
.balance-refresh{
background:rgba(249,115,22,0.12);border:1px solid rgba(249,115,22,0.25);
color:var(--orange);border-radius:6px;padding:4px 10px;
font-size:.72em;cursor:pointer;font-family:inherit;transition:all .15s;
}
.balance-refresh:hover{background:rgba(249,115,22,0.22)}
.balance-refresh:disabled{opacity:.4;cursor:default}
.key-row{
background:rgba(0,0,0,0.3);border:1px solid var(--border);
border-radius:8px;padding:10px 14px;margin-bottom:12px;
}
.key-label{font-size:.72em;color:var(--text-dim);margin-bottom:4px}
.key-inner{display:flex;align-items:center;gap:8px}
.key-val{
flex:1;font-size:.72em;color:var(--orange);
font-family:"Consolas","Courier New",monospace;
letter-spacing:.02em;word-break:break-all;line-height:1.5;
}
.copy-btn{
background:rgba(249,115,22,0.15);border:1px solid rgba(249,115,22,0.3);
color:var(--orange);border-radius:6px;padding:4px 10px;
font-size:.72em;font-weight:600;cursor:pointer;white-space:nowrap;
transition:all .15s;font-family:inherit;
}
.copy-btn:hover{background:rgba(249,115,22,0.25)}
.balance-row{
display:flex;align-items:center;gap:10px;
background:rgba(0,0,0,0.25);border:1px solid var(--border);
border-radius:8px;padding:10px 14px;
}
.balance-label{font-size:.75em;color:var(--text-dim);white-space:nowrap}
.balance-val{
flex:1;font-size:1.1em;font-weight:700;
font-family:"Consolas","Courier New",monospace;
}
.balance-val.ok{color:var(--green)}
.balance-val.warn{color:var(--yellow)}
.balance-val.low{color:var(--red)}
.balance-val.dim{color:var(--text-dim)}
/* 充值表单区 */
.form-card{
background:var(--card);border:1px solid var(--border);
border-radius:var(--radius);padding:20px;margin-bottom:16px; border-radius:var(--radius);padding:20px;margin-bottom:16px;
box-shadow:var(--shadow);
}
.key-input-title{font-size:.88em;font-weight:600;color:var(--text-muted);margin-bottom:10px}
.key-input-wrap{display:flex;gap:8px}
.key-input-wrap input{
flex:1;padding:9px 12px;
background:var(--bg);border:1.5px solid var(--border);
border-radius:9px;color:var(--text);font-size:.86em;
outline:none;transition:border-color .15s;font-family:inherit;
}
.key-input-wrap input:focus{border-color:var(--orange)}
.key-confirm-btn{
padding:9px 16px;border:none;border-radius:9px;
background:var(--blue);color:#fff;font-size:.84em;font-weight:600;
cursor:pointer;white-space:nowrap;font-family:inherit;transition:background .15s;
}
.key-confirm-btn:hover{background:#1d4ed8}
/* 账户面板 */
.xp-panel{
background:var(--surface);
border:1.5px solid var(--orange-border);
border-radius:var(--radius);
overflow:hidden;
box-shadow:var(--shadow);
margin-bottom:16px;
}
.xp-panel-head{
background:var(--orange-light);
padding:14px 18px;
border-bottom:1px solid var(--orange-border);
display:flex;align-items:center;justify-content:space-between;gap:8px;
}
.xp-panel-head-left{display:flex;align-items:center;gap:8px}
.xp-panel-title{font-size:.9em;font-weight:700;color:var(--orange)}
.xp-panel-body{padding:16px 18px;display:flex;flex-direction:column;gap:10px}
/* Key 行 */
.xp-key-box{
background:var(--bg);border:1px solid var(--border);
border-radius:9px;padding:10px 12px;
}
.xp-key-label{font-size:.68em;color:var(--text-dim);margin-bottom:4px;font-weight:600;letter-spacing:.04em}
.xp-key-inner{display:flex;align-items:center;gap:6px}
.xp-key-val{
flex:1;font-size:.72em;color:var(--text-muted);
font-family:"Consolas","Courier New",monospace;
word-break:break-all;line-height:1.4;
}
.xp-copy-btn{
background:var(--surface);border:1px solid var(--border);
color:var(--text-muted);border-radius:6px;
padding:4px 10px;font-size:.7em;font-weight:600;
cursor:pointer;white-space:nowrap;font-family:inherit;
transition:all .15s;flex-shrink:0;
}
.xp-copy-btn:hover{border-color:var(--blue);color:var(--blue)}
/* 余额行 */
.xp-bal-box{
background:var(--bg);border:1px solid var(--border);
border-radius:9px;padding:10px 12px;
display:flex;align-items:center;gap:8px;
}
.xp-bal-label{font-size:.72em;color:var(--text-dim);flex-shrink:0}
.xp-bal-val{flex:1;font-size:.95em;font-weight:700;color:var(--green)}
.xp-bal-val.warn{color:var(--yellow)}
.xp-bal-val.low{color:var(--red)}
.xp-bal-val.dim{color:var(--text-dim);font-weight:400;font-size:.82em}
.xp-refresh-btn{
background:none;border:1px solid var(--border);
color:var(--text-dim);border-radius:6px;
padding:3px 9px;font-size:.68em;cursor:pointer;
font-family:inherit;transition:all .15s;white-space:nowrap;flex-shrink:0;
}
.xp-refresh-btn:hover{border-color:var(--border-hover);color:var(--text)}
.xp-refresh-btn:disabled{opacity:.45;cursor:default}
/* 充值表单卡片 */
.form-card{
background:var(--surface);border:1.5px solid var(--border);
border-radius:var(--radius);padding:20px;margin-bottom:16px;
box-shadow:var(--shadow);
} }
.form-card-title{ .form-card-title{
font-size:.9em;font-weight:700;color:var(--text); font-size:.9em;font-weight:700;color:var(--text);
margin-bottom:16px;display:flex;align-items:center;gap:8px; margin-bottom:16px;display:flex;align-items:center;gap:8px;
} }
/* 金额选择 */ /* 金额网格 */
.amount-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:12px} .amt-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:12px}
.amount-btn{ .amt-btn{
background:rgba(255,255,255,0.03);border:1px solid var(--border); background:var(--bg);border:1.5px solid var(--border);
border-radius:9px;padding:12px 8px;text-align:center; border-radius:10px;padding:12px 6px;text-align:center;
cursor:pointer;transition:all .15s; cursor:pointer;transition:all .15s;
} }
.amount-btn:hover{border-color:var(--border-active);background:rgba(255,255,255,0.06)} .amt-btn:hover{border-color:var(--border-hover);box-shadow:var(--shadow-hover)}
.amount-btn.selected{ .amt-btn.sel{border-color:var(--orange);background:var(--orange-light);box-shadow:0 0 0 1px var(--orange)}
border-color:var(--orange); .amt-cny{font-size:1em;font-weight:700;color:var(--text)}
background:rgba(249,115,22,0.1); .amt-quota{font-size:.62em;color:var(--text-dim);margin-top:2px}
box-shadow:0 0 0 1px var(--orange); .amt-btn.sel .amt-cny{color:var(--orange)}
} .amt-btn.sel .amt-quota{color:rgba(234,88,12,.6)}
.amount-cny{font-size:1.05em;font-weight:700;color:var(--text)}
.amount-quota{font-size:.68em;color:var(--text-dim);margin-top:2px}
.amount-btn.selected .amount-cny{color:var(--orange)}
.amount-btn.selected .amount-quota{color:rgba(249,115,22,0.6)}
.custom-wrap{display:flex;align-items:center;gap:8px;margin-bottom:4px} .custom-wrap{display:none;margin-bottom:8px}
.custom-prefix{font-size:.9em;color:var(--text-muted);white-space:nowrap} .custom-inner{display:flex;align-items:center;gap:6px}
.custom-prefix{font-size:.9em;color:var(--text-muted)}
input[type="number"],input[type="text"]{ input[type="number"],input[type="text"]{
flex:1;padding:10px 13px; flex:1;padding:9px 12px;
background:#0c0c0f;border:1px solid var(--border); background:var(--bg);border:1.5px solid var(--border);
border-radius:9px;color:var(--text);font-size:.92em; border-radius:9px;color:var(--text);font-size:.86em;
outline:none;transition:border-color .2s;font-family:inherit; outline:none;transition:border-color .15s;font-family:inherit;
-moz-appearance:textfield; -moz-appearance:textfield;
} }
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none} input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none}
input:focus{border-color:var(--orange)} input:focus{border-color:var(--orange)}
.input-hint{font-size:.76em;color:var(--text-dim);margin-top:5px} .input-hint{font-size:.74em;color:var(--text-dim);margin-top:5px}
/* 支付二维码 */ /* 分割线 */
.qr-section{margin-bottom:16px} .divider{height:1px;background:var(--border);margin:16px 0}
.qr-tabs{display:flex;gap:6px;margin-bottom:12px}
/* QR */
.qr-tabs{display:flex;gap:5px;margin-bottom:10px}
.qr-tab{ .qr-tab{
padding:6px 14px;border-radius:7px;font-size:.8em;font-weight:600; flex:1;padding:7px;border-radius:8px;
cursor:pointer;border:1px solid var(--border);background:transparent; font-size:.78em;font-weight:600;
color:var(--text-muted);font-family:inherit;transition:all .15s; cursor:pointer;border:1.5px solid var(--border);
} background:transparent;color:var(--text-muted);
.qr-tab.active{ font-family:inherit;transition:all .15s;text-align:center;
background:rgba(34,197,94,0.12);border-color:rgba(34,197,94,0.35);
color:var(--green);
}
.qr-box{
background:rgba(0,0,0,0.3);border:1px solid var(--border);
border-radius:10px;padding:16px;text-align:center;display:none;
} }
.qr-tab.active{background:var(--green-light);border-color:var(--green-border);color:var(--green)}
.qr-box{display:none;text-align:center}
.qr-box.active{display:block} .qr-box.active{display:block}
.qr-img{ .qr-img{
width:180px;height:180px;object-fit:contain; width:168px;height:168px;object-fit:contain;
border-radius:10px;border:2px solid var(--border); border-radius:10px;border:1px solid var(--border);
background:#fff;margin:0 auto 10px;display:block; background:var(--bg);margin:0 auto 8px;display:block;
} }
.qr-placeholder{ .qr-placeholder{
width:180px;height:180px;border-radius:10px; width:168px;height:168px;border-radius:10px;
border:2px dashed var(--border);background:rgba(0,0,0,0.3); border:1.5px dashed var(--border);background:var(--bg);
margin:0 auto 10px;display:flex;align-items:center;justify-content:center; margin:0 auto 8px;display:flex;align-items:center;justify-content:center;
flex-direction:column;gap:8px;color:var(--text-dim);font-size:.8em; flex-direction:column;gap:6px;color:var(--text-dim);font-size:.78em;
} }
.qr-name{font-size:.82em;color:var(--text-muted);font-weight:600} .qr-name{font-size:.82em;color:var(--text-muted);font-weight:600}
.qr-sub{font-size:.72em;color:var(--text-dim);margin-top:2px} .qr-sub{font-size:.7em;color:var(--text-dim);margin-top:2px;line-height:1.5}
/* 截图上传 */ /* 截图上传 */
.upload-area{ .upload-area{
border:2px dashed var(--border);border-radius:10px; border:1.5px dashed var(--border);border-radius:10px;
padding:28px 20px;text-align:center;cursor:pointer; padding:22px 16px;text-align:center;cursor:pointer;
transition:all .2s;position:relative;overflow:hidden; transition:all .15s;position:relative;overflow:hidden;
background:rgba(0,0,0,0.2); background:var(--bg);
} }
.upload-area:hover{border-color:var(--border-active);background:rgba(255,255,255,0.02)} .upload-area:hover{border-color:var(--border-hover);background:var(--surface)}
.upload-area.has-file{border-color:var(--green);border-style:solid;background:rgba(34,197,94,0.05)} .upload-area.has{border-color:var(--green);border-style:solid;background:var(--green-light)}
.upload-area input{position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%} .upload-area input{position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%}
.upload-icon{font-size:2em;margin-bottom:8px;color:var(--text-dim)} .upload-icon{font-size:1.8em;margin-bottom:6px;color:var(--text-dim)}
.upload-text{font-size:.84em;color:var(--text-muted)} .upload-text{font-size:.82em;color:var(--text-muted)}
.upload-sub{font-size:.74em;color:var(--text-dim);margin-top:4px} .upload-sub{font-size:.72em;color:var(--text-dim);margin-top:3px}
.upload-preview{max-width:100%;max-height:200px;border-radius:8px;object-fit:contain;display:none;margin:0 auto} .upload-preview{max-width:100%;max-height:160px;border-radius:8px;object-fit:contain;display:none;margin:0 auto}
label{display:block;font-size:.8em;color:var(--text-muted);font-weight:600;margin-bottom:8px}
/* 提交按钮 */ /* 提交按钮 */
.submit-btn{ .submit-btn{
width:100%;padding:14px;border:none;border-radius:10px; width:100%;padding:13px;border:none;border-radius:10px;
font-size:.96em;font-weight:700;cursor:pointer; font-size:.94em;font-weight:700;cursor:pointer;
font-family:inherit;transition:all .2s; font-family:inherit;transition:all .15s;
background:linear-gradient(135deg,var(--orange),var(--orange-dark)); background:var(--orange);color:#fff;
color:#fff; box-shadow:0 2px 8px rgba(234,88,12,0.25);
box-shadow:0 4px 16px rgba(249,115,22,0.3);
}
.submit-btn:hover{box-shadow:0 6px 20px rgba(249,115,22,0.4);transform:translateY(-1px)}
.submit-btn:active{transform:translateY(0)}
.submit-btn:disabled{
background:var(--border);color:var(--text-dim);
cursor:not-allowed;box-shadow:none;transform:none;
} }
.submit-btn:hover{background:#c2410c;box-shadow:0 4px 14px rgba(234,88,12,0.3);transform:translateY(-1px)}
.submit-btn:active{transform:none}
.submit-btn:disabled{background:var(--text-dim);cursor:not-allowed;box-shadow:none;transform:none}
/* 成功页 */ /* 成功页 */
.success-view{text-align:center;padding:50px 20px} .success-view{
.success-icon{font-size:3.5em;margin-bottom:20px} background:var(--surface);border:1.5px solid var(--green-border);
.success-title{font-size:1.3em;font-weight:700;color:var(--green);margin-bottom:10px} border-radius:var(--radius);padding:40px 24px;
.success-desc{color:var(--text-muted);font-size:.88em;line-height:1.8;margin-bottom:24px} text-align:center;box-shadow:var(--shadow);
}
.success-icon{font-size:3em;margin-bottom:16px}
.success-title{font-size:1.2em;font-weight:700;color:var(--green);margin-bottom:8px}
.success-desc{color:var(--text-muted);font-size:.86em;line-height:1.8;margin-bottom:20px}
.success-tip{ .success-tip{
background:rgba(34,197,94,0.08);border:1px solid rgba(34,197,94,0.2); background:var(--green-light);border:1px solid var(--green-border);
border-radius:10px;padding:14px 18px; border-radius:10px;padding:14px 16px;
font-size:.82em;color:var(--text-muted);line-height:1.8;text-align:left; font-size:.8em;color:var(--text-muted);line-height:1.8;text-align:left;
} }
.back-btn{ .back-btn{
display:inline-flex;align-items:center;gap:6px; display:inline-flex;align-items:center;gap:5px;
margin-top:24px;padding:10px 22px; margin-top:20px;padding:9px 20px;
background:var(--card);border:1px solid var(--border); background:var(--bg);border:1.5px solid var(--border);
border-radius:8px;color:var(--text-muted);font-size:.88em; border-radius:8px;color:var(--text-muted);font-size:.84em;
cursor:pointer;font-family:inherit;transition:all .15s; cursor:pointer;font-family:inherit;transition:all .15s;
} }
.back-btn:hover{border-color:var(--border-active);color:var(--text)} .back-btn:hover{border-color:var(--border-hover);color:var(--text)}
/* Key 未找到提示 */
.key-input-section{
background:var(--card);border:1px solid var(--border);
border-radius:var(--radius);padding:20px;margin-bottom:20px;
}
.key-input-title{font-size:.88em;font-weight:600;color:var(--text-muted);margin-bottom:10px}
.key-input-wrap{display:flex;gap:8px}
.key-input-wrap input{flex:1}
.key-confirm-btn{
padding:10px 16px;border:none;border-radius:9px;
background:var(--blue);color:#fff;font-size:.86em;font-weight:600;
cursor:pointer;white-space:nowrap;font-family:inherit;transition:background .15s;
}
.key-confirm-btn:hover{background:#2563eb}
/* Toast */ /* Toast */
.toast{ .toast{
position:fixed;top:20px;right:20px; position:fixed;top:20px;right:20px;
background:#22c55e;color:#fff; background:var(--green);color:#fff;
padding:10px 20px;border-radius:8px; padding:10px 18px;border-radius:8px;
font-size:.84em;font-weight:500; font-size:.82em;font-weight:500;
opacity:0;transform:translateY(-8px); opacity:0;transform:translateY(-8px);
transition:all .25s;z-index:999;pointer-events:none; transition:all .25s;z-index:999;pointer-events:none;
box-shadow:0 4px 12px rgba(0,0,0,0.15);
} }
.toast.show{opacity:1;transform:translateY(0)} .toast.show{opacity:1;transform:translateY(0)}
.toast.error{background:var(--red)} .toast.error{background:var(--red)}
.toast.info{background:var(--blue)} .toast.info{background:var(--blue)}
/* 分割线 */
.divider{height:1px;background:var(--border);margin:16px 0}
label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;margin-bottom:8px}
@media(max-width:480px){ @media(max-width:480px){
.amount-grid{grid-template-columns:repeat(2,1fr)} .amt-grid{grid-template-columns:repeat(2,1fr)}
.header{padding:16px 18px} .header{padding:0 16px}
.container{padding:20px 14px 80px} .container{padding:20px 14px 80px}
} }
</style> </style>
@@ -262,20 +281,20 @@ label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;marg
<body> <body>
<div class="header"> <div class="header">
<img class="logo" src="assets/logo.png" alt="logo" onerror="this.style.display='none'"> <div class="header-left">
<div> <img class="logo" src="assets/logo.png" alt="" onerror="this.style.display='none'">
<div class="header-title">虾盘云 — 充值</div> <span class="header-title">虾盘云 — 充值</span>
<div class="header-sub">充值后余额实时到账一般10分钟内审核</div>
</div> </div>
<span class="header-badge">虾盘出品</span>
</div> </div>
<div class="container"> <div class="container">
<!-- Key 手动输入区(自动隐藏 --> <!-- Key 手动输入(未检测到时显示 -->
<div class="key-input-section" id="keyInputSection" style="display:none"> <div class="key-input-card" id="keyInputCard" style="display:none">
<div class="key-input-title">未检测到 API Key请手动粘贴</div> <div class="key-input-title">未检测到 API Key请手动粘贴</div>
<div class="key-input-wrap"> <div class="key-input-wrap">
<input type="text" id="manualKeyInput" placeholder="sk-xp-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"> <input type="text" id="manualKeyInput" placeholder="sk-xp-... 或 sk-...">
<button class="key-confirm-btn" onclick="confirmManualKey()">确认</button> <button class="key-confirm-btn" onclick="confirmManualKey()">确认</button>
</div> </div>
</div> </div>
@@ -283,94 +302,97 @@ label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;marg
<!-- 主表单 --> <!-- 主表单 -->
<div class="section active" id="mainSection"> <div class="section active" id="mainSection">
<!-- 余额卡片 --> <!-- 账户面板 -->
<div class="balance-card"> <div class="xp-panel">
<div class="balance-header"> <div class="xp-panel-head">
<div class="balance-title">🦐 虾盘云 · 我的账户</div> <div class="xp-panel-head-left">
<button class="balance-refresh" id="refreshBtn" onclick="loadBalance()">刷新余额</button> <span style="font-size:1.1em">🦐</span>
<span class="xp-panel-title">虾盘云 · 账户</span>
</div> </div>
<div class="key-row"> <button class="xp-refresh-btn" id="refreshBtn" onclick="loadBalance()">刷新</button>
<div class="key-label">我的专属 Key</div> </div>
<div class="key-inner"> <div class="xp-panel-body">
<div class="key-val" id="keyDisplay">检测中...</div> <div class="xp-key-box">
<button class="copy-btn" onclick="copyKey()">复制</button> <div class="xp-key-label">我的专属 KEY</div>
<div class="xp-key-inner">
<div class="xp-key-val" id="keyDisplay">检测中...</div>
<button class="xp-copy-btn" onclick="copyKey()">复制</button>
</div> </div>
</div> </div>
<div class="balance-row"> <div class="xp-bal-box">
<div class="balance-label">当前余额</div> <span class="xp-bal-label">当前余额</span>
<div class="balance-val dim" id="balanceVal">加载中...</div> <span class="xp-bal-val dim" id="balanceVal">查询中...</span>
</div>
</div> </div>
</div> </div>
<!-- 充值金额 --> <!-- 充值表单 -->
<div class="form-card"> <div class="form-card">
<div class="form-card-title">💰 选择充值金额</div> <div class="form-card-title">选择充值金额</div>
<div class="amount-grid"> <div class="amt-grid">
<div class="amount-btn" onclick="selectAmount(20)" data-amt="20"> <div class="amt-btn" onclick="selectAmt(20)" data-amt="20">
<div class="amount-cny">¥20</div> <div class="amt-cny">¥20</div>
<div class="amount-quota">+1000万</div> <div class="amt-quota">+1000万</div>
</div> </div>
<div class="amount-btn" onclick="selectAmount(50)" data-amt="50"> <div class="amt-btn" onclick="selectAmt(50)" data-amt="50">
<div class="amount-cny">¥50</div> <div class="amt-cny">¥50</div>
<div class="amount-quota">+2500万</div> <div class="amt-quota">+2500万</div>
</div> </div>
<div class="amount-btn" onclick="selectAmount(100)" data-amt="100"> <div class="amt-btn" onclick="selectAmt(100)" data-amt="100">
<div class="amount-cny">¥100</div> <div class="amt-cny">¥100</div>
<div class="amount-quota">+5000万</div> <div class="amt-quota">+5000万</div>
</div> </div>
<div class="amount-btn" onclick="selectAmount(0)" data-amt="0"> <div class="amt-btn" onclick="selectAmt(0)" data-amt="0">
<div class="amount-cny">自定</div> <div class="amt-cny">自定</div>
<div class="amount-quota">输入金额</div> <div class="amt-quota">输入金额</div>
</div> </div>
</div> </div>
<div id="customWrap" style="display:none;margin-bottom:8px"> <div class="custom-wrap" id="customWrap">
<div class="custom-wrap"> <div class="custom-inner">
<span class="custom-prefix">¥</span> <span class="custom-prefix">¥</span>
<input type="number" id="customAmt" placeholder="请输入金额(最低¥10" min="10" max="9999" oninput="onCustomInput()"> <input type="number" id="customAmt" placeholder="最低 ¥10" min="10" max="9999" oninput="onCustomInput()">
</div> </div>
<div class="input-hint">¥1 = 50万 quota¥10 起充</div> <div class="input-hint">¥1 = 50万 quota¥10 起充</div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<!-- 支付二维码 -->
<div class="qr-section">
<label>扫码付款</label> <label>扫码付款</label>
<div class="qr-tabs"> <div class="qr-tabs">
<button class="qr-tab active" onclick="switchQr('alipay',this)">支付宝</button> <button class="qr-tab active" onclick="switchQr('alipay',this)">支付宝</button>
<button class="qr-tab" onclick="switchQr('wechat',this)">微信</button> <button class="qr-tab" onclick="switchQr('wechat',this)">微信支付</button>
</div> </div>
<div class="qr-box active" id="qr-alipay"> <div class="qr-box active" id="qr-alipay">
<div class="qr-placeholder" id="qr-alipay-placeholder"> <div class="qr-placeholder" id="qr-alipay-ph">
<div style="font-size:2em">📱</div> <div style="font-size:1.8em">📱</div>
<div>支付宝收款码</div> <div>支付宝收款码</div>
<div style="font-size:.68em;margin-top:4px;opacity:.6">(管理员配置后显示)</div> <div style="font-size:.68em;margin-top:2px;opacity:.6">(管理员配置后显示)</div>
</div> </div>
<img class="qr-img" id="qr-alipay-img" src="" alt="支付宝收款码" style="display:none" onerror="this.style.display='none';document.getElementById('qr-alipay-placeholder').style.display='flex'"> <img class="qr-img" id="qr-alipay-img" src="" alt="支付宝" style="display:none"
onerror="this.style.display='none';document.getElementById('qr-alipay-ph').style.display='flex'">
<div class="qr-name">支付宝</div> <div class="qr-name">支付宝</div>
<div class="qr-sub">扫码付款备注填写您的 apikey</div> <div class="qr-sub">扫码付款 · 备注填写您的 Key 后8位</div>
</div> </div>
<div class="qr-box" id="qr-wechat"> <div class="qr-box" id="qr-wechat">
<div class="qr-placeholder" id="qr-wechat-placeholder"> <div class="qr-placeholder" id="qr-wechat-ph">
<div style="font-size:2em">💚</div> <div style="font-size:1.8em">💚</div>
<div>微信收款码</div> <div>微信收款码</div>
<div style="font-size:.68em;margin-top:4px;opacity:.6">(管理员配置后显示)</div> <div style="font-size:.68em;margin-top:2px;opacity:.6">(管理员配置后显示)</div>
</div> </div>
<img class="qr-img" id="qr-wechat-img" src="" alt="微信收款码" style="display:none" onerror="this.style.display='none';document.getElementById('qr-wechat-placeholder').style.display='flex'"> <img class="qr-img" id="qr-wechat-img" src="" alt="微信" style="display:none"
onerror="this.style.display='none';document.getElementById('qr-wechat-ph').style.display='flex'">
<div class="qr-name">微信支付</div> <div class="qr-name">微信支付</div>
<div class="qr-sub">扫码付款备注填写您的 apikey</div> <div class="qr-sub">扫码付款 · 备注填写您的 Key 后8位</div>
</div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<!-- 上传截图 -->
<label>上传付款截图 <span style="color:var(--text-dim);font-weight:400">(可选,有图更快审核)</span></label> <label>上传付款截图 <span style="color:var(--text-dim);font-weight:400">(可选,有图更快审核)</span></label>
<div class="upload-area" id="uploadArea" onclick="document.getElementById('screenshotInput').click()"> <div class="upload-area" id="uploadArea" onclick="document.getElementById('screenshotInput').click()">
<input type="file" id="screenshotInput" accept="image/*" style="display:none" onchange="onFileSelect(event)"> <input type="file" id="screenshotInput" accept="image/*" style="display:none" onchange="onFileSelect(event)">
<div id="uploadPlaceholder"> <div id="uploadPh">
<div class="upload-icon">📸</div> <div class="upload-icon">📸</div>
<div class="upload-text">点击上传付款截图</div> <div class="upload-text">点击上传付款截图</div>
<div class="upload-sub">支持 JPG / PNG不超过 5MB</div> <div class="upload-sub">支持 JPG / PNG不超过 5MB</div>
@@ -380,13 +402,11 @@ label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;marg
<div class="divider"></div> <div class="divider"></div>
<!-- 备注 -->
<label style="margin-top:4px">备注 <span style="color:var(--text-dim);font-weight:400">(可选)</span></label> <label style="margin-top:4px">备注 <span style="color:var(--text-dim);font-weight:400">(可选)</span></label>
<input type="text" id="noteInput" placeholder="如有疑问可在此备注,管理员会看到"> <input type="text" id="noteInput" placeholder="如有问题可备注,管理员会看到">
</div> </div>
<button class="submit-btn" id="submitBtn" onclick="submitRecharge()">提交充值申请</button> <button class="submit-btn" id="submitBtn" onclick="submitRecharge()">提交充值申请</button>
</div><!-- /mainSection --> </div><!-- /mainSection -->
@@ -397,15 +417,15 @@ label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;marg
<div class="success-title">申请已提交!</div> <div class="success-title">申请已提交!</div>
<div class="success-desc"> <div class="success-desc">
您的充值申请已成功提交。<br> 您的充值申请已成功提交。<br>
管理员会在微信收到通知,一般 <strong style="color:var(--orange)">10分钟内</strong> 完成审核充值 管理员会在微信收到通知,一般 <strong style="color:var(--orange)">10分钟内</strong> 完成审核。
</div> </div>
<div class="success-tip"> <div class="success-tip">
<strong style="color:var(--text)">审核完成后:</strong><br> <strong style="color:var(--text)">审核完成后:</strong><br>
· 余额自动到账,无需任何操作<br> · 余额自动到账,无需任何操作<br>
· 刷新余额即可看到最新数字<br> · 点"刷新"即可看到最新余额<br>
· 如超过1小时未到账微信联系管理员 · 如超过1小时未到账联系管理员
</div> </div>
<button class="back-btn" onclick="goBack()">← 返回查看余额</button> <button class="back-btn" onclick="goBack()">← 返回</button>
</div> </div>
</div> </div>
@@ -414,65 +434,43 @@ label{display:block;font-size:.82em;color:var(--text-muted);font-weight:500;marg
<div class="toast" id="toast"></div> <div class="toast" id="toast"></div>
<script> <script>
// ── 配置 ──────────────────────────────────────────────
const API_BASE = 'https://api.u-claw.org'; const API_BASE = 'https://api.u-claw.org';
const RECHARGE_API = API_BASE + '/recharge'; const RECHARGE_API = API_BASE + '/recharge';
// 管理员在服务器配置好后,把二维码图片路径填在这里
// 也可以通过 /recharge/config 接口动态获取
const QR_ALIPAY = ''; // 如 'https://api.u-claw.org/recharge/qr/alipay.jpg'
const QR_WECHAT = ''; // 如 'https://api.u-claw.org/recharge/qr/wechat.jpg'
// ── 状态 ──────────────────────────────────────────────
let currentKey = ''; let currentKey = '';
let selectedAmount = 0; // 0 = 自定义 let selectedAmt = -1;
let screenshotB64 = ''; let screenshotB64 = '';
let screenshotMime = 'image/jpeg'; let screenshotMime = 'image/jpeg';
// ── 初始化 ──────────────────────────────────────────────
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
initKey(); initKey();
loadQrCodes(); loadQrCodes();
}); });
// ── Key 检测 ─────────────────────────────────────────────
function initKey() { function initKey() {
// 优先从 URL 参数获取 key
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
let key = params.get('key') || params.get('api_key') || ''; let key = params.get('key') || params.get('api_key') || '';
// 其次尝试从 localStorage 读取
if (!key) key = localStorage.getItem('xiapan_key') || ''; if (!key) key = localStorage.getItem('xiapan_key') || '';
if (key) { setKey(key); return; }
// 尝试从 providers.json 读取(通过 config-server 本地服务)
if (!key) {
fetchKeyFromConfigServer().then(k => { fetchKeyFromConfigServer().then(k => {
if (k) { if (k) setKey(k);
setKey(k); else showKeyInput();
} else {
showKeyInput();
}
}); });
return;
}
setKey(key);
} }
async function fetchKeyFromConfigServer() { async function fetchKeyFromConfigServer() {
try {
// launcher 会启动本地 config-server通常在 localhost:18799
const ports = [18799, 18798, 18797, 18796, 18789]; const ports = [18799, 18798, 18797, 18796, 18789];
for (const port of ports) { for (const port of ports) {
try { try {
const r = await fetch(`http://localhost:${port}/config`, {signal: AbortSignal.timeout(800)}); const r = await fetch(`http://localhost:${port}/config`, {signal: AbortSignal.timeout(800)});
if (r.ok) { if (r.ok) {
const cfg = await r.json(); const cfg = await r.json();
const key = cfg?.providers?.xiapanyun?.api_key || ''; const k = cfg?.providers?.xiapanyun?.api_key || '';
if (key) return key; if (k) return k;
}
} catch(e) { /* 端口未开放,继续 */ }
} }
} catch(e) {} } catch(e) {}
}
return ''; return '';
} }
@@ -481,69 +479,64 @@ function setKey(key) {
localStorage.setItem('xiapan_key', key); localStorage.setItem('xiapan_key', key);
const masked = key.length > 14 ? key.slice(0, 10) + '...' + key.slice(-6) : key; const masked = key.length > 14 ? key.slice(0, 10) + '...' + key.slice(-6) : key;
document.getElementById('keyDisplay').textContent = masked; document.getElementById('keyDisplay').textContent = masked;
document.getElementById('keyInputSection').style.display = 'none'; document.getElementById('keyInputCard').style.display = 'none';
loadBalance(); loadBalance();
} }
function showKeyInput() { function showKeyInput() {
document.getElementById('keyInputSection').style.display = 'block'; document.getElementById('keyInputCard').style.display = 'block';
document.getElementById('keyDisplay').textContent = '未检测到'; document.getElementById('keyDisplay').textContent = '未检测到';
document.getElementById('balanceVal').textContent = '—'; document.getElementById('balanceVal').textContent = '—';
document.getElementById('balanceVal').className = 'balance-val dim'; document.getElementById('balanceVal').className = 'xp-bal-val dim';
} }
function confirmManualKey() { function confirmManualKey() {
const val = document.getElementById('manualKeyInput').value.trim(); const val = document.getElementById('manualKeyInput').value.trim();
if (val.length < 8) { if (val.length < 8) { showToast('Key 格式不对,请重新确认', 'error'); return; }
showToast('Key 格式不对,请重新确认', 'error'); return;
}
setKey(val); setKey(val);
} }
// ── 余额查询 ─────────────────────────────────────────────
async function loadBalance() { async function loadBalance() {
if (!currentKey) return; if (!currentKey) return;
const btn = document.getElementById('refreshBtn'); const btn = document.getElementById('refreshBtn');
const valEl = document.getElementById('balanceVal'); const valEl = document.getElementById('balanceVal');
btn.disabled = true; btn.disabled = true;
btn.textContent = '加载中...'; valEl.textContent = '查询中...';
valEl.textContent = '加载中...'; valEl.className = 'xp-bal-val dim';
valEl.className = 'balance-val dim';
try { try {
const d = new Date();
const monthStart = d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-01';
const hdrs = {'Authorization': 'Bearer ' + currentKey};
const [subRes, usageRes] = await Promise.all([ const [subRes, usageRes] = await Promise.all([
fetch(API_BASE + '/v1/dashboard/billing/subscription', {headers: {'Authorization': 'Bearer ' + currentKey}}), fetch(API_BASE + '/v1/dashboard/billing/subscription', {headers: hdrs}),
fetch(API_BASE + '/v1/dashboard/billing/usage?start_date=' + getMonthStart(), {headers: {'Authorization': 'Bearer ' + currentKey}}) fetch(API_BASE + '/v1/dashboard/billing/usage?start_date=' + monthStart, {headers: hdrs})
]); ]);
if (!subRes.ok) throw new Error('Key 无效');
if (!subRes.ok) throw new Error('key无效或网络错误');
const sub = await subRes.json(); const sub = await subRes.json();
const usage = usageRes.ok ? await usageRes.json() : {total_usage: 0}; const usage = usageRes.ok ? await usageRes.json() : {total_usage: 0};
const total = sub.hard_limit_usd || 0; const total = sub.hard_limit_usd || 0;
const used = (usage.total_usage || 0) / 100; const used = (usage.total_usage || 0) / 100;
const remaining = Math.max(0, total - used); const remaining = Math.max(0, total - used);
const remCny = remaining * 7.2;
let cls = 'ok'; let cls = '';
if (remaining < 1) cls = 'low'; if (remCny < 5) cls = 'low';
else if (remaining < 5) cls = 'warn'; else if (remCny < 20) cls = 'warn';
valEl.textContent = '¥' + (remaining * 7.2).toFixed(2) + ' 剩余(共充值 ¥' + (total * 7.2).toFixed(2) + ''; valEl.textContent = '¥' + remCny.toFixed(2);
valEl.className = 'balance-val ' + cls; valEl.className = 'xp-bal-val' + (cls ? ' ' + cls : '');
} catch(e) { } catch(e) {
valEl.textContent = '查询失败' + e.message + ''; valEl.textContent = '查询失败';
valEl.className = 'balance-val low'; valEl.className = 'xp-bal-val dim';
} finally { } finally {
btn.disabled = false; btn.disabled = false;
btn.textContent = '刷新余额';
} }
} }
function getMonthStart() { // ── 二维码 ─────────────────────────────────────────────
const d = new Date();
return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-01';
}
// ── 二维码 ──────────────────────────────────────────────
async function loadQrCodes() { async function loadQrCodes() {
try { try {
const r = await fetch(RECHARGE_API + '/config', {signal: AbortSignal.timeout(3000)}); const r = await fetch(RECHARGE_API + '/config', {signal: AbortSignal.timeout(3000)});
@@ -552,19 +545,15 @@ async function loadQrCodes() {
if (cfg.qr_alipay) showQrImg('alipay', cfg.qr_alipay); if (cfg.qr_alipay) showQrImg('alipay', cfg.qr_alipay);
if (cfg.qr_wechat) showQrImg('wechat', cfg.qr_wechat); if (cfg.qr_wechat) showQrImg('wechat', cfg.qr_wechat);
} }
} catch(e) { } catch(e) {}
// 服务器未部署时静默失败,用静态配置兜底
if (QR_ALIPAY) showQrImg('alipay', QR_ALIPAY);
if (QR_WECHAT) showQrImg('wechat', QR_WECHAT);
}
} }
function showQrImg(type, src) { function showQrImg(type, src) {
const img = document.getElementById('qr-' + type + '-img'); const img = document.getElementById('qr-' + type + '-img');
const placeholder = document.getElementById('qr-' + type + '-placeholder'); const ph = document.getElementById('qr-' + type + '-ph');
img.src = src; img.src = src;
img.style.display = 'block'; img.style.display = 'block';
placeholder.style.display = 'none'; ph.style.display = 'none';
} }
function switchQr(type, btn) { function switchQr(type, btn) {
@@ -574,111 +563,100 @@ function switchQr(type, btn) {
document.getElementById('qr-' + type).classList.add('active'); document.getElementById('qr-' + type).classList.add('active');
} }
// ── 金额选择 ───────────────────────────────────────────── // ── 金额选择 ─────────────────────────────────────────────
function selectAmount(amt) { function selectAmt(amt) {
document.querySelectorAll('.amount-btn').forEach(b => b.classList.remove('selected')); document.querySelectorAll('.amt-btn').forEach(b => b.classList.remove('sel'));
document.querySelector(`.amount-btn[data-amt="${amt}"]`).classList.add('selected'); document.querySelector(`.amt-btn[data-amt="${amt}"]`).classList.add('sel');
selectedAmount = amt; selectedAmt = amt;
document.getElementById('customWrap').style.display = amt === 0 ? 'block' : 'none'; document.getElementById('customWrap').style.display = amt === 0 ? 'block' : 'none';
if (amt !== 0) document.getElementById('customAmt').value = ''; if (amt !== 0) document.getElementById('customAmt').value = '';
} }
function onCustomInput() { function onCustomInput() {
const v = parseFloat(document.getElementById('customAmt').value) || 0; selectedAmt = parseFloat(document.getElementById('customAmt').value) || 0;
selectedAmount = v;
} }
function getEffectiveAmount() { function getEffectiveAmt() {
if (selectedAmount === 0) { if (selectedAmt === 0) return parseFloat(document.getElementById('customAmt').value) || 0;
return parseFloat(document.getElementById('customAmt').value) || 0; return selectedAmt;
}
return selectedAmount;
} }
// ── 截图上传 ───────────────────────────────────────────── // ── 截图上传 ─────────────────────────────────────────────
function onFileSelect(e) { function onFileSelect(e) {
const file = e.target.files[0]; const file = e.target.files[0];
if (!file) return; if (!file) return;
if (file.size > 5 * 1024 * 1024) { if (file.size > 5 * 1024 * 1024) { showToast('图片不超过5MB', 'error'); return; }
showToast('图片不超过5MB', 'error'); return;
}
screenshotMime = file.type || 'image/jpeg'; screenshotMime = file.type || 'image/jpeg';
const reader = new FileReader(); const reader = new FileReader();
reader.onload = ev => { reader.onload = ev => {
const dataUrl = ev.target.result; const dataUrl = ev.target.result;
screenshotB64 = dataUrl.split(',')[1]; screenshotB64 = dataUrl.split(',')[1];
// 预览
const preview = document.getElementById('uploadPreview'); const preview = document.getElementById('uploadPreview');
preview.src = dataUrl; preview.src = dataUrl;
preview.style.display = 'block'; preview.style.display = 'block';
document.getElementById('uploadPlaceholder').style.display = 'none'; document.getElementById('uploadPh').style.display = 'none';
document.getElementById('uploadArea').classList.add('has-file'); document.getElementById('uploadArea').classList.add('has');
}; };
reader.readAsDataURL(file); reader.readAsDataURL(file);
} }
// ── 提交 ───────────────────────────────────────────── // ── 提交 ─────────────────────────────────────────────
async function submitRecharge() { async function submitRecharge() {
if (!currentKey) { showToast('请先输入您的 API Key', 'error'); return; } if (!currentKey) { showToast('请先输入您的 API Key', 'error'); return; }
const amount = getEffectiveAmt();
const amount = getEffectiveAmount();
if (amount < 10) { showToast('充值金额最低 ¥10', 'error'); return; } if (amount < 10) { showToast('充值金额最低 ¥10', 'error'); return; }
// 截图可选,不强制
const btn = document.getElementById('submitBtn'); const btn = document.getElementById('submitBtn');
btn.disabled = true; btn.disabled = true;
btn.textContent = '提交中...'; btn.textContent = '提交中...';
try { try {
const payload = { const res = await fetch(RECHARGE_API + '/submit', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
api_key: currentKey, api_key: currentKey,
amount_cny: amount, amount_cny: amount,
screenshot_b64: screenshotB64, screenshot_b64: screenshotB64,
screenshot_mime: screenshotMime, screenshot_mime: screenshotMime,
note: document.getElementById('noteInput').value.trim() note: document.getElementById('noteInput').value.trim()
}; })
const res = await fetch(RECHARGE_API + '/submit', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload)
}); });
const data = await res.json(); const data = await res.json();
if (!res.ok) throw new Error(data.error || '服务器错误'); if (!res.ok) throw new Error(data.error || '服务器错误');
// 成功
document.getElementById('mainSection').classList.remove('active'); document.getElementById('mainSection').classList.remove('active');
document.getElementById('successSection').classList.add('active'); document.getElementById('successSection').classList.add('active');
} catch(e) { } catch(e) {
showToast('提交失败:' + e.message, 'error'); showToast('提交失败:' + e.message, 'error');
btn.disabled = false; btn.disabled = false;
btn.textContent = '提交充值申请'; btn.textContent = '提交充值申请';
} }
} }
function goBack() { function goBack() {
document.getElementById('successSection').classList.remove('active'); document.getElementById('successSection').classList.remove('active');
document.getElementById('mainSection').classList.add('active'); document.getElementById('mainSection').classList.add('active');
// 重置表单
screenshotB64 = ''; screenshotB64 = '';
document.getElementById('uploadPreview').style.display = 'none'; document.getElementById('uploadPreview').style.display = 'none';
document.getElementById('uploadPlaceholder').style.display = 'block'; document.getElementById('uploadPh').style.display = 'block';
document.getElementById('uploadArea').classList.remove('has-file'); document.getElementById('uploadArea').classList.remove('has');
document.getElementById('screenshotInput').value = ''; document.getElementById('screenshotInput').value = '';
document.getElementById('noteInput').value = ''; document.getElementById('noteInput').value = '';
document.querySelectorAll('.amount-btn').forEach(b => b.classList.remove('selected')); document.querySelectorAll('.amt-btn').forEach(b => b.classList.remove('sel'));
document.getElementById('customWrap').style.display = 'none'; document.getElementById('customWrap').style.display = 'none';
document.getElementById('submitBtn').disabled = false; document.getElementById('submitBtn').disabled = false;
document.getElementById('submitBtn').textContent = '提交充值申请'; document.getElementById('submitBtn').textContent = '提交充值申请';
selectedAmt = -1;
loadBalance(); loadBalance();
} }
// ── 工具 ───────────────────────────────────────────── // ── 工具 ─────────────────────────────────────────────
function copyKey() { function copyKey() {
if (!currentKey) return; if (!currentKey) return;
navigator.clipboard.writeText(currentKey).then(() => showToast('Key 已复制')).catch(() => { navigator.clipboard.writeText(currentKey)
.then(() => showToast('Key 已复制'))
.catch(() => {
const el = document.createElement('textarea'); const el = document.createElement('textarea');
el.value = currentKey; el.value = currentKey;
document.body.appendChild(el); document.body.appendChild(el);