Files
socks-manager/templates/proxies.html
T
Your Name aa8af6c2e0 feat: SOCKS5 代理管理系统 v1.0
Flask + SQLite + Bootstrap5 暗色主题
- 仪表盘: 在线/离线统计 + 最近代理 + 操作日志
- 代理 CRUD: 增删改 + 启用/禁用 + 单/批量健康检测(SOCKS5)
- 分组管理: 创建/删除/筛选
- 操作日志: 分页查询
- RESTful API + Web 界面
- 管理员登录认证 (SM_ADMIN_PASSWORD 环境变量)
2026-07-16 16:40:20 +08:00

66 lines
3.1 KiB
HTML

{% extends "base.html" %}
{% block title %}代理列表 · SOCKS Manager{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0"><i class="bi bi-globe"></i> 代理列表</h4>
<div class="d-flex gap-2">
<select class="form-select form-select-sm" id="groupFilter" style="width:180px"
onchange="location.href='/proxies?group='+this.value">
<option value="">全部分组</option>
{% for g in groups %}
<option value="{{ g.id }}" {% if active_group|default('') == g.id|string %}selected{% endif %}>
{{ g.name }}</option>
{% endfor %}
</select>
<a href="/proxies/add" class="btn btn-primary btn-sm"><i class="bi bi-plus-lg"></i> 添加代理</a>
</div>
</div>
<div class="card">
<div class="card-body p-0">
<table class="table table-dark table-hover align-middle mb-0">
<thead><tr><th>名称</th><th>主机</th><th>端口</th><th>认证</th><th>分组</th><th>状态</th><th>延迟</th><th>操作</th></tr></thead>
<tbody>
{% for p in proxies %}
<tr class="{% if not p.enabled %}table-secondary{% endif %}">
<td><a href="/proxies/{{ p.id }}/edit" class="text-decoration-none">{{ p.name }}</a></td>
<td><code>{{ p.host }}</code></td>
<td>{{ p.port }}</td>
<td>{{ '有认证' if p.username else '无' }}</td>
<td>{% if p.group %}<span style="color:{{ p.group.color }}">{{ p.group.name }}</span>{% else %}-{% endif %}</td>
<td><span class="status-dot dot-{{ p.status }}"></span>{{ p.status }}<br><small class="text-muted">{{ p.last_check.strftime('%Y-%m-%d %H:%M') if p.last_check else '未检测' }}</small></td>
<td>{{ "%.1f"|format(p.latency_ms) if p.latency_ms else '-' }}ms</td>
<td>
<div class="btn-group btn-group-sm">
<a href="/proxies/{{ p.id }}/edit" class="btn btn-outline-secondary"><i class="bi bi-pencil"></i></a>
<a href="/proxies/toggle/{{ p.id }}" class="btn btn-outline-{{ 'secondary' if p.enabled else 'success' }}" onclick="return confirm('确认{{ '禁用' if p.enabled else '启用' }}?')">
<i class="bi bi-{{ 'eye-slash' if p.enabled else 'eye' }}"></i></a>
<a href="/proxies/{{ p.id }}" class="btn btn-outline-danger" onclick="return confirm('确认删除?')"><i class="bi bi-trash"></i></a>
<button class="btn btn-outline-info" onclick="checkOne({{ p.id }})"><i class="bi bi-arrow-clockwise"></i></button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if not proxies %}
<div class="text-center py-5 text-muted">暂无代理</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block extra_script %}
<script>
async function checkOne(pid) {
try {
const r = await apiFetch(`/api/proxies/${pid}/check`, {method:'POST'});
toast(`${r.name}: ${r.status}${r.latency_ms? ' ('+r.latency_ms+'ms)':''}`, r.status==='online'?'success':'danger');
location.reload();
} catch(e) { toast('检测失败', 'danger'); }
}
</script>
{% endblock %}