Files
weibo_signin/frontend/templates/dashboard.html

298 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}控制台 - 微博超话签到{% endblock %}
{% block extra_css %}
<style>
.dash-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28px;
}
.dash-header h1 {
font-size: 26px;
font-weight: 700;
color: #1e293b;
}
.dash-actions { display: flex; gap: 10px; }
/* 统计卡片 */
.stats-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 28px;
}
.stat-card {
background: rgba(255,255,255,0.9);
backdrop-filter: blur(8px);
border-radius: 20px;
padding: 22px 24px;
border: 1px solid rgba(255,255,255,0.6);
box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.04);
}
.stat-card .stat-icon { font-size: 28px; margin-bottom: 8px; }
.stat-card .stat-value { font-size: 28px; font-weight: 700; color: #1e293b; }
.stat-card .stat-label { font-size: 13px; color: #94a3b8; font-weight: 500; margin-top: 2px; }
/* 账号卡片网格 */
.account-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 18px;
}
.account-card {
background: rgba(255,255,255,0.92);
backdrop-filter: blur(8px);
border-radius: 20px;
padding: 24px;
border: 1px solid rgba(255,255,255,0.6);
box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.04);
cursor: pointer;
transition: all 0.25s ease;
position: relative;
overflow: hidden;
}
.account-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 4px;
border-radius: 20px 20px 0 0;
}
.account-card.status-active::before { background: linear-gradient(90deg, #10b981, #34d399); }
.account-card.status-pending::before { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
.account-card.status-invalid_cookie::before { background: linear-gradient(90deg, #ef4444, #f87171); }
.account-card.status-banned::before { background: linear-gradient(90deg, #6b7280, #9ca3af); }
.account-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(99,102,241,0.12);
}
.account-card-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 14px;
}
.account-avatar {
width: 48px; height: 48px;
border-radius: 16px;
background: linear-gradient(135deg, #6366f1, #a855f7);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
font-weight: 700;
flex-shrink: 0;
}
.account-name {
font-size: 16px;
font-weight: 700;
color: #1e293b;
margin-bottom: 4px;
word-break: break-all;
}
.account-remark {
font-size: 13px;
color: #94a3b8;
margin-bottom: 14px;
}
.account-meta {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 14px;
border-top: 1px solid #f1f5f9;
}
.account-date { font-size: 12px; color: #cbd5e1; }
/* 删除按钮 */
.account-del-btn {
width: 32px; height: 32px;
border-radius: 10px;
border: 1.5px solid #fecaca;
background: #fff;
color: #ef4444;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
flex-shrink: 0;
}
.account-del-btn:hover {
background: #fef2f2;
border-color: #f87171;
}
/* 空状态 */
.empty-state {
text-align: center;
padding: 80px 20px;
background: rgba(255,255,255,0.7);
border-radius: 24px;
border: 2px dashed #e2e8f0;
}
.empty-state .empty-icon { font-size: 56px; margin-bottom: 16px; }
.empty-state p { color: #94a3b8; margin-bottom: 24px; font-size: 16px; }
/* Cookie 批量验证 */
.batch-verify-bar {
background: rgba(255,255,255,0.9);
backdrop-filter: blur(8px);
border-radius: 20px;
padding: 16px 24px;
margin-bottom: 20px;
border: 1px solid rgba(255,255,255,0.6);
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
display: flex;
justify-content: space-between;
align-items: center;
}
.batch-verify-bar .info { font-size: 14px; color: #64748b; }
.batch-verify-bar .info strong { color: #1e293b; }
</style>
{% endblock %}
{% block content %}
<div class="dash-header">
<h1>👋 控制台</h1>
<div class="dash-actions">
<a href="{{ url_for('add_account') }}" class="btn btn-primary">+ 添加账号</a>
</div>
</div>
{% if accounts %}
<!-- 统计概览 -->
<div class="stats-row">
<div class="stat-card">
<div class="stat-icon">📊</div>
<div class="stat-value">{{ accounts|length }}</div>
<div class="stat-label">账号总数</div>
</div>
<div class="stat-card">
<div class="stat-icon"></div>
<div class="stat-value">{{ accounts|selectattr('status','equalto','active')|list|length }}</div>
<div class="stat-label">正常运行</div>
</div>
<div class="stat-card">
<div class="stat-icon">⚠️</div>
<div class="stat-value">{{ accounts|selectattr('status','equalto','pending')|list|length + accounts|selectattr('status','equalto','invalid_cookie')|list|length }}</div>
<div class="stat-label">需要关注</div>
</div>
</div>
<!-- 批量操作栏 -->
<div class="batch-verify-bar">
<div class="info">
💡 系统每天 <strong>23:50</strong> 自动批量验证 Cookie也可手动触发
</div>
<div style="display:flex; gap:10px;">
<button class="btn btn-secondary" id="batch-verify-btn" onclick="batchVerify()">🔍 批量验证 Cookie</button>
<button class="btn btn-primary" id="batch-signin-btn" onclick="batchSignin()">🚀 全部签到</button>
</div>
</div>
<!-- 账号卡片 -->
<div class="account-grid">
{% for account in accounts %}
<div class="account-card status-{{ account.status }}" onclick="window.location.href='{{ url_for('account_detail', account_id=account.id) }}'">
<div class="account-card-top">
<div style="flex:1; min-width:0;">
<div class="account-name">{{ account.remark or account.weibo_user_id }}</div>
<div class="account-remark">UID: {{ account.weibo_user_id }}</div>
</div>
<div class="account-avatar">{{ (account.remark or account.weibo_user_id)[:1] }}</div>
</div>
<div class="account-meta">
<div>
{% if account.status == 'active' %}
<span class="badge badge-success">正常</span>
{% elif account.status == 'pending' %}
<span class="badge badge-warning">待验证</span>
{% elif account.status == 'invalid_cookie' %}
<span class="badge badge-danger">Cookie 失效</span>
{% elif account.status == 'banned' %}
<span class="badge badge-danger">已封禁</span>
{% endif %}
</div>
<div style="display:flex; align-items:center; gap:10px;">
<span class="account-date">{{ account.created_at[:10] }}</span>
<button class="account-del-btn" title="删除账号" onclick="event.stopPropagation(); deleteAccount('{{ account.id }}', '{{ account.remark or account.weibo_user_id }}');">🗑</button>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state">
<div class="empty-icon">📱</div>
<p>暂无账号,扫码添加你的微博账号开始自动签到</p>
<a href="{{ url_for('add_account') }}" class="btn btn-primary" style="font-size:16px; padding:14px 32px;">添加第一个账号</a>
</div>
{% endif %}
<script>
async function deleteAccount(accountId, name) {
if (!confirm(`确定要删除账号「${name}」吗?此操作不可恢复。`)) return;
try {
const form = document.createElement('form');
form.method = 'POST';
form.action = `/accounts/${accountId}/delete`;
document.body.appendChild(form);
form.submit();
} catch(e) {
alert('删除失败: ' + e.message);
}
}
async function batchVerify() {
const btn = document.getElementById('batch-verify-btn');
btn.disabled = true;
btn.textContent = '⏳ 验证中...';
try {
const resp = await fetch('/api/batch/verify', {method: 'POST'});
const data = await resp.json();
if (data.success) {
const r = data.data;
alert(`验证完成:${r.valid} 个有效,${r.invalid} 个失效,${r.errors} 个出错`);
} else {
alert('验证失败: ' + (data.message || '未知错误'));
}
} catch(e) {
alert('请求失败: ' + e.message);
}
btn.disabled = false;
btn.textContent = '🔍 批量验证 Cookie';
location.reload();
}
async function batchSignin() {
const btn = document.getElementById('batch-signin-btn');
if (!confirm('确定要对所有正常账号执行签到吗?')) return;
btn.disabled = true;
btn.textContent = '⏳ 签到中...';
try {
const resp = await fetch('/api/batch/signin', {method: 'POST'});
const data = await resp.json();
if (data.success) {
const r = data.data;
alert(`签到完成:${r.total_accounts} 个账号,${r.total_signed} 成功,${r.total_already} 已签,${r.total_failed} 失败`);
} else {
alert('签到失败: ' + (data.message || '未知错误'));
}
} catch(e) {
alert('请求失败: ' + e.message);
}
btn.disabled = false;
btn.textContent = '🚀 全部签到';
location.reload();
}
</script>
{% endblock %}