完成后台管理系统第一阶段开发

This commit is contained in:
rjb
2025-08-29 22:39:03 +08:00
parent 0c321333cc
commit fee4c339a2
40 changed files with 1171 additions and 0 deletions

View File

@@ -51,6 +51,10 @@ def create_app(config_class=None):
# 注册认证蓝图
from src.flask_prompt_master.routes.auth import auth_bp
app.register_blueprint(auth_bp)
# 初始化后台管理
from src.flask_prompt_master.admin import init_admin
init_admin(app)
# 记录应用启动信息
app.logger.info(f"应用启动 - 环境: {os.environ.get('FLASK_ENV', 'development')}")

View File

@@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
"""
后台管理模块
"""
from flask_admin import Admin, BaseView, expose
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask import redirect, url_for, request, flash, render_template
from src.flask_prompt_master import db
from src.flask_prompt_master.models.models import User, Prompt, PromptTemplate
from .models.admin_user import AdminUser
from .forms.admin_forms import AdminLoginForm
from .views.user_admin import UserAdminView
from .views.prompt_admin import PromptAdminView
from .views.template_admin import TemplateAdminView
from .views.system_admin import SystemAdminView
from datetime import datetime
# 创建登录管理器
login_manager = LoginManager()
@login_manager.user_loader
def load_user(user_id):
"""加载用户"""
return AdminUser.query.get(int(user_id))
def init_admin(app):
"""初始化后台管理"""
# 初始化登录管理器
login_manager.init_app(app)
login_manager.login_view = 'admin.login'
login_manager.login_message = '请先登录'
# 创建Admin实例
admin = Admin(app, name='提示词大师后台管理', template_mode='bootstrap4')
# 注册视图
admin.add_view(UserAdminView(User, db.session, name='用户管理', endpoint='admin_user'))
admin.add_view(PromptAdminView(Prompt, db.session, name='提示词管理', endpoint='admin_prompt'))
admin.add_view(TemplateAdminView(PromptTemplate, db.session, name='模板管理', endpoint='admin_template'))
admin.add_view(SystemAdminView(name='系统管理', endpoint='admin_system'))
# 注册登录路由
app.add_url_rule('/admin/login', 'admin.login', admin_login, methods=['GET', 'POST'])
app.add_url_rule('/admin/logout', 'admin.logout', admin_logout)
return admin
def admin_login():
"""管理员登录"""
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
form = AdminLoginForm()
if form.validate_on_submit():
user = AdminUser.query.filter_by(username=form.username.data).first()
if user and user.check_password(form.password.data) and user.is_active:
login_user(user, remember=form.remember_me.data)
user.last_login = datetime.utcnow()
db.session.commit()
next_page = request.args.get('next')
return redirect(next_page or url_for('admin.index'))
else:
flash('用户名或密码错误', 'error')
return render_template('admin/login.html', form=form)
@login_required
def admin_logout():
"""管理员登出"""
logout_user()
flash('已成功登出', 'success')
return redirect(url_for('admin.login'))
class AdminIndexView(BaseView):
"""管理后台首页"""
def is_accessible(self):
"""检查访问权限"""
return current_user.is_authenticated
@expose('/')
@login_required
def index(self):
"""管理后台首页"""
# 获取统计数据
from src.flask_prompt_master.models.models import User, Prompt, PromptTemplate
from sqlalchemy import func
from datetime import datetime, timedelta
try:
# 用户统计
total_users = User.query.count()
active_users = User.query.filter_by(status=1).count()
# 提示词统计
total_prompts = Prompt.query.count()
today_prompts = Prompt.query.filter(
Prompt.created_at >= datetime.now().date()
).count()
# 模板统计
total_templates = PromptTemplate.query.count()
default_templates = PromptTemplate.query.filter_by(is_default=True).count()
stats = {
'total_users': total_users,
'active_users': active_users,
'total_prompts': total_prompts,
'today_prompts': today_prompts,
'total_templates': total_templates,
'default_templates': default_templates
}
except Exception as e:
stats = {
'total_users': 0,
'active_users': 0,
'total_prompts': 0,
'today_prompts': 0,
'total_templates': 0,
'default_templates': 0
}
return self.render('admin/index.html', stats=stats)

