2025017a
This commit is contained in:
@@ -1,13 +1,18 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, session
|
||||
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
|
||||
from datetime import datetime, timedelta
|
||||
import sqlite3
|
||||
import os
|
||||
import random
|
||||
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
|
||||
|
||||
# 导入用户模块
|
||||
from user import bp as user_bp, init_user_db
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'your_secret_key' # 生产环境中应该使用更安全的密钥
|
||||
|
||||
# 注册用户蓝图
|
||||
app.register_blueprint(user_bp)
|
||||
|
||||
# 确保模板文件夹存在
|
||||
templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
|
||||
if not os.path.exists(templates_dir):
|
||||
@@ -15,20 +20,12 @@ if not os.path.exists(templates_dir):
|
||||
|
||||
# 初始化数据库
|
||||
def init_db():
|
||||
# 初始化用户相关的数据库
|
||||
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' NOT NULL
|
||||
)
|
||||
''')
|
||||
|
||||
# 创建车辆信息表
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS car_owners (
|
||||
@@ -41,6 +38,7 @@ def init_db():
|
||||
address TEXT
|
||||
)
|
||||
''')
|
||||
|
||||
# 创建查询历史表
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS query_history (
|
||||
@@ -54,30 +52,8 @@ def init_db():
|
||||
)
|
||||
''')
|
||||
|
||||
# 创建登录信息表
|
||||
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 NOT NULL,
|
||||
FOREIGN KEY (username) REFERENCES users (username)
|
||||
)
|
||||
''')
|
||||
# 插入测试数据
|
||||
# 插入用户和车辆数据
|
||||
# 插入一些测试车辆数据
|
||||
try:
|
||||
# 先检查用户表结构是否有新字段,如果没有则跳过插入,避免错误
|
||||
cursor.execute("PRAGMA table_info(users)")
|
||||
columns = [column[1] for column in cursor.fetchall()]
|
||||
if 'name' in columns and 'phone' in columns and 'department' in columns:
|
||||
# 检查admin用户是否已存在
|
||||
cursor.execute("SELECT id FROM users WHERE username = ?", ('admin',))
|
||||
if not cursor.fetchone():
|
||||
cursor.execute("INSERT INTO users (username, password, name, phone, department) VALUES (?, ?, ?, ?, ?)", ('admin', 'admin123', '管理员', '13800138000', 'IT部'))
|
||||
# 同时插入到登录信息表
|
||||
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)", ('admin', 'admin123', str(random.randint(100000, 999999))))
|
||||
# 插入一些测试车辆数据
|
||||
test_cars = [
|
||||
('京A12345', '13800138001', '110101199001011234', '张三', 'zhangsan@example.com', '北京市朝阳区'),
|
||||
('沪B54321', '13900139001', '310101199001012345', '李四', 'lisi@example.com', '上海市静安区'),
|
||||
@@ -160,63 +136,16 @@ def init_db():
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# 登录路由
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
def login():
|
||||
# 检查用户是否已登录,如果已登录则自动跳转到查询页面
|
||||
if 'username' in session:
|
||||
return redirect(url_for('query'))
|
||||
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 先检查用户是否存在于users表中
|
||||
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||
user = cursor.fetchone()
|
||||
|
||||
if user:
|
||||
# 从login_info表中验证密码
|
||||
cursor.execute("SELECT password, otp_code FROM login_info WHERE username = ?", (username,))
|
||||
login_info = cursor.fetchone()
|
||||
|
||||
# 如果login_info表中没有该用户的记录,创建一个
|
||||
if not login_info:
|
||||
# 不自动生成OTP码,设置为空字符串
|
||||
otp_code = ""
|
||||
# 插入到login_info表
|
||||
cursor.execute("INSERT INTO login_info (username, password, otp_code) VALUES (?, ?, ?)",
|
||||
(username, password, otp_code))
|
||||
conn.commit()
|
||||
is_valid = True
|
||||
else:
|
||||
# 验证密码
|
||||
is_valid = (login_info[0] == password)
|
||||
otp_code = login_info[1]
|
||||
|
||||
if is_valid:
|
||||
# 登录成功,设置会话信息
|
||||
session['username'] = username
|
||||
session['department'] = user[5] if len(user) > 5 else '未知部门'
|
||||
session['name'] = user[3] if len(user) > 3 else username # 存储用户姓名,默认使用用户名
|
||||
# 存储登录时间
|
||||
session['login_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
# 存储OTP码
|
||||
session['otp_code'] = otp_code
|
||||
conn.close()
|
||||
return redirect(url_for('query'))
|
||||
|
||||
conn.close()
|
||||
return render_template('login.html', error='用户名或密码错误')
|
||||
return render_template('login.html')
|
||||
# 首页重定向到登录页
|
||||
@app.route('/')
|
||||
def index():
|
||||
return redirect(url_for('user.login'))
|
||||
|
||||
# 查询路由
|
||||
@app.route('/query', methods=['GET', 'POST'])
|
||||
def query():
|
||||
if 'username' not in session:
|
||||
return redirect(url_for('login'))
|
||||
return redirect(url_for('user.login'))
|
||||
|
||||
# 获取最近查询历史
|
||||
formatted_recent_queries = get_recent_queries()
|
||||
@@ -370,436 +299,6 @@ def get_recent_queries():
|
||||
})
|
||||
return formatted_recent_queries
|
||||
|
||||
# 注册路由
|
||||
@app.route('/register', methods=['GET', 'POST'])
|
||||
def register():
|
||||
if request.method == 'POST':
|
||||
username = request.form.get('username', '').strip()
|
||||
name = request.form.get('name', '').strip()
|
||||
phone = request.form.get('phone', '').strip()
|
||||
department = request.form.get('department', '').strip()
|
||||
password = request.form.get('password', '')
|
||||
confirm_password = request.form.get('confirm_password', '')
|
||||
|
||||
# 表单验证
|
||||
if not username or not name or not phone or not department or not password:
|
||||
return render_template('register.html', error='请填写所有必填字段')
|
||||
|
||||
# 密码匹配检查
|
||||
if password != confirm_password:
|
||||
return render_template('register.html', error='两次输入的密码不一致')
|
||||
|
||||
# 检查用户名是否已存在
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id 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')
|
||||
|
||||
# 修改密码路由
|
||||
@app.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': '修改密码成功,请重新登录'})
|
||||
|
||||
# 获取个人信息路由
|
||||
@app.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})
|
||||
|
||||
# 更新个人信息路由
|
||||
@app.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)}'})
|
||||
|
||||
# 获取登录信息路由
|
||||
@app.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
|
||||
})
|
||||
|
||||
# 登录信息更新路由
|
||||
@app.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)}'})
|
||||
|
||||
# 登出路由
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
session.clear()
|
||||
return redirect(url_for('login'))
|
||||
|
||||
# 用户管理页面路由
|
||||
@app.route('/users_management')
|
||||
def users_management():
|
||||
if 'username' not in session:
|
||||
return redirect(url_for('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)
|
||||
|
||||
# 获取用户列表路由
|
||||
@app.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})
|
||||
|
||||
# 更新用户状态路由
|
||||
@app.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)}'})
|
||||
|
||||
# 更新用户部门路由
|
||||
@app.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)}'})
|
||||
|
||||
# 重置用户密码路由
|
||||
@app.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)}'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
init_db()
|
||||
app.run(debug=True)
|
||||
BIN
Binary file not shown.
@@ -695,13 +695,10 @@
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// 密码修改成功
|
||||
// 密码修改成功,先执行退出功能,再跳转到登录页面
|
||||
alert(data.message);
|
||||
closeChangePasswordModal();
|
||||
// 跳转到登录页面
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ url_for('login') }}';
|
||||
}, 1000);
|
||||
// 重定向到退出路由,系统会自动完成退出并跳转到登录页面
|
||||
window.location.href = '{{ url_for('logout') }}';
|
||||
} else if (data.error) {
|
||||
// 显示服务器返回的错误信息
|
||||
showPasswordError(data.error);
|
||||
|
||||
@@ -0,0 +1,552 @@
|
||||
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)}'})
|
||||
Reference in New Issue
Block a user