Files
ai-app-database/app/templates/admin/dashboard.html
T
huty f103148ebf feat: 初始化个人资料库 Web 应用
基于 Flask + MySQL + Bootstrap 5 的全栈个人资料库管理系统。

主要功能:
- 管理员/普通用户双角色权限体系,全站登录保护
- 资源管理:文本、图片、音频、视频四类资源
- 三种添加方式:本地上传(拖拽)、URL 后台下载、磁力下载(aria2c)
- 在线预览:文本、图片、HTML5 音视频播放器
- 安全:bcrypt 加盐密码哈希、CSRF 防护、SQLAlchemy ORM 防注入

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 00:16:59 +09:00

133 lines
4.7 KiB
HTML

{% extends 'base.html' %}
{% block title %}管理控制台{% endblock %}
{% block breadcrumb %}
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item active">管理控制台</li>
</ol>
{% endblock %}
{% block content %}
<h4 class="mb-4"><i class="bi bi-speedometer2 me-2"></i>管理控制台</h4>
<!-- 统计卡片 -->
<div class="row g-4 mb-4">
<div class="col-sm-6 col-xl-3">
<div class="card stat-card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center gap-3">
<div class="stat-icon bg-primary-subtle text-primary rounded-3 p-3">
<i class="bi bi-people fs-2"></i>
</div>
<div>
<div class="fs-2 fw-bold">{{ total_users }}</div>
<div class="text-muted small">注册用户</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card stat-card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center gap-3">
<div class="stat-icon bg-success-subtle text-success rounded-3 p-3">
<i class="bi bi-collection fs-2"></i>
</div>
<div>
<div class="fs-2 fw-bold">{{ total_resources }}</div>
<div class="text-muted small">资源总数</div>
</div>
</div>
</div>
</div>
{% for t, label, icon, color in [
('text', '文本', 'file-text', 'secondary'),
('image', '图片', 'image', 'info'),
('audio', '音频', 'music-note-beamed', 'warning'),
('video', '视频', 'camera-video', 'danger'),
] %}
<div class="col-sm-6 col-xl-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center gap-3">
<div class="stat-icon bg-{{ color }}-subtle text-{{ color }} rounded-3 p-3">
<i class="bi bi-{{ icon }} fs-2"></i>
</div>
<div>
<div class="fs-2 fw-bold">{{ type_stats[t] }}</div>
<div class="text-muted small">{{ label }}</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="row g-4">
<!-- 最近用户 -->
<div class="col-lg-5">
<div class="card shadow-sm h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<span><i class="bi bi-person-plus me-1"></i>最近注册用户</span>
<a href="{{ url_for('admin.users') }}" class="btn btn-sm btn-outline-primary">查看全部</a>
</div>
<div class="list-group list-group-flush">
{% for user in recent_users %}
<div class="list-group-item d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center gap-2">
<div class="avatar-circle avatar-sm">{{ user.username[0].upper() }}</div>
<div>
<div class="fw-medium">{{ user.username }}</div>
<div class="text-muted small">{{ user.email }}</div>
</div>
</div>
<div class="text-end">
<span class="badge bg-{{ 'danger' if user.is_admin else 'secondary' }}">
{{ '管理员' if user.is_admin else '用户' }}
</span>
<div class="text-muted small">{{ user.created_at | datetime_fmt }}</div>
</div>
</div>
{% else %}
<div class="list-group-item text-muted text-center py-3">暂无用户</div>
{% endfor %}
</div>
</div>
</div>
<!-- 最近资源 -->
<div class="col-lg-7">
<div class="card shadow-sm h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<span><i class="bi bi-clock-history me-1"></i>最近上传资源</span>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr>
<th>标题</th><th>类型</th><th>用户</th><th>时间</th>
</tr>
</thead>
<tbody>
{% for r in recent_resources %}
<tr>
<td>
<a href="{{ url_for('resources.detail', resource_id=r.id) }}"
class="text-decoration-none text-truncate d-block" style="max-width:200px">
{{ r.title }}
</a>
</td>
<td>
<span class="badge bg-{{ r.type_badge_color }}">{{ r.resource_type }}</span>
</td>
<td class="text-muted small">{{ r.owner.username }}</td>
<td class="text-muted small">{{ r.created_at | datetime_fmt }}</td>
</tr>
{% else %}
<tr><td colspan="4" class="text-center text-muted py-3">暂无资源</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}