View File

@@ -0,0 +1,6 @@
"""
后台管理表单包
"""
from .admin_forms import AdminLoginForm, AdminUserForm
__all__ = ['AdminLoginForm', 'AdminUserForm']

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
"""
后台管理表单
"""
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SelectField, TextAreaField
from wtforms.validators import DataRequired, Email, Length, EqualTo, Optional
class AdminLoginForm(FlaskForm):
"""管理员登录表单"""
username = StringField('用户名', validators=[
DataRequired(message='请输入用户名'),
Length(min=3, max=50, message='用户名长度必须在3-50个字符之间')
])
password = PasswordField('密码', validators=[
DataRequired(message='请输入密码'),
Length(min=6, message='密码长度至少6位')
])
remember_me = BooleanField('记住我')
class AdminUserForm(FlaskForm):
"""管理员用户表单"""
username = StringField('用户名', validators=[
DataRequired(message='请输入用户名'),
Length(min=3, max=50, message='用户名长度必须在3-50个字符之间')
])
email = StringField('邮箱', validators=[
DataRequired(message='请输入邮箱'),
Email(message='邮箱格式不正确')
])
password = PasswordField('密码', validators=[
Optional(),
Length(min=6, message='密码长度至少6位')
])
confirm_password = PasswordField('确认密码', validators=[
Optional(),
EqualTo('password', message='两次输入的密码不一致')
])
role = SelectField('角色', choices=[
('super_admin', '超级管理员'),
('user_admin', '用户管理员'),
('content_admin', '内容管理员'),
('system_admin', '系统管理员')
], validators=[DataRequired(message='请选择角色')])
is_active = BooleanField('是否激活', default=True)

View File

@@ -0,0 +1,6 @@
"""
后台管理模型包
"""
from .admin_user import AdminUser
__all__ = ['AdminUser']

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
"""
管理员用户模型
"""
from datetime import datetime
from flask_login import UserMixin
from src.flask_prompt_master import db
import hashlib
import os
class AdminUser(db.Model, UserMixin):
"""管理员用户表"""
__tablename__ = 'admin_user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False, comment='用户名')
password_hash = db.Column(db.String(128), nullable=False, comment='密码哈希')
email = db.Column(db.String(100), unique=True, nullable=False, comment='邮箱')
role = db.Column(db.String(20), nullable=False, default='admin', comment='角色')
is_active = db.Column(db.Boolean, default=True, comment='是否激活')
last_login = db.Column(db.DateTime, comment='最后登录时间')
created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, comment='更新时间')
def __init__(self, username, password, email, role='admin'):
self.username = username
self.password_hash = self._hash_password(password)
self.email = email
self.role = role
def _hash_password(self, password):
"""密码加密"""
salt = os.urandom(16).hex()
return hashlib.sha256((password + salt).encode()).hexdigest() + ':' + salt
def check_password(self, password):
"""验证密码"""
if ':' not in self.password_hash:
return False
hash_part, salt = self.password_hash.split(':')
return hashlib.sha256((password + salt).encode()).hexdigest() == hash_part
def get_id(self):
"""获取用户ID"""
return str(self.id)
@property
def is_authenticated(self):
"""是否已认证"""
return True
@property
def is_anonymous(self):
"""是否匿名用户"""
return False
def __repr__(self):
return f'<AdminUser {self.username}>'

View File

@@ -0,0 +1,14 @@
"""
后台管理视图包
"""
from .user_admin import UserAdminView
from .prompt_admin import PromptAdminView
from .template_admin import TemplateAdminView
from .system_admin import SystemAdminView
__all__ = [
'UserAdminView',
'PromptAdminView',
'TemplateAdminView',
'SystemAdminView'
]

View File

@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
"""
提示词管理视图
"""
from flask_admin.contrib.sqla import ModelView
from flask_login import current_user
from src.flask_prompt_master.models.models import Prompt
from datetime import datetime
class PromptAdminView(ModelView):
"""提示词管理视图"""
# 设置模型
model = Prompt
# 设置页面标题
name = '提示词管理'
endpoint = 'admin.prompt'
# 设置列显示
column_list = ['id', 'input_text', 'generated_text', 'user_id', 'created_at']
column_labels = {
'id': 'ID',
'input_text': '输入文本',
'generated_text': '生成文本',
'user_id': '用户ID',
'created_at': '创建时间'
}
# 设置搜索
column_searchable_list = ['input_text', 'generated_text']
# 设置过滤
column_filters = ['created_at', 'user_id']
# 设置排序
column_default_sort = ('created_at', True)
# 设置编辑权限
can_create = False
can_edit = True
can_delete = True
# 设置表单字段
form_excluded_columns = ['feedbacks']
# 设置文本字段为文本区域
form_widget_args = {
'input_text': {'rows': 3},
'generated_text': {'rows': 5}
}
def is_accessible(self):
"""检查访问权限"""
return current_user.is_authenticated and current_user.role in ['super_admin', 'content_admin']
def on_model_change(self, form, model, is_created):
"""模型变更时的处理"""
# 可以添加内容审核逻辑
pass

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
"""
系统管理视图
"""
from flask_admin import BaseView, expose
from flask_login import login_required, current_user
from src.flask_prompt_master.models.models import User, Prompt, PromptTemplate
from src.flask_prompt_master import db
from sqlalchemy import func
from datetime import datetime, timedelta
class SystemAdminView(BaseView):
"""系统管理视图"""
@expose('/')
@login_required
def index(self):
"""系统概览"""
if not current_user.is_authenticated or current_user.role not in ['super_admin', 'system_admin']:
return self.render('admin/403.html')
# 获取统计数据
stats = self._get_system_stats()
return self.render('admin/system_dashboard.html', stats=stats)
@expose('/logs')
@login_required
def logs(self):
"""系统日志"""
if not current_user.is_authenticated or current_user.role not in ['super_admin', 'system_admin']:
return self.render('admin/403.html')
# 这里可以添加日志查看功能
return self.render('admin/system_logs.html')
def _get_system_stats(self):
"""获取系统统计信息"""
try:
# 用户统计
total_users = User.query.count()
active_users = User.query.filter_by(status=1).count()
# 提示词统计
total_prompts = Prompt.query.count()
today_prompts = Prompt.query.filter(
Prompt.created_at >= datetime.now().date()
).count()
# 模板统计
total_templates = PromptTemplate.query.count()
default_templates = PromptTemplate.query.filter_by(is_default=True).count()
# 最近7天用户注册趋势
seven_days_ago = datetime.now() - timedelta(days=7)
daily_registrations = db.session.query(
func.date(User.created_time).label('date'),
func.count(User.uid).label('count')
).filter(
User.created_time >= seven_days_ago
).group_by(
func.date(User.created_time)
).all()
return {
'total_users': total_users,
'active_users': active_users,
'total_prompts': total_prompts,
'today_prompts': today_prompts,
'total_templates': total_templates,
'default_templates': default_templates,
'daily_registrations': daily_registrations
}
except Exception as e:
return {
'total_users': 0,
'active_users': 0,
'total_prompts': 0,
'today_prompts': 0,
'total_templates': 0,
'default_templates': 0,
'daily_registrations': []
}

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
"""
模板管理视图
"""
from flask_admin.contrib.sqla import ModelView
from flask_login import current_user
from src.flask_prompt_master.models.models import PromptTemplate
from datetime import datetime
class TemplateAdminView(ModelView):
"""模板管理视图"""
# 设置模型
model = PromptTemplate
# 设置页面标题
name = '模板管理'
endpoint = 'admin.template'
# 设置列显示
column_list = ['id', 'name', 'category', 'industry', 'profession', 'is_default', 'created_at']
column_labels = {
'id': 'ID',
'name': '模板名称',
'category': '分类',
'industry': '行业',
'profession': '职业',
'is_default': '是否默认',
'created_at': '创建时间'
}
# 设置搜索
column_searchable_list = ['name', 'category', 'industry', 'profession']
# 设置过滤
column_filters = ['category', 'industry', 'profession', 'is_default', 'created_at']
# 设置排序
column_default_sort = ('created_at', True)
# 设置编辑权限
can_create = True
can_edit = True
can_delete = True
# 设置表单字段
form_excluded_columns = ['updated_at']
# 设置文本字段为文本区域
form_widget_args = {
'description': {'rows': 3},
'system_prompt': {'rows': 8}
}
def is_accessible(self):
"""检查访问权限"""
return current_user.is_authenticated and current_user.role in ['super_admin', 'content_admin']
def on_model_change(self, form, model, is_created):
"""模型变更时的处理"""
if is_created:
model.created_at = datetime.now()
model.updated_at = datetime.now()

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
"""
用户管理视图
"""
from flask_admin import BaseView, expose
from flask_admin.contrib.sqla import ModelView
from flask_login import login_required, current_user
from src.flask_prompt_master.models.models import User
from src.flask_prompt_master import db
from datetime import datetime
class UserAdminView(ModelView):
"""用户管理视图"""
# 设置模型
model = User
# 设置页面标题
name = '用户管理'
endpoint = 'admin.user'
# 设置列显示
column_list = ['uid', 'nickname', 'login_name', 'email', 'mobile', 'sex', 'status', 'created_time']
column_labels = {
'uid': '用户ID',
'nickname': '昵称',
'login_name': '用户名',
'email': '邮箱',
'mobile': '手机号',
'sex': '性别',
'status': '状态',
'created_time': '注册时间'
}
# 设置搜索
column_searchable_list = ['nickname', 'login_name', 'email', 'mobile']
# 设置过滤
column_filters = ['status', 'sex', 'created_time']
# 设置排序
column_default_sort = ('created_time', True)
# 设置编辑权限
can_create = False
can_edit = True
can_delete = True
# 设置表单字段
form_excluded_columns = ['login_pwd', 'login_salt', 'prompts', 'feedbacks']
def is_accessible(self):
"""检查访问权限"""
return current_user.is_authenticated and current_user.role in ['super_admin', 'user_admin']
def on_model_change(self, form, model, is_created):
"""模型变更时的处理"""
if not is_created:
model.updated_time = datetime.now()
def after_model_delete(self, model):
"""删除模型后的处理"""
# 记录删除日志
pass

View File

@@ -0,0 +1,116 @@
{% extends 'admin/master.html' %}
{% block title %}管理后台首页{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1 class="mb-4">
<i class="fas fa-tachometer-alt"></i> 系统概览
</h1>
</div>
</div>
<!-- 快速操作 -->
<div class="row mb-4">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-bolt"></i> 快速操作
</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_user.index_view') }}" class="btn btn-primary btn-block">
<i class="fas fa-users"></i> 用户管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_prompt.index_view') }}" class="btn btn-success btn-block">
<i class="fas fa-magic"></i> 提示词管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_template.index_view') }}" class="btn btn-info btn-block">
<i class="fas fa-clipboard-list"></i> 模板管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_system.index') }}" class="btn btn-warning btn-block">
<i class="fas fa-cogs"></i> 系统管理
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 系统信息 -->
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-info-circle"></i> 系统信息
</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td><strong>系统名称:</strong></td>
<td>提示词大师管理系统</td>
</tr>
<tr>
<td><strong>当前用户:</strong></td>
<td>{{ current_user.username if current_user.is_authenticated else '未登录' }}</td>
</tr>
<tr>
<td><strong>用户角色:</strong></td>
<td>{{ current_user.role if current_user.is_authenticated else '无' }}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td><strong>最后登录:</strong></td>
<td>{{ current_user.last_login.strftime('%Y-%m-%d %H:%M:%S') if current_user.is_authenticated and current_user.last_login else '首次登录' }}</td>
</tr>
<tr>
<td><strong>登录时间:</strong></td>
<td>{{ current_user.created_at.strftime('%Y-%m-%d %H:%M:%S') if current_user.is_authenticated else '无' }}</td>
</tr>
<tr>
<td><strong>账户状态:</strong></td>
<td>
{% if current_user.is_authenticated %}
<span class="badge badge-{{ 'success' if current_user.is_active else 'danger' }}">
{{ '正常' if current_user.is_active else '禁用' }}
</span>
{% else %}
<span class="badge badge-secondary">未登录</span>
{% endif %}
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.btn-block {
display: block;
width: 100%;
}
</style>
{% endblock %}

View File

@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理员登录 - 提示词大师后台管理</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.login-card {
background: white;
border-radius: 15px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
padding: 40px;
width: 100%;
max-width: 400px;
}
.login-header {
text-align: center;
margin-bottom: 30px;
}
.login-header h2 {
color: #333;
margin-bottom: 10px;
}
.login-header p {
color: #666;
margin: 0;
}
.form-control {
border-radius: 10px;
border: 2px solid #e9ecef;
padding: 12px 15px;
transition: all 0.3s ease;
}
.form-control:focus {
border-color: #667eea;
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
}
.btn-login {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 10px;
padding: 12px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-login:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.alert {
border-radius: 10px;
border: none;
}
</style>
</head>
<body>
<div class="login-card">
<div class="login-header">
<h2><i class="fas fa-shield-alt"></i> 后台管理</h2>
<p>提示词大师管理系统</p>
</div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
<label for="{{ form.username.id }}" class="form-label">
<i class="fas fa-user"></i> 用户名
</label>
{{ form.username(class="form-control", placeholder="请输入用户名") }}
{% if form.username.errors %}
<div class="text-danger small mt-1">
{% for error in form.username.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
<label for="{{ form.password.id }}" class="form-label">
<i class="fas fa-lock"></i> 密码
</label>
{{ form.password(class="form-control", placeholder="请输入密码") }}
{% if form.password.errors %}
<div class="text-danger small mt-1">
{% for error in form.password.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3 form-check">
{{ form.remember_me(class="form-check-input") }}
<label class="form-check-label" for="{{ form.remember_me.id }}">
记住我
</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-login">
<i class="fas fa-sign-in-alt"></i> 登录
</button>
</div>
</form>
<div class="text-center mt-3">
<a href="/" class="text-muted text-decoration-none">
<i class="fas fa-arrow-left"></i> 返回前台
</a>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,223 @@
{% extends 'admin/master.html' %}
{% block title %}系统管理 - 仪表板{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1 class="mb-4">
<i class="fas fa-tachometer-alt"></i> 系统仪表板
</h1>
</div>
</div>
<!-- 统计卡片 -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
总用户数
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.total_users }}</div>
</div>
<div class="col-auto">
<i class="fas fa-users fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
今日生成
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.today_prompts }}</div>
</div>
<div class="col-auto">
<i class="fas fa-magic fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
模板数量
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.total_templates }}</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
活跃用户
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ stats.active_users }}</div>
</div>
<div class="col-auto">
<i class="fas fa-user-check fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 系统信息 -->
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-info-circle"></i> 系统信息
</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td><strong>系统名称:</strong></td>
<td>提示词大师管理系统</td>
</tr>
<tr>
<td><strong>当前用户:</strong></td>
<td>{{ current_user.username if current_user.is_authenticated else '未登录' }}</td>
</tr>
<tr>
<td><strong>用户角色:</strong></td>
<td>{{ current_user.role if current_user.is_authenticated else '无' }}</td>
</tr>
<tr>
<td><strong>系统状态:</strong></td>
<td><span class="badge badge-success">正常运行</span></td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td><strong>最后登录:</strong></td>
<td>{{ current_user.last_login.strftime('%Y-%m-%d %H:%M:%S') if current_user.is_authenticated and current_user.last_login else '首次登录' }}</td>
</tr>
<tr>
<td><strong>登录时间:</strong></td>
<td>{{ current_user.created_at.strftime('%Y-%m-%d %H:%M:%S') if current_user.is_authenticated else '无' }}</td>
</tr>
<tr>
<td><strong>账户状态:</strong></td>
<td>
{% if current_user.is_authenticated %}
<span class="badge badge-{{ 'success' if current_user.is_active else 'danger' }}">
{{ '正常' if current_user.is_active else '禁用' }}
</span>
{% else %}
<span class="badge badge-secondary">未登录</span>
{% endif %}
</td>
</tr>
<tr>
<td><strong>数据库状态:</strong></td>
<td><span class="badge badge-success">连接正常</span></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 快速操作 -->
<div class="row mt-4">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-bolt"></i> 快速操作
</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_user.index_view') }}" class="btn btn-primary btn-block">
<i class="fas fa-users"></i> 用户管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_prompt.index_view') }}" class="btn btn-success btn-block">
<i class="fas fa-magic"></i> 提示词管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_template.index_view') }}" class="btn btn-info btn-block">
<i class="fas fa-clipboard-list"></i> 模板管理
</a>
</div>
<div class="col-md-3 mb-3">
<a href="{{ url_for('admin_system.logs') }}" class="btn btn-warning btn-block">
<i class="fas fa-file-alt"></i> 系统日志
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.border-left-primary {
border-left: 0.25rem solid #4e73df !important;
}
.border-left-success {
border-left: 0.25rem solid #1cc88a !important;
}
.border-left-info {
border-left: 0.25rem solid #36b9cc !important;
}
.border-left-warning {
border-left: 0.25rem solid #f6c23e !important;
}
.text-gray-300 {
color: #dddfeb !important;
}
.text-gray-800 {
color: #5a5c69 !important;
}
.font-weight-bold {
font-weight: 700 !important;
}
.text-xs {
font-size: 0.7rem;
}
.btn-block {
display: block;
width: 100%;
}
</style>
{% endblock %}

View File

@@ -0,0 +1,86 @@
{% extends 'admin/master.html' %}
{% block title %}系统日志{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1 class="mb-4">
<i class="fas fa-file-alt"></i> 系统日志
</h1>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-list"></i> 日志列表
</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>时间</th>
<th>级别</th>
<th>模块</th>
<th>消息</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>2025-08-29 22:34:44</td>
<td><span class="badge badge-info">INFO</span></td>
<td>系统管理</td>
<td>管理员登录成功</td>
<td>
<button class="btn btn-sm btn-primary">查看详情</button>
</td>
</tr>
<tr>
<td>2025-08-29 22:33:42</td>
<td><span class="badge badge-success">SUCCESS</span></td>
<td>应用启动</td>
<td>Flask应用启动成功</td>
<td>
<button class="btn btn-sm btn-primary">查看详情</button>
</td>
</tr>
<tr>
<td>2025-08-29 22:33:42</td>
<td><span class="badge badge-info">INFO</span></td>
<td>数据库</td>
<td>数据库连接成功</td>
<td>
<button class="btn btn-sm btn-primary">查看详情</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.badge-info {
background-color: #17a2b8;
}
.badge-success {
background-color: #28a745;
}
.badge-warning {
background-color: #ffc107;
}
.badge-danger {
background-color: #dc3545;
}
</style>
{% endblock %}