Add payment status filter dropdown (paid/unpaid/refunded/suspended)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,14 @@
|
||||
<i class="bi bi-credit-card"></i>
|
||||
<span>Claude检测</span>
|
||||
</button>
|
||||
<select class="filter-select" id="paymentFilter" title="支付状态筛选">
|
||||
<option value="">全部状态</option>
|
||||
<option value="paid">已支付</option>
|
||||
<option value="unpaid">未支付</option>
|
||||
<option value="refunded">已退款</option>
|
||||
<option value="suspended">已封号</option>
|
||||
<option value="unchecked">未检测</option>
|
||||
</select>
|
||||
<button class="btn btn-icon" id="refreshAccountsBtn" title="刷新">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
|
||||
@@ -50,6 +50,7 @@ class MailManager {
|
||||
this.messages = [];
|
||||
this.selectedId = null;
|
||||
this.claudePaymentStatuses = {};
|
||||
this.paymentFilter = '';
|
||||
|
||||
this.init();
|
||||
}
|
||||
@@ -104,6 +105,13 @@ class MailManager {
|
||||
// Claude支付检测
|
||||
document.getElementById('claudePaymentBtn').addEventListener('click', () => this.startClaudePaymentCheck());
|
||||
|
||||
// 支付状态筛选
|
||||
document.getElementById('paymentFilter').addEventListener('change', (e) => {
|
||||
this.paymentFilter = e.target.value;
|
||||
this.page = 1;
|
||||
this.loadAccounts();
|
||||
});
|
||||
|
||||
// 刷新
|
||||
document.getElementById('refreshAccountsBtn').addEventListener('click', () => this.loadAccounts());
|
||||
|
||||
@@ -242,22 +250,22 @@ class MailManager {
|
||||
tbody.innerHTML = `<tr><td colspan="13"><div class="table-loading"><div class="spinner-border spinner-border-sm"></div> 加载中...</div></td></tr>`;
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
page: this.page,
|
||||
page_size: this.pageSize
|
||||
});
|
||||
// 有筛选时加载全部数据,否则分页加载
|
||||
const params = new URLSearchParams(
|
||||
this.paymentFilter
|
||||
? { page: 1, page_size: 9999 }
|
||||
: { page: this.page, page_size: this.pageSize }
|
||||
);
|
||||
if (this.query) params.set('q', this.query);
|
||||
|
||||
const resp = await fetch(`/api/accounts/detailed?${params}`);
|
||||
const result = await resp.json();
|
||||
|
||||
if (result.success && result.data) {
|
||||
this.accounts = result.data.items || [];
|
||||
this.total = result.data.total || 0;
|
||||
this.page = result.data.page || 1;
|
||||
this._allAccounts = result.data.items || [];
|
||||
this._allTotal = result.data.total || 0;
|
||||
await this.loadClaudePaymentStatuses();
|
||||
this.renderAccounts();
|
||||
this.renderPager();
|
||||
this.applyFilterAndRender();
|
||||
} else {
|
||||
tbody.innerHTML = `<tr><td colspan="13"><div class="no-data"><i class="bi bi-exclamation-circle"></i><div>${this.escapeHtml(result.message || '加载失败')}</div></div></td></tr>`;
|
||||
}
|
||||
@@ -267,6 +275,32 @@ class MailManager {
|
||||
}
|
||||
}
|
||||
|
||||
_matchPaymentFilter(email) {
|
||||
const info = this.claudePaymentStatuses[email];
|
||||
switch (this.paymentFilter) {
|
||||
case 'paid': return info && !!info.payment_time;
|
||||
case 'unpaid': return !info || !info.payment_time;
|
||||
case 'refunded': return info && !!info.refund_time;
|
||||
case 'suspended': return info && !!info.suspended_time;
|
||||
case 'unchecked': return !info;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
|
||||
applyFilterAndRender() {
|
||||
if (this.paymentFilter) {
|
||||
const filtered = this._allAccounts.filter(acc => this._matchPaymentFilter(acc.email));
|
||||
this.total = filtered.length;
|
||||
const start = (this.page - 1) * this.pageSize;
|
||||
this.accounts = filtered.slice(start, start + this.pageSize);
|
||||
} else {
|
||||
this.accounts = this._allAccounts;
|
||||
this.total = this._allTotal;
|
||||
}
|
||||
this.renderAccounts();
|
||||
this.renderPager();
|
||||
}
|
||||
|
||||
renderAccounts() {
|
||||
const tbody = document.getElementById('accountTableBody');
|
||||
if (!this.accounts.length) {
|
||||
|
||||
@@ -219,6 +219,27 @@ body {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
/* 筛选下拉 */
|
||||
.filter-select {
|
||||
height: 38px;
|
||||
padding: 0 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filter-select:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.search-box input::placeholder { color: #9ca3af; }
|
||||
.search-box input:focus {
|
||||
border-color: #667eea;
|
||||
|
||||
Reference in New Issue
Block a user