Merge client_id+token into credential popup, add refund button to actions
- Merge client_id and token columns into single "credential" button - Click to view in modal with copy buttons for each - Add refund toggle button in actions row with confirm dialog - Remove separate refund_received column, cleaner layout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,6 +131,29 @@ class MailManager {
|
||||
}
|
||||
});
|
||||
|
||||
// 凭证弹窗事件
|
||||
document.getElementById('closeCredentialBtn').addEventListener('click', () => {
|
||||
document.getElementById('credentialModal').classList.remove('show');
|
||||
});
|
||||
document.getElementById('credentialModal').addEventListener('click', (e) => {
|
||||
if (e.target === e.currentTarget) e.currentTarget.classList.remove('show');
|
||||
});
|
||||
document.getElementById('copyCredClientIdBtn').addEventListener('click', () => {
|
||||
this.copyToClipboard(document.getElementById('credClientId').textContent);
|
||||
});
|
||||
document.getElementById('copyCredTokenBtn').addEventListener('click', () => {
|
||||
this.copyToClipboard(document.getElementById('credToken').textContent);
|
||||
});
|
||||
|
||||
// 凭证查看按钮 — 事件委托
|
||||
document.getElementById('accountTableBody').addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.credential-btn');
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.showCredentialModal(btn.dataset.credEmail);
|
||||
});
|
||||
|
||||
// 退款到账按钮 — 事件委托
|
||||
document.getElementById('accountTableBody').addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.refund-received-btn');
|
||||
@@ -257,7 +280,7 @@ class MailManager {
|
||||
|
||||
async loadAccounts() {
|
||||
const tbody = document.getElementById('accountTableBody');
|
||||
tbody.innerHTML = `<tr><td colspan="14"><div class="table-loading"><div class="spinner-border spinner-border-sm"></div> 加载中...</div></td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="12"><div class="table-loading"><div class="spinner-border spinner-border-sm"></div> 加载中...</div></td></tr>`;
|
||||
|
||||
try {
|
||||
// 有筛选时加载全部数据,否则分页加载
|
||||
@@ -277,11 +300,11 @@ class MailManager {
|
||||
await this.loadClaudePaymentStatuses();
|
||||
this.applyFilterAndRender();
|
||||
} else {
|
||||
tbody.innerHTML = `<tr><td colspan="14"><div class="no-data"><i class="bi bi-exclamation-circle"></i><div>${this.escapeHtml(result.message || '加载失败')}</div></div></td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="12"><div class="no-data"><i class="bi bi-exclamation-circle"></i><div>${this.escapeHtml(result.message || '加载失败')}</div></div></td></tr>`;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载账号失败:', err);
|
||||
tbody.innerHTML = `<tr><td colspan="14"><div class="no-data"><i class="bi bi-wifi-off"></i><div>网络错误</div></div></td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="12"><div class="no-data"><i class="bi bi-wifi-off"></i><div>网络错误</div></div></td></tr>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +339,7 @@ class MailManager {
|
||||
renderAccounts() {
|
||||
const tbody = document.getElementById('accountTableBody');
|
||||
if (!this.accounts.length) {
|
||||
tbody.innerHTML = `<tr><td colspan="14"><div class="no-data"><i class="bi bi-inbox"></i><div>暂无邮箱数据</div></div></td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="12"><div class="no-data"><i class="bi bi-inbox"></i><div>暂无邮箱数据</div></div></td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -347,17 +370,8 @@ class MailManager {
|
||||
${pwd ? `<button class="copy-icon-btn" data-copy-field="pwd" data-copy-key="${this.escapeHtml(email)}" title="复制"><i class="bi bi-clipboard"></i></button>` : ''}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-hide-mobile">
|
||||
<div class="value-container">
|
||||
<span class="value-text value-secret" title="${this.escapeHtml(cid)}">${this.truncate(cid, 16)}</span>
|
||||
${cid ? `<button class="copy-icon-btn" data-copy-field="cid" data-copy-key="${this.escapeHtml(email)}" title="复制"><i class="bi bi-clipboard"></i></button>` : ''}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="value-container">
|
||||
<span class="value-text value-secret" title="点击复制">${token ? this.truncate(token, 20) : '-'}</span>
|
||||
${token ? `<button class="copy-icon-btn" data-copy-field="token" data-copy-key="${this.escapeHtml(email)}" title="复制"><i class="bi bi-clipboard"></i></button>` : ''}
|
||||
</div>
|
||||
<button class="note-cell-btn credential-btn" data-cred-email="${this.escapeHtml(email)}"><i class="bi bi-key"></i> 查看</button>
|
||||
</td>
|
||||
${this.renderClaudeColumns(email)}
|
||||
<td>
|
||||
@@ -365,6 +379,7 @@ class MailManager {
|
||||
<button class="view" onclick="app.openMailbox('${this.escapeHtml(email)}', 'INBOX')">收件箱</button>
|
||||
<button class="view" onclick="app.openMailbox('${this.escapeHtml(email)}', 'Junk')">垃圾箱</button>
|
||||
<button class="view claude-check-btn" onclick="app.checkSingleClaudePayment('${this.escapeHtml(email)}', this)">Claude</button>
|
||||
${this.renderRefundBtn(email)}
|
||||
<button class="delete" onclick="app.deleteAccount('${this.escapeHtml(email)}')">删除</button>
|
||||
</div>
|
||||
</td>
|
||||
@@ -705,6 +720,39 @@ class MailManager {
|
||||
// Claude 支付检测
|
||||
// ====================================================================
|
||||
|
||||
renderRefundBtn(email) {
|
||||
const info = this.claudePaymentStatuses[email];
|
||||
const isReceived = info && info.refund_received === '1';
|
||||
if (isReceived) {
|
||||
return `<button class="view" style="background:rgba(16,185,129,0.1);color:#059669;border-color:rgba(16,185,129,0.15);" onclick="app.confirmRefundToggle('${this.escapeHtml(email)}')">已到账</button>`;
|
||||
}
|
||||
return `<button class="view" onclick="app.confirmRefundToggle('${this.escapeHtml(email)}')">退款</button>`;
|
||||
}
|
||||
|
||||
confirmRefundToggle(email) {
|
||||
const info = this.claudePaymentStatuses[email];
|
||||
const isReceived = info && info.refund_received === '1';
|
||||
const msg = isReceived
|
||||
? `确定将 ${email} 的退款状态改为【未到账】吗?`
|
||||
: `确定将 ${email} 标记为【退款已到账】吗?`;
|
||||
if (confirm(msg)) {
|
||||
this.toggleRefundReceived(email);
|
||||
}
|
||||
}
|
||||
|
||||
showCredentialModal(email) {
|
||||
const data = this._accountDataMap[email];
|
||||
if (!data) return;
|
||||
const cid = data.cid || '-';
|
||||
const token = data.token || '-';
|
||||
// 复用 paste-modal 样式
|
||||
const modal = document.getElementById('credentialModal');
|
||||
document.getElementById('credModalEmail').textContent = email;
|
||||
document.getElementById('credClientId').textContent = cid;
|
||||
document.getElementById('credToken').textContent = token;
|
||||
modal.classList.add('show');
|
||||
}
|
||||
|
||||
async toggleRefundReceived(email) {
|
||||
try {
|
||||
const resp = await fetch(`/api/tools/refund-received/${encodeURIComponent(email)}`, { method: 'POST' });
|
||||
@@ -739,7 +787,6 @@ class MailManager {
|
||||
if (!info) {
|
||||
return `<td><span class="claude-badge claude-unknown">未检测</span></td>
|
||||
<td><span class="claude-badge claude-unknown">未检测</span></td>
|
||||
<td>-</td>
|
||||
<td class="claude-time">-</td>
|
||||
<td class="claude-time">-</td>
|
||||
<td class="claude-time">-</td>
|
||||
@@ -777,12 +824,8 @@ class MailManager {
|
||||
? `<span class="claude-badge claude-suspended">${fmtTime(info.suspended_time)}</span>`
|
||||
: '-';
|
||||
|
||||
const isRefundReceived = info.refund_received === '1';
|
||||
const refundReceivedBtn = `<button class="claude-badge ${isRefundReceived ? 'claude-paid' : 'claude-unknown'} refund-received-btn" data-email="${this.escapeHtml(email)}" style="cursor:pointer;border:none;" title="点击切换">${isRefundReceived ? '已到账' : '未到账'}</button>`;
|
||||
|
||||
return `<td>${paidBadge}</td>
|
||||
<td>${refundBadge}</td>
|
||||
<td>${refundReceivedBtn}</td>
|
||||
<td class="claude-time">${fmtTime(info.payment_time)}</td>
|
||||
<td class="claude-time">${fmtTime(info.refund_time)}</td>
|
||||
<td>${suspendedHtml}</td>
|
||||
|
||||
Reference in New Issue
Block a user