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)}'})