feat: 用户登录/管理 + 操作日志模块

- tb_user 用户表、tb_log 日志表
- Flask-Login 认证(login/logout/权限装饰器)
- 用户管理页(admin 专有):增删改查、改密、角色设置
- 操作日志页:分页查询、按用户/类型筛选
- 测试操作区指令自动记录日志
- 所有页面加 @login_required 保护
- 默认管理员 admin/admin123(首次启动自动创建)
This commit is contained in:
wangfq
2026-05-28 13:58:19 +08:00
parent 56e3b03121
commit 322563dab0
19 changed files with 614 additions and 5 deletions

View File

@@ -236,3 +236,108 @@ def get_automation_averages(dnt_id: int) -> dict:
if row:
return {k: round(v, 2) if v else 0 for k, v in row.items()}
return {}
# ─── 用户管理 ──────────────────────────────────────────────────────
def get_user_by_username(username: str) -> dict | None:
conn = get_conn()
try:
with conn.cursor() as cur:
cur.execute("SELECT * FROM tb_user WHERE username=%s", (username,))
return cur.fetchone()
finally:
conn.close()
def get_all_users() -> list[dict]:
conn = get_conn()
try:
with conn.cursor() as cur:
cur.execute("SELECT id, username, role, is_active, create_time FROM tb_user ORDER BY id")
return cur.fetchall()
finally:
conn.close()
def create_user(username: str, password_hash: str, role: str = "operator"):
conn = get_conn()
try:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO tb_user (username, password_hash, role) VALUES (%s,%s,%s)",
(username, password_hash, role),
)
conn.commit()
finally:
conn.close()
def update_user(user_id: int, password_hash: str = None, role: str = None, is_active: bool = None):
conn = get_conn()
try:
with conn.cursor() as cur:
parts = []
params = []
if password_hash is not None:
parts.append("password_hash=%s")
params.append(password_hash)
if role is not None:
parts.append("role=%s")
params.append(role)
if is_active is not None:
parts.append("is_active=%s")
params.append(int(is_active))
if parts:
params.append(user_id)
cur.execute(f"UPDATE tb_user SET {', '.join(parts)} WHERE id=%s", params)
conn.commit()
finally:
conn.close()
# ─── 日志管理 ──────────────────────────────────────────────────────
def insert_log(user_id: int, username: str, action_type: str,
target: str = "", detail: str = "", result: str = "ok",
ip: str = ""):
conn = get_conn()
try:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO tb_log (user_id, username, action_type, target, detail, result, ip) "
"VALUES (%s,%s,%s,%s,%s,%s,%s)",
(user_id, username, action_type, target, detail, result, ip),
)
conn.commit()
finally:
conn.close()
def get_logs(page: int = 1, per_page: int = 30,
username: str = "", action_type: str = "") -> tuple[list[dict], int]:
conn = get_conn()
try:
with conn.cursor() as cur:
where = []
params = []
if username:
where.append("username LIKE %s")
params.append(f"%{username}%")
if action_type:
where.append("action_type=%s")
params.append(action_type)
where_clause = " AND ".join(where) if where else "1=1"
cur.execute(f"SELECT COUNT(*) as total FROM tb_log WHERE {where_clause}", params)
total = cur.fetchone()["total"]
offset = (page - 1) * per_page
cur.execute(
f"SELECT * FROM tb_log WHERE {where_clause} "
f"ORDER BY id DESC LIMIT %s OFFSET %s",
params + [per_page, offset],
)
return cur.fetchall(), total
finally:
conn.close()