Files
QueryCarInfo2/user.py
T
2025-09-17 22:33:49 +08:00

552 lines
20 KiB
Python

import sqlite3
from datetime import datetime
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, session
# 创建用户相关的蓝图
bp = Blueprint('user', __name__)
# 初始化数据库(用户相关部分)
def init_user_db():
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
# 创建用户表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
name TEXT NOT NULL,
phone TEXT NOT NULL,
department TEXT NOT NULL,
status TEXT DEFAULT 'active'
)
''')
# 创建登录信息表
cursor.execute('''
CREATE TABLE IF NOT EXISTS login_info (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
otp_code TEXT
)
''')
# 检查是否存在admin用户,如果不存在则创建
cursor.execute("SELECT * FROM users WHERE username = 'admin'")
if not cursor.fetchone():
# 创建admin用户,默认密码为'admin123'
cursor.execute(
"INSERT INTO users (username, password, name, phone, department) VALUES (?, ?, ?, ?, ?)",
('admin', 'admin123', '管理员', '13800138000', '管理部')
)
# 同时插入到登录信息表
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
('admin', 'admin123', ''))
# 插入一些测试数据
cursor.execute("SELECT COUNT(*) FROM users")
if cursor.fetchone()[0] <= 1: # 只有admin用户时
# 插入几个测试用户
test_users = [
('user1', 'password1', '张三', '13800138001', '技术部'),
('user2', 'password2', '李四', '13800138002', '销售部'),
('user3', 'password3', '王五', '13800138003', '财务部')
]
for user in test_users:
cursor.execute(
"INSERT INTO users (username, password, name, phone, department) VALUES (?, ?, ?, ?, ?)",
user
)
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(user[0], user[1], ''))
conn.commit()
conn.close()
# 登录路由
@bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
# 连接数据库
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
# 验证用户名和密码
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))
user = cursor.fetchone()
if user:
# 检查用户状态
if user[6] != 'active':
conn.close()
return render_template('login.html', error='用户已被禁用')
# 设置会话信息
session['username'] = user[1] # 用户名
session['name'] = user[3] # 姓名
session['department'] = user[5] # 部门
session['login_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 检查是否有login_info记录,如果没有则创建
cursor.execute("SELECT * FROM login_info WHERE username = ?", (username,))
login_info = cursor.fetchone()
if not login_info:
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(username, password, ""))
conn.commit()
# 设置session中的OTP码为空
session['otp_code'] = ""
else:
# 设置session中的OTP码
session['otp_code'] = login_info[3] if login_info[3] else ""
conn.close()
# 登录成功,跳转到查询页面
return redirect(url_for('query'))
else:
conn.close()
return render_template('login.html', error='用户名或密码错误')
return render_template('login.html')
# 注册路由
@bp.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
confirm_password = request.form.get('confirm_password')
name = request.form.get('name')
phone = request.form.get('phone')
department = request.form.get('department')
# 验证参数
if not username or not password or not confirm_password or not name or not phone or not department:
return render_template('register.html', error='请填写所有必填字段')
# 验证密码是否一致
if password != confirm_password:
return render_template('register.html', error='两次输入的密码不一致')
# 验证密码复杂度
if len(password) < 8 or not any(c.isalpha() for c in password) or not any(c.isdigit() for c in password):
return render_template('register.html', error='密码长度至少8位,且必须包含字母和数字')
# 连接数据库,检查用户名是否已存在
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
if cursor.fetchone():
conn.close()
return render_template('register.html', error='用户名已存在')
try:
cursor.execute(
"INSERT INTO users (username, password, name, phone, department) VALUES (?, ?, ?, ?, ?)",
(username, password, name, phone, department)
)
# 同时插入到登录信息表,不自动生成OTP码
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(username, password, ""))
conn.commit()
conn.close()
# 注册成功,跳转到登录页并显示成功消息
return render_template('login.html', success='注册成功,请登录')
except Exception as e:
conn.close()
return render_template('register.html', error=f'注册失败,请重试。错误:{str(e)}')
return render_template('register.html')
# 修改密码路由
@bp.route('/change_password', methods=['POST'])
def change_password():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
old_password = request.form.get('old_password')
new_password = request.form.get('new_password')
confirm_password = request.form.get('confirm_password')
# 验证参数
if not old_password or not new_password or not confirm_password:
return jsonify({'success': False, 'error': '请填写所有必填字段'})
# 验证新密码和确认密码是否一致
if new_password != confirm_password:
return jsonify({'success': False, 'error': '两次输入的新密码不一致'})
# 验证新密码复杂度
if len(new_password) < 8 or not any(c.isalpha() for c in new_password) or not any(c.isdigit() for c in new_password):
return jsonify({'success': False, 'error': '新密码长度至少8位,且必须包含字母和数字'})
# 连接数据库,验证旧密码并更新新密码
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
# 验证旧密码是否正确
cursor.execute("SELECT password FROM users WHERE username = ?", (session['username'],))
result = cursor.fetchone()
if not result or result[0] != old_password:
conn.close()
return jsonify({'success': False, 'error': '旧密码不正确'})
# 更新密码
cursor.execute("UPDATE users SET password = ? WHERE username = ?", (new_password, session['username']))
# 同时更新login_info表中的密码
cursor.execute("UPDATE login_info SET password = ? WHERE username = ?", (new_password, session['username']))
conn.commit()
conn.close()
return jsonify({'success': True, 'message': '修改密码成功,请重新登录'})
# 获取个人信息路由
@bp.route('/get_user_profile', methods=['GET'])
def get_user_profile():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 连接数据库,获取用户信息
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
cursor.execute("SELECT username, name, phone, department FROM users WHERE username = ?", (session['username'],))
user = cursor.fetchone()
conn.close()
if not user:
return jsonify({'success': False, 'error': '用户不存在'})
# 构造返回数据
user_data = {
'username': user[0],
'name': user[1],
'phone': user[2],
'department': user[3]
}
return jsonify({'success': True, 'user': user_data})
# 更新个人信息路由
@bp.route('/update_user_profile', methods=['POST'])
def update_user_profile():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
name = request.form.get('name', '').strip()
phone = request.form.get('phone', '').strip()
department = request.form.get('department', '').strip()
# 验证参数
if not name or not phone or not department:
return jsonify({'success': False, 'error': '请填写所有必填字段'})
# 连接数据库,更新用户信息
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
try:
cursor.execute(
"UPDATE users SET name = ?, phone = ?, department = ? WHERE username = ?",
(name, phone, department, session['username'])
)
conn.commit()
# 获取更新后的用户信息
cursor.execute("SELECT username, name, phone, department FROM users WHERE username = ?", (session['username'],))
updated_user = cursor.fetchone()
conn.close()
# 更新会话中的部门信息
session['department'] = department
# 构造返回数据
user_data = {
'username': updated_user[0],
'name': updated_user[1],
'phone': updated_user[2],
'department': updated_user[3]
}
return jsonify({'success': True, 'message': '个人信息更新成功', 'user': user_data})
except Exception as e:
conn.close()
return jsonify({'success': False, 'error': f'更新失败,请重试。错误:{str(e)}'})
# 获取登录信息路由
@bp.route('/get_login_info', methods=['GET'])
def get_login_info():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 获取登录时间 - 如果会话中没有存储登录时间,可以使用当前时间
login_time = session.get('login_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
# 获取登录IP地址
login_ip = request.remote_addr
# 构造返回数据
return jsonify({
'success': True,
'login_time': login_time,
'login_ip': login_ip
})
# 登录信息更新路由
@bp.route('/update_login_info', methods=['POST'])
def update_login_info():
import re
if 'username' not in session:
return jsonify({'success': False, 'error': '请先登录'}), 401
data = request.get_json()
username = data.get('username')
password = data.get('password')
otp_code = data.get('otp_code')
# 验证输入
if not username or not otp_code:
return jsonify({'success': False, 'error': '用户名和OTP码不能为空'})
# 验证OTP码长度必须是6位
if len(otp_code) != 6:
return jsonify({'success': False, 'error': 'OTP码长度必须是6位'})
# 确保用户只能更新自己的信息
if username != session['username'] and session['username'] != 'admin':
return jsonify({'success': False, 'error': '无权更新其他用户的信息'})
# 连接数据库
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
try:
# 构建更新语句
if session['username'] == 'admin':
# admin用户可以更新所有字段
if password:
# 只验证密码不为空,不限制格式
cursor.execute("UPDATE login_info SET password = ?, otp_code = ? WHERE username = ?",
(password, otp_code, username))
else:
cursor.execute("UPDATE login_info SET otp_code = ? WHERE username = ?", (otp_code, username))
else:
# 普通用户只能更新自己的OTP码
cursor.execute("UPDATE login_info SET otp_code = ? WHERE username = ?", (otp_code, session['username']))
# 检查是否有行被更新
if cursor.rowcount == 0:
# 如果没有找到记录,则插入新记录
if session['username'] == 'admin':
# admin用户可以为任何用户创建登录信息
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(username, password or 'default_password', otp_code))
else:
# 普通用户只能创建自己的登录信息
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(session['username'], 'default_password', otp_code))
# 提交更改
conn.commit()
# 如果更新的是当前登录用户的信息,更新session中的OTP码
if username == session['username']:
session['otp_code'] = otp_code
conn.close()
return jsonify({'success': True, 'message': '登录信息更新成功'})
except Exception as e:
conn.close()
return jsonify({'success': False, 'error': f'更新失败:{str(e)}'})
# 登出路由
@bp.route('/logout')
def logout():
session.clear()
return redirect(url_for('user.login'))
# 用户管理页面路由
@bp.route('/users_management')
def users_management():
if 'username' not in session:
return redirect(url_for('user.login'))
# 只有admin用户才能访问用户管理页面
if session['username'] != 'admin':
return redirect(url_for('query'))
# 获取所有部门列表(用于筛选和修改)
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
cursor.execute("SELECT DISTINCT department FROM users")
departments = [dept[0] for dept in cursor.fetchall()]
conn.close()
return render_template('users_management.html', departments=departments)
# 获取用户列表路由
@bp.route('/get_users', methods=['GET'])
def get_users():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 只有admin用户才能获取用户列表
if session['username'] != 'admin':
return jsonify({'success': False, 'error': '无权限访问'}), 403
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
# 获取所有用户信息
cursor.execute("SELECT id, username, name, department, status FROM users")
users = cursor.fetchall()
conn.close()
# 格式化用户数据
formatted_users = []
for user in users:
formatted_users.append({
'id': user[0],
'username': user[1],
'name': user[2],
'department': user[3],
'status': user[4]
})
return jsonify({'success': True, 'users': formatted_users})
# 更新用户状态路由
@bp.route('/update_user_status', methods=['POST'])
def update_user_status():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 只有admin用户才能更新用户状态
if session['username'] != 'admin':
return jsonify({'success': False, 'error': '无权限访问'}), 403
data = request.get_json()
user_id = data.get('user_id')
status = data.get('status')
# 验证输入
if not user_id or not status:
return jsonify({'success': False, 'error': '缺少必要参数'})
# 验证状态值
if status not in ['active', 'inactive']:
return jsonify({'success': False, 'error': '状态值无效'})
# 不能禁用admin用户
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
cursor.execute("SELECT username FROM users WHERE id = ?", (user_id,))
user = cursor.fetchone()
if user and user[0] == 'admin' and status == 'inactive':
conn.close()
return jsonify({'success': False, 'error': '不能禁用管理员用户'})
# 更新用户状态
try:
cursor.execute("UPDATE users SET status = ? WHERE id = ?", (status, user_id))
conn.commit()
conn.close()
return jsonify({'success': True, 'message': '用户状态更新成功'})
except Exception as e:
conn.close()
return jsonify({'success': False, 'error': f'更新失败:{str(e)}'})
# 更新用户部门路由
@bp.route('/update_user_department', methods=['POST'])
def update_user_department():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 只有admin用户才能更新用户部门
if session['username'] != 'admin':
return jsonify({'success': False, 'error': '无权限访问'}), 403
data = request.get_json()
user_id = data.get('user_id')
department = data.get('department')
# 验证输入
if not user_id or not department:
return jsonify({'success': False, 'error': '缺少必要参数'})
# 更新用户部门
try:
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
cursor.execute("UPDATE users SET department = ? WHERE id = ?", (department, user_id))
conn.commit()
conn.close()
return jsonify({'success': True, 'message': '部门信息更新成功'})
except Exception as e:
conn.close()
return jsonify({'success': False, 'error': f'更新失败:{str(e)}'})
# 重置用户密码路由
@bp.route('/reset_user_password', methods=['POST'])
def reset_user_password():
if 'username' not in session:
return jsonify({'success': False, 'error': '未登录'}), 401
# 只有admin用户才能重置用户密码
if session['username'] != 'admin':
return jsonify({'success': False, 'error': '无权限访问'}), 403
data = request.get_json()
user_id = data.get('user_id')
username = data.get('username')
# 验证输入
if not user_id or not username:
return jsonify({'success': False, 'error': '缺少必要参数'})
# 重置密码为默认值
default_password = 'default123'
try:
conn = sqlite3.connect('car_info.db')
cursor = conn.cursor()
# 检查用户ID和用户名是否匹配
cursor.execute("SELECT id FROM users WHERE username = ?", (username,))
db_user_id = cursor.fetchone()
if not db_user_id or db_user_id[0] != user_id:
conn.close()
return jsonify({'success': False, 'error': '用户信息不匹配'})
# 更新users表中的密码
cursor.execute("UPDATE users SET password = ? WHERE id = ?", (default_password, user_id))
# 更新login_info表中的密码
cursor.execute("UPDATE login_info SET password = ? WHERE username = ?", (default_password, username))
# 如果login_info表中没有该用户的记录,则插入
if cursor.rowcount == 0:
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
(username, default_password, ""))
conn.commit()
conn.close()
return jsonify({'success': True, 'message': '密码已初始化为:' + default_password})
except Exception as e:
conn.close()
return jsonify({'success': False, 'error': f'密码重置失败:{str(e)}'})