20250819corp
This commit is contained in:
@@ -1,75 +1,188 @@
|
||||
from flask import Flask, jsonify
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
# 创建Flask蓝图
|
||||
api_bp = Flask(__name__)
|
||||
api_bp = Blueprint('api', __name__)
|
||||
|
||||
# 连接数据库的辅助函数
|
||||
def get_db_connection():
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn.row_factory = sqlite3.Row # 使返回的数据可以通过列名访问
|
||||
return conn
|
||||
|
||||
# API函数1: 返回所有的参数信息
|
||||
# API函数1: 返回最新的参数配置记录
|
||||
@api_bp.route('/api/parameters', methods=['GET'])
|
||||
def get_all_parameters():
|
||||
def get_parameters():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询所有参数配置记录
|
||||
# 查询所有参数配置记录并只返回第一条(最新的一条)
|
||||
cursor.execute("""
|
||||
SELECT id, param1, param2, param3, param4, param5, update_time
|
||||
FROM parameter_config
|
||||
ORDER BY update_time DESC
|
||||
LIMIT 1
|
||||
""")
|
||||
|
||||
# 获取第一条查询结果
|
||||
row = cursor.fetchone()
|
||||
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
|
||||
# 如果没有查询到数据
|
||||
if not row:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': '未找到参数配置记录',
|
||||
'data': None
|
||||
}), 404
|
||||
|
||||
# 格式化查询结果
|
||||
parameter = {
|
||||
'id': row[0],
|
||||
'param1': row[1],
|
||||
'param2': row[2],
|
||||
'param3': row[3],
|
||||
'param4': row[4],
|
||||
'param5': row[5],
|
||||
'update_time': row[6]
|
||||
}
|
||||
|
||||
# 返回JSON格式的数据
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': parameter
|
||||
})
|
||||
except Exception as e:
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': str(e),
|
||||
'data': []
|
||||
}), 500
|
||||
|
||||
# API函数2: 返回query_history表中所有results_count=-1的数据
|
||||
@api_bp.route('/api/pending-queries', methods=['GET'])
|
||||
def get_pending_queries():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询query_history表中results_count=-1的所有数据
|
||||
cursor.execute("""
|
||||
SELECT id, department, query_date, plate_number, phone, results_count, query_ip
|
||||
FROM query_history
|
||||
WHERE results_count = -1
|
||||
ORDER BY query_date DESC
|
||||
""")
|
||||
|
||||
# 获取所有查询结果
|
||||
rows = cursor.fetchall()
|
||||
|
||||
# 关闭数据库连接
|
||||
conn.close()
|
||||
|
||||
# 如果没有查询到数据
|
||||
if not rows:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': '未找到参数配置记录',
|
||||
'data': []
|
||||
}), 404
|
||||
close_db_connection(conn)
|
||||
|
||||
# 格式化查询结果
|
||||
parameters_list = []
|
||||
pending_queries = []
|
||||
for row in rows:
|
||||
parameters_list.append({
|
||||
pending_query = {
|
||||
'id': row['id'],
|
||||
'param1': row['param1'],
|
||||
'param2': row['param2'],
|
||||
'param3': row['param3'],
|
||||
'param4': row['param4'],
|
||||
'param5': row['param5'],
|
||||
'update_time': row['update_time']
|
||||
})
|
||||
'department': row['department'],
|
||||
'query_date': row['query_date'],
|
||||
'plate_number': row['plate_number'],
|
||||
'phone': row['phone'],
|
||||
'results_count': row['results_count'],
|
||||
'query_ip': row['query_ip']
|
||||
}
|
||||
pending_queries.append(pending_query)
|
||||
|
||||
# 返回JSON格式的参数信息
|
||||
# 返回JSON格式的数据
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': '参数信息获取成功',
|
||||
'data': parameters_list,
|
||||
'total': len(parameters_list)
|
||||
}), 200
|
||||
|
||||
'data': pending_queries,
|
||||
'count': len(pending_queries)
|
||||
})
|
||||
except Exception as e:
|
||||
# 处理异常情况
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'获取参数信息失败: {str(e)}',
|
||||
'error': str(e),
|
||||
'data': []
|
||||
}), 500
|
||||
|
||||
# 如果直接运行此文件(用于测试)
|
||||
if __name__ == '__main__':
|
||||
# 在生产环境中不应使用debug=True
|
||||
api_bp.run(debug=True)
|
||||
# API函数3: 更新query_history表中对应记录的results_count值
|
||||
@api_bp.route('/api/update-query-result', methods=['POST'])
|
||||
def update_query_result():
|
||||
try:
|
||||
# 获取前端提交的数据
|
||||
data = request.json
|
||||
if not data:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': '请求数据不能为空',
|
||||
'data': None
|
||||
}), 400
|
||||
|
||||
# 检查必要的字段是否存在
|
||||
if 'id' not in data or 'results_count' not in data:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': '缺少必要的字段: id 或 results_count',
|
||||
'data': None
|
||||
}), 400
|
||||
|
||||
# 获取id和results_count值
|
||||
query_id = data['id']
|
||||
results_count = data['results_count']
|
||||
|
||||
# 连接数据库
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 更新query_history表中的对应记录
|
||||
cursor.execute("""
|
||||
UPDATE query_history
|
||||
SET results_count = ?
|
||||
WHERE id = ?
|
||||
""", (results_count, query_id))
|
||||
|
||||
# 提交更改
|
||||
conn.commit()
|
||||
|
||||
# 获取受影响的行数
|
||||
affected_rows = cursor.rowcount
|
||||
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
|
||||
# 检查是否有记录被更新
|
||||
if affected_rows == 0:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': '未找到id为 {} 的记录'.format(query_id),
|
||||
'data': None
|
||||
}), 404
|
||||
|
||||
# 返回成功响应
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': '记录更新成功',
|
||||
'data': {
|
||||
'id': query_id,
|
||||
'results_count': results_count
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': str(e),
|
||||
'data': None
|
||||
}), 500
|
||||
@@ -1,13 +1,15 @@
|
||||
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
|
||||
|
||||
# 导入用户模块
|
||||
from user import bp as user_bp, init_user_db
|
||||
# 导入API模块
|
||||
from api import api_bp
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection, close_global_connection
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'your_secret_key' # 生产环境中应该使用更安全的密钥
|
||||
@@ -27,7 +29,7 @@ def init_db():
|
||||
# 初始化用户相关的数据库
|
||||
init_user_db()
|
||||
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 创建车辆信息表
|
||||
@@ -66,9 +68,9 @@ def init_db():
|
||||
('浙E54321', '13500135001', '330501199001015678', '钱七', 'qianqi@example.com', '浙江省湖州市')
|
||||
]
|
||||
cursor.executemany("INSERT INTO car_owners (plate_number, phone, id_card, name, email, address) VALUES (?, ?, ?, ?, ?, ?)", test_cars)
|
||||
except sqlite3.IntegrityError:
|
||||
# 数据已存在,忽略
|
||||
pass
|
||||
except Exception as e:
|
||||
# 数据已存在或其他错误,忽略
|
||||
print(f"插入测试数据时出错: {e}")
|
||||
|
||||
# 单独处理查询历史演示数据,确保每次都能插入20条记录
|
||||
try:
|
||||
@@ -137,8 +139,12 @@ def init_db():
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"插入查询历史数据时出错: {e}")
|
||||
try:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"提交数据库更改时出错: {e}")
|
||||
finally:
|
||||
close_db_connection(conn)
|
||||
|
||||
# 首页重定向到登录页
|
||||
@app.route('/')
|
||||
@@ -161,7 +167,7 @@ def query():
|
||||
if not plate_number and not phone:
|
||||
return render_template('query.html', error='请至少输入车牌号或手机号', recent_queries=formatted_recent_queries)
|
||||
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
query_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
@@ -180,32 +186,35 @@ def query():
|
||||
|
||||
# 从用户信息表获取部门信息
|
||||
try:
|
||||
conn_dept = sqlite3.connect('car_info.db')
|
||||
cursor_dept = conn_dept.cursor()
|
||||
cursor_dept.execute("SELECT department FROM users WHERE username = ?", (session['username'],))
|
||||
user_dept = cursor_dept.fetchone()
|
||||
department = user_dept[0] if user_dept else '未知部门'
|
||||
# 可以复用同一个连接,不需要创建新连接
|
||||
cursor.execute("SELECT department FROM users WHERE username = ?", (session['username'],))
|
||||
user_dept = cursor.fetchone()
|
||||
if user_dept:
|
||||
department = user_dept[0]
|
||||
except Exception as e:
|
||||
print(f"获取部门信息时出错: {e}")
|
||||
department = '未知部门'
|
||||
finally:
|
||||
if 'conn_dept' in locals():
|
||||
conn_dept.close()
|
||||
|
||||
# 记录查询历史到数据库
|
||||
try:
|
||||
conn_history = sqlite3.connect('car_info.db')
|
||||
cursor_history = conn_history.cursor()
|
||||
cursor_history.execute(
|
||||
# 继续使用同一个连接
|
||||
# 检查是否是从"增加"按钮提交的请求
|
||||
is_add_query = request.form.get('is_add_query', 'false').lower() == 'true'
|
||||
|
||||
# 如果是增加按钮提交的请求,将results_count设置为-1
|
||||
if is_add_query:
|
||||
results_count = -1
|
||||
else:
|
||||
results_count = len(results)
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO query_history (department, query_date, plate_number, phone, results_count, query_ip) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(department, query_date, plate_number if plate_number else None, phone if phone else None, len(results), query_ip)
|
||||
(department, query_date, plate_number if plate_number else None, phone if phone else None, results_count, query_ip)
|
||||
)
|
||||
conn_history.commit()
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"记录查询历史时出错: {e}")
|
||||
finally:
|
||||
if 'conn_history' in locals():
|
||||
conn_history.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
# 处理查询结果
|
||||
car_owners = []
|
||||
@@ -241,15 +250,15 @@ def query_history_detail(history_id):
|
||||
if 'username' not in session:
|
||||
return jsonify({'error': '未登录'}), 401
|
||||
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
# 获取查询历史记录
|
||||
cursor.execute("SELECT plate_number, phone FROM query_history WHERE id = ?", (history_id,))
|
||||
history = cursor.fetchone()
|
||||
|
||||
if not history:
|
||||
conn.close()
|
||||
return jsonify({'error': '查询历史不存在'}), 404
|
||||
|
||||
plate_number, phone = history
|
||||
@@ -263,7 +272,6 @@ def query_history_detail(history_id):
|
||||
cursor.execute("SELECT * FROM car_owners WHERE phone = ?", (phone,))
|
||||
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
# 格式化结果
|
||||
car_owners = []
|
||||
@@ -279,15 +287,21 @@ def query_history_detail(history_id):
|
||||
})
|
||||
|
||||
return jsonify({'car_owners': car_owners})
|
||||
except Exception as e:
|
||||
print(f"查询历史详情时出错: {e}")
|
||||
return jsonify({'error': '查询失败'}), 500
|
||||
finally:
|
||||
close_db_connection(conn)
|
||||
|
||||
# 获取最近查询历史的辅助函数
|
||||
def get_recent_queries():
|
||||
# 获取最近20条查询历史记录,按查询日期降序排列
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
cursor.execute("SELECT id, department, query_date, plate_number, phone, results_count, query_ip FROM query_history ORDER BY query_date DESC LIMIT 20")
|
||||
recent_queries = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
# 格式化查询历史数据
|
||||
formatted_recent_queries = []
|
||||
@@ -301,8 +315,32 @@ def get_recent_queries():
|
||||
'results_count': q[5],
|
||||
'query_ip': q[6]
|
||||
})
|
||||
|
||||
return formatted_recent_queries
|
||||
except Exception as e:
|
||||
print(f"获取最近查询历史时出错: {e}")
|
||||
return []
|
||||
finally:
|
||||
close_db_connection(conn)
|
||||
|
||||
import signal
|
||||
import sys
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
"""处理终止信号,确保在程序退出时关闭数据库连接"""
|
||||
print('\n接收到终止信号,正在关闭数据库连接...')
|
||||
close_global_connection()
|
||||
print('数据库连接已关闭')
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 注册信号处理程序
|
||||
signal.signal(signal.SIGINT, signal_handler) # 处理Ctrl+C
|
||||
signal.signal(signal.SIGTERM, signal_handler) # 处理终止信号
|
||||
|
||||
try:
|
||||
init_db()
|
||||
app.run(debug=True)
|
||||
finally:
|
||||
# 确保在程序退出时关闭数据库连接
|
||||
close_global_connection()
|
||||
BIN
Binary file not shown.
+47
-23
@@ -1,31 +1,55 @@
|
||||
import sqlite3
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
# 检查数据库连接是否正常
|
||||
def check_database_connection():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询所有表
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
||||
tables = cursor.fetchall()
|
||||
print('数据库中的表:', tables)
|
||||
# 执行简单的SQL查询来测试连接
|
||||
cursor.execute("SELECT sqlite_version()")
|
||||
version = cursor.fetchone()[0]
|
||||
|
||||
# 查询参数配置表
|
||||
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='parameter_config'")
|
||||
result = cursor.fetchone()
|
||||
print('参数配置表SQL:', result)
|
||||
# 检查是否存在必要的表
|
||||
necessary_tables = ['users', 'query_records']
|
||||
tables_info = []
|
||||
|
||||
# 如果参数配置表存在,查询其结构
|
||||
if result:
|
||||
cursor.execute("PRAGMA table_info(parameter_config)")
|
||||
columns = cursor.fetchall()
|
||||
print('参数配置表结构:')
|
||||
for col in columns:
|
||||
print(f"字段: {col[1]}, 类型: {col[2]}")
|
||||
for table in necessary_tables:
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table,))
|
||||
exists = cursor.fetchone() is not None
|
||||
tables_info.append({"name": table, "exists": exists})
|
||||
|
||||
# 查询数据
|
||||
cursor.execute("SELECT * FROM parameter_config")
|
||||
data = cursor.fetchall()
|
||||
print('参数配置数据:', data)
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
|
||||
# 关闭连接
|
||||
conn.close()
|
||||
# 构造返回结果
|
||||
result = {
|
||||
"success": True,
|
||||
"version": version,
|
||||
"tables": tables_info
|
||||
}
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# 如果直接运行此脚本,则执行检查操作
|
||||
if __name__ == "__main__":
|
||||
result = check_database_connection()
|
||||
print(f"数据库连接状态: {'成功' if result['success'] else '失败'}")
|
||||
if result['success']:
|
||||
print(f"SQLite版本: {result['version']}")
|
||||
print("表状态:")
|
||||
for table in result['tables']:
|
||||
print(f" - {table['name']}: {'存在' if table['exists'] else '不存在'}")
|
||||
else:
|
||||
print(f"错误信息: {result['error']}")
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import sqlite3
|
||||
import threading
|
||||
|
||||
# 数据库文件路径
|
||||
db_path = 'car_info.db'
|
||||
|
||||
# 使用线程本地存储来保存每个线程的连接
|
||||
_thread_local = threading.local()
|
||||
|
||||
# 全局连接引用计数
|
||||
global_ref_count = 0
|
||||
|
||||
def get_db_connection():
|
||||
"""获取数据库连接(线程本地存储模式)
|
||||
|
||||
使用线程本地存储确保每个线程都有自己的数据库连接,解决SQLite多线程问题
|
||||
|
||||
Returns:
|
||||
sqlite3.Connection: 当前线程的数据库连接对象
|
||||
"""
|
||||
global global_ref_count
|
||||
|
||||
# 检查当前线程是否已有连接
|
||||
if not hasattr(_thread_local, 'connection') or _thread_local.connection is None:
|
||||
try:
|
||||
# 为当前线程创建新连接
|
||||
_thread_local.connection = sqlite3.connect(db_path)
|
||||
# 设置行工厂,使查询结果以字典形式返回
|
||||
_thread_local.connection.row_factory = sqlite3.Row
|
||||
# 增加全局引用计数
|
||||
global_ref_count += 1
|
||||
except sqlite3.Error as e:
|
||||
print(f"数据库连接失败: {e}")
|
||||
raise
|
||||
|
||||
return _thread_local.connection
|
||||
|
||||
def close_db_connection(conn=None):
|
||||
"""关闭数据库连接(线程本地存储模式)
|
||||
|
||||
1. 如果传入了连接对象,直接关闭它
|
||||
2. 如果没有传入连接对象,但当前线程有连接,则关闭当前线程的连接
|
||||
|
||||
Args:
|
||||
conn (sqlite3.Connection): 需要关闭的数据库连接对象(可选)
|
||||
"""
|
||||
global global_ref_count
|
||||
|
||||
# 如果指定了连接对象,直接关闭
|
||||
if conn:
|
||||
try:
|
||||
conn.close()
|
||||
# 如果关闭的是当前线程的连接,更新线程本地存储
|
||||
if hasattr(_thread_local, 'connection') and _thread_local.connection == conn:
|
||||
_thread_local.connection = None
|
||||
global_ref_count = max(0, global_ref_count - 1)
|
||||
except sqlite3.Error as e:
|
||||
print(f"关闭数据库连接时出错: {e}")
|
||||
else:
|
||||
# 如果没有指定连接对象,尝试关闭当前线程的连接
|
||||
if hasattr(_thread_local, 'connection') and _thread_local.connection is not None:
|
||||
try:
|
||||
_thread_local.connection.close()
|
||||
_thread_local.connection = None
|
||||
global_ref_count = max(0, global_ref_count - 1)
|
||||
except sqlite3.Error as e:
|
||||
print(f"关闭当前线程的数据库连接时出错: {e}")
|
||||
|
||||
def close_global_connection():
|
||||
"""全局连接清理函数(线程本地存储模式)
|
||||
|
||||
在应用程序关闭时调用此函数,它会:
|
||||
1. 关闭当前线程的数据库连接(如果有)
|
||||
2. 重置全局引用计数
|
||||
|
||||
注意:由于使用了线程本地存储,无法直接关闭其他线程的连接。
|
||||
每个线程应该在结束前自行关闭其连接。
|
||||
"""
|
||||
global global_ref_count
|
||||
|
||||
# 关闭当前线程的连接(如果有)
|
||||
if hasattr(_thread_local, 'connection') and _thread_local.connection is not None:
|
||||
try:
|
||||
_thread_local.connection.close()
|
||||
_thread_local.connection = None
|
||||
except sqlite3.Error as e:
|
||||
print(f"关闭当前线程的数据库连接时出错: {e}")
|
||||
|
||||
# 重置全局引用计数
|
||||
global_ref_count = 0
|
||||
+169
-52
@@ -5,9 +5,14 @@
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function showModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
var modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
// 使用className替代classList以提高兼容性
|
||||
if (modal.classList) {
|
||||
modal.classList.remove('hidden');
|
||||
} else {
|
||||
modal.className = modal.className.replace('hidden', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +21,14 @@ function showModal(modalId) {
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
var modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
// 使用className替代classList以提高兼容性
|
||||
if (modal.classList) {
|
||||
modal.classList.add('hidden');
|
||||
} else {
|
||||
modal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +37,7 @@ function closeModal(modalId) {
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function bindModalOutsideClick(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
var modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
@@ -43,29 +53,69 @@ function bindModalOutsideClick(modalId) {
|
||||
* @param {boolean} isSuccess - 是否为成功消息
|
||||
* @param {number} duration - 消息显示时长(毫秒)
|
||||
*/
|
||||
function showMessage(message, isSuccess = true, duration = 5000) {
|
||||
const messageContainer = document.getElementById('messageContainer');
|
||||
const successMessage = document.getElementById('successMessage');
|
||||
const errorMessage = document.getElementById('errorMessage');
|
||||
function showMessage(message, isSuccess, duration) {
|
||||
// 为参数设置默认值,不使用ES6默认参数
|
||||
isSuccess = (isSuccess === undefined) ? true : isSuccess;
|
||||
duration = (duration === undefined) ? 5000 : duration;
|
||||
|
||||
var messageContainer = document.getElementById('messageContainer');
|
||||
var successMessage = document.getElementById('successMessage');
|
||||
var errorMessage = document.getElementById('errorMessage');
|
||||
|
||||
if (!messageContainer || !successMessage || !errorMessage) return;
|
||||
|
||||
if (isSuccess) {
|
||||
successMessage.querySelector('span').textContent = message;
|
||||
if (successMessage.classList) {
|
||||
successMessage.classList.remove('hidden');
|
||||
} else {
|
||||
successMessage.className = successMessage.className.replace('hidden', '');
|
||||
}
|
||||
if (errorMessage.classList) {
|
||||
errorMessage.classList.add('hidden');
|
||||
} else {
|
||||
errorMessage.className += ' hidden';
|
||||
}
|
||||
} else {
|
||||
errorMessage.querySelector('span').textContent = message;
|
||||
if (errorMessage.classList) {
|
||||
errorMessage.classList.remove('hidden');
|
||||
} else {
|
||||
errorMessage.className = errorMessage.className.replace('hidden', '');
|
||||
}
|
||||
if (successMessage.classList) {
|
||||
successMessage.classList.add('hidden');
|
||||
} else {
|
||||
successMessage.className += ' hidden';
|
||||
}
|
||||
}
|
||||
|
||||
if (messageContainer.classList) {
|
||||
messageContainer.classList.remove('hidden');
|
||||
} else {
|
||||
messageContainer.className = messageContainer.className.replace('hidden', '');
|
||||
}
|
||||
|
||||
// 自动隐藏
|
||||
setTimeout(() => {
|
||||
(isSuccess ? successMessage : errorMessage).classList.add('hidden');
|
||||
setTimeout(function() {
|
||||
if (isSuccess) {
|
||||
if (successMessage.classList) {
|
||||
successMessage.classList.add('hidden');
|
||||
} else {
|
||||
successMessage.className += ' hidden';
|
||||
}
|
||||
} else {
|
||||
if (errorMessage.classList) {
|
||||
errorMessage.classList.add('hidden');
|
||||
} else {
|
||||
errorMessage.className += ' hidden';
|
||||
}
|
||||
}
|
||||
if (messageContainer.classList) {
|
||||
messageContainer.classList.add('hidden');
|
||||
} else {
|
||||
messageContainer.className += ' hidden';
|
||||
}
|
||||
}, duration);
|
||||
}
|
||||
|
||||
@@ -76,22 +126,32 @@ function showMessage(message, isSuccess = true, duration = 5000) {
|
||||
* @param {string} message - 错误消息内容
|
||||
* @param {string} successId - 成功消息容器的ID
|
||||
*/
|
||||
function showFormError(errorId, messageId, message, successId = '') {
|
||||
const errorContainer = document.getElementById(errorId);
|
||||
const errorMessage = document.getElementById(messageId);
|
||||
const successContainer = successId ? document.getElementById(successId) : null;
|
||||
function showFormError(errorId, messageId, message, successId) {
|
||||
successId = successId || '';
|
||||
|
||||
var errorContainer = document.getElementById(errorId);
|
||||
var errorMessage = document.getElementById(messageId);
|
||||
var successContainer = successId ? document.getElementById(successId) : null;
|
||||
|
||||
if (!errorContainer || !errorMessage) return;
|
||||
|
||||
errorMessage.textContent = message;
|
||||
if (errorContainer.classList) {
|
||||
errorContainer.classList.remove('hidden');
|
||||
|
||||
if (successContainer) {
|
||||
successContainer.classList.add('hidden');
|
||||
} else {
|
||||
errorContainer.className = errorContainer.className.replace('hidden', '');
|
||||
}
|
||||
|
||||
// 滚动到错误信息
|
||||
errorContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
if (successContainer) {
|
||||
if (successContainer.classList) {
|
||||
successContainer.classList.add('hidden');
|
||||
} else {
|
||||
successContainer.className += ' hidden';
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动到错误信息,使用简单滚动方式替代smooth behavior
|
||||
errorContainer.scrollIntoView(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,41 +161,71 @@ function showFormError(errorId, messageId, message, successId = '') {
|
||||
* @param {string} message - 成功消息内容
|
||||
* @param {string} errorId - 错误消息容器的ID
|
||||
*/
|
||||
function showFormSuccess(successId, messageId, message, errorId = '') {
|
||||
const successContainer = document.getElementById(successId);
|
||||
const successMessage = document.getElementById(messageId);
|
||||
const errorContainer = errorId ? document.getElementById(errorId) : null;
|
||||
function showFormSuccess(successId, messageId, message, errorId) {
|
||||
errorId = errorId || '';
|
||||
|
||||
var successContainer = document.getElementById(successId);
|
||||
var successMessage = document.getElementById(messageId);
|
||||
var errorContainer = errorId ? document.getElementById(errorId) : null;
|
||||
|
||||
if (!successContainer || !successMessage) return;
|
||||
|
||||
successMessage.textContent = message;
|
||||
if (successContainer.classList) {
|
||||
successContainer.classList.remove('hidden');
|
||||
|
||||
if (errorContainer) {
|
||||
errorContainer.classList.add('hidden');
|
||||
} else {
|
||||
successContainer.className = successContainer.className.replace('hidden', '');
|
||||
}
|
||||
|
||||
// 滚动到成功信息
|
||||
successContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
if (errorContainer) {
|
||||
if (errorContainer.classList) {
|
||||
errorContainer.classList.add('hidden');
|
||||
} else {
|
||||
errorContainer.className += ' hidden';
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动到成功信息,使用简单滚动方式替代smooth behavior
|
||||
successContainer.scrollIntoView(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起API请求的通用函数
|
||||
* 发起API请求的通用函数 - 使用Promise替代async/await以提高兼容性
|
||||
* @param {string} url - 请求URL
|
||||
* @param {string} method - 请求方法
|
||||
* @param {object} data - 请求数据
|
||||
* @param {object} options - 附加选项
|
||||
* @returns {Promise} - 返回Promise对象
|
||||
*/
|
||||
async function apiRequest(url, method = 'GET', data = null, options = {}) {
|
||||
const defaultOptions = {
|
||||
function apiRequest(url, method, data, options) {
|
||||
// 为参数设置默认值,不使用ES6默认参数
|
||||
method = method || 'GET';
|
||||
data = data || null;
|
||||
options = options || {};
|
||||
|
||||
// 手动合并选项,不使用扩展运算符
|
||||
var defaultOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method,
|
||||
...options
|
||||
method: method
|
||||
};
|
||||
|
||||
// 手动合并options
|
||||
for (var key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
if (key === 'headers' && options.headers) {
|
||||
for (var headerKey in options.headers) {
|
||||
if (options.headers.hasOwnProperty(headerKey)) {
|
||||
defaultOptions.headers[headerKey] = options.headers[headerKey];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
defaultOptions[key] = options[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
// 根据Content-Type处理数据
|
||||
if (defaultOptions.headers['Content-Type'] === 'application/json') {
|
||||
@@ -145,13 +235,23 @@ async function apiRequest(url, method = 'GET', data = null, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url, defaultOptions);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`API请求错误 [${url}]:`, error);
|
||||
throw error;
|
||||
// 使用Promise替代async/await
|
||||
return new Promise(function(resolve, reject) {
|
||||
fetch(url, defaultOptions)
|
||||
.then(function(response) {
|
||||
if (!response.ok) {
|
||||
throw new Error('网络错误');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
resolve(data);
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('API请求错误 [' + url + ']:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +259,7 @@ async function apiRequest(url, method = 'GET', data = null, options = {}) {
|
||||
* @param {string} formId - 表单ID
|
||||
*/
|
||||
function resetForm(formId) {
|
||||
const form = document.getElementById(formId);
|
||||
var form = document.getElementById(formId);
|
||||
if (form) {
|
||||
form.reset();
|
||||
}
|
||||
@@ -171,44 +271,61 @@ function resetForm(formId) {
|
||||
* @param {object} data - 表单数据对象
|
||||
*/
|
||||
function fillForm(formId, data) {
|
||||
const form = document.getElementById(formId);
|
||||
var form = document.getElementById(formId);
|
||||
if (!form || !data) return;
|
||||
|
||||
Object.keys(data).forEach(key => {
|
||||
const element = form.elements[key] || document.getElementById(key);
|
||||
// 使用传统的for-in循环替代forEach
|
||||
for (var key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
var element = form.elements[key] || document.getElementById(key);
|
||||
if (element) {
|
||||
element.value = data[key] || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* 防抖函数 - 使用传统函数替代箭头函数
|
||||
* @param {Function} func - 要防抖的函数
|
||||
* @param {number} delay - 延迟时间(毫秒)
|
||||
* @returns {Function} - 返回防抖后的函数
|
||||
*/
|
||||
function debounce(func, delay) {
|
||||
let timeoutId;
|
||||
return function(...args) {
|
||||
var timeoutId;
|
||||
var that = this;
|
||||
|
||||
return function() {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => func.apply(this, args), delay);
|
||||
timeoutId = setTimeout(function() {
|
||||
func.apply(context || that, args);
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* 节流函数 - 使用传统函数替代箭头函数
|
||||
* @param {Function} func - 要节流的函数
|
||||
* @param {number} limit - 时间限制(毫秒)
|
||||
* @returns {Function} - 返回节流后的函数
|
||||
*/
|
||||
function throttle(func, limit) {
|
||||
let inThrottle;
|
||||
return function(...args) {
|
||||
var inThrottle;
|
||||
var that = this;
|
||||
|
||||
return function() {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
|
||||
if (!inThrottle) {
|
||||
func.apply(this, args);
|
||||
func.apply(context || that, args);
|
||||
inThrottle = true;
|
||||
setTimeout(() => inThrottle = false, limit);
|
||||
setTimeout(function() {
|
||||
inThrottle = false;
|
||||
}, limit);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
// 通用工具函数
|
||||
|
||||
/**
|
||||
* 显示模态框
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function showModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭模态框
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定模态框点击外部关闭事件
|
||||
* @param {string} modalId - 模态框的ID
|
||||
*/
|
||||
function bindModalOutsideClick(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeModal(modalId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示消息提示
|
||||
* @param {string} message - 消息内容
|
||||
* @param {boolean} isSuccess - 是否为成功消息
|
||||
* @param {number} duration - 消息显示时长(毫秒)
|
||||
*/
|
||||
function showMessage(message, isSuccess = true, duration = 5000) {
|
||||
const messageContainer = document.getElementById('messageContainer');
|
||||
const successMessage = document.getElementById('successMessage');
|
||||
const errorMessage = document.getElementById('errorMessage');
|
||||
|
||||
if (!messageContainer || !successMessage || !errorMessage) return;
|
||||
|
||||
if (isSuccess) {
|
||||
successMessage.querySelector('span').textContent = message;
|
||||
successMessage.classList.remove('hidden');
|
||||
errorMessage.classList.add('hidden');
|
||||
} else {
|
||||
errorMessage.querySelector('span').textContent = message;
|
||||
errorMessage.classList.remove('hidden');
|
||||
successMessage.classList.add('hidden');
|
||||
}
|
||||
|
||||
messageContainer.classList.remove('hidden');
|
||||
|
||||
// 自动隐藏
|
||||
setTimeout(() => {
|
||||
(isSuccess ? successMessage : errorMessage).classList.add('hidden');
|
||||
messageContainer.classList.add('hidden');
|
||||
}, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示表单错误消息
|
||||
* @param {string} errorId - 错误容器的ID
|
||||
* @param {string} messageId - 错误消息的ID
|
||||
* @param {string} message - 错误消息内容
|
||||
* @param {string} successId - 成功消息容器的ID
|
||||
*/
|
||||
function showFormError(errorId, messageId, message, successId = '') {
|
||||
const errorContainer = document.getElementById(errorId);
|
||||
const errorMessage = document.getElementById(messageId);
|
||||
const successContainer = successId ? document.getElementById(successId) : null;
|
||||
|
||||
if (!errorContainer || !errorMessage) return;
|
||||
|
||||
errorMessage.textContent = message;
|
||||
errorContainer.classList.remove('hidden');
|
||||
|
||||
if (successContainer) {
|
||||
successContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
// 滚动到错误信息
|
||||
errorContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示表单成功消息
|
||||
* @param {string} successId - 成功容器的ID
|
||||
* @param {string} messageId - 成功消息的ID
|
||||
* @param {string} message - 成功消息内容
|
||||
* @param {string} errorId - 错误消息容器的ID
|
||||
*/
|
||||
function showFormSuccess(successId, messageId, message, errorId = '') {
|
||||
const successContainer = document.getElementById(successId);
|
||||
const successMessage = document.getElementById(messageId);
|
||||
const errorContainer = errorId ? document.getElementById(errorId) : null;
|
||||
|
||||
if (!successContainer || !successMessage) return;
|
||||
|
||||
successMessage.textContent = message;
|
||||
successContainer.classList.remove('hidden');
|
||||
|
||||
if (errorContainer) {
|
||||
errorContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
// 滚动到成功信息
|
||||
successContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起API请求的通用函数
|
||||
* @param {string} url - 请求URL
|
||||
* @param {string} method - 请求方法
|
||||
* @param {object} data - 请求数据
|
||||
* @param {object} options - 附加选项
|
||||
* @returns {Promise} - 返回Promise对象
|
||||
*/
|
||||
async function apiRequest(url, method = 'GET', data = null, options = {}) {
|
||||
const defaultOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method,
|
||||
...options
|
||||
};
|
||||
|
||||
if (data) {
|
||||
// 根据Content-Type处理数据
|
||||
if (defaultOptions.headers['Content-Type'] === 'application/json') {
|
||||
defaultOptions.body = JSON.stringify(data);
|
||||
} else if (defaultOptions.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
|
||||
defaultOptions.body = new URLSearchParams(data);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url, defaultOptions);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`API请求错误 [${url}]:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
* @param {string} formId - 表单ID
|
||||
*/
|
||||
function resetForm(formId) {
|
||||
const form = document.getElementById(formId);
|
||||
if (form) {
|
||||
form.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充表单数据
|
||||
* @param {string} formId - 表单ID
|
||||
* @param {object} data - 表单数据对象
|
||||
*/
|
||||
function fillForm(formId, data) {
|
||||
const form = document.getElementById(formId);
|
||||
if (!form || !data) return;
|
||||
|
||||
Object.keys(data).forEach(key => {
|
||||
const element = form.elements[key] || document.getElementById(key);
|
||||
if (element) {
|
||||
element.value = data[key] || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param {Function} func - 要防抖的函数
|
||||
* @param {number} delay - 延迟时间(毫秒)
|
||||
* @returns {Function} - 返回防抖后的函数
|
||||
*/
|
||||
function debounce(func, delay) {
|
||||
let timeoutId;
|
||||
return function(...args) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => func.apply(this, args), delay);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* @param {Function} func - 要节流的函数
|
||||
* @param {number} limit - 时间限制(毫秒)
|
||||
* @returns {Function} - 返回节流后的函数
|
||||
*/
|
||||
function throttle(func, limit) {
|
||||
let inThrottle;
|
||||
return function(...args) {
|
||||
if (!inThrottle) {
|
||||
func.apply(this, args);
|
||||
inThrottle = true;
|
||||
setTimeout(() => inThrottle = false, limit);
|
||||
}
|
||||
};
|
||||
}
|
||||
+199
-69
@@ -105,7 +105,7 @@
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">查询日期</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">车牌号</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">手机号</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">查询结果</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">登录部门</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">登录IP</th>
|
||||
</tr>
|
||||
@@ -119,12 +119,18 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.phone }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
|
||||
{% if query.results_count > 0 %}
|
||||
{% if query.results_count == -1 %}
|
||||
bg-warning/10 text-warning
|
||||
{% elif query.results_count > 0 %}
|
||||
bg-success/10 text-success
|
||||
{% else %}
|
||||
bg-error/10 text-error
|
||||
{% endif %}">
|
||||
{% if query.results_count == -1 %}
|
||||
待查询
|
||||
{% else %}
|
||||
{{ query.results_count }} 条记录
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.department }}</td>
|
||||
@@ -219,59 +225,90 @@
|
||||
// 等待DOM加载完成
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 获取DOM元素
|
||||
const addQueryBtn = document.getElementById('addQueryBtn');
|
||||
const addQueryModal = document.getElementById('addQueryModal');
|
||||
const closeAddModal = document.getElementById('closeAddModal');
|
||||
const cancelAddBtn = document.getElementById('cancelAddBtn');
|
||||
const addQueryForm = document.getElementById('addQueryForm');
|
||||
const addQueryLoading = document.getElementById('addQueryLoading');
|
||||
const detailModal = document.getElementById('detailModal');
|
||||
const closeModal = document.getElementById('closeModal');
|
||||
const loadingState = document.getElementById('loadingState');
|
||||
const noResultState = document.getElementById('noResultState');
|
||||
const resultList = document.getElementById('resultList');
|
||||
const carOwnerCards = document.getElementById('carOwnerCards');
|
||||
var addQueryBtn = document.getElementById('addQueryBtn');
|
||||
var addQueryModal = document.getElementById('addQueryModal');
|
||||
var closeAddModal = document.getElementById('closeAddModal');
|
||||
var cancelAddBtn = document.getElementById('cancelAddBtn');
|
||||
var addQueryForm = document.getElementById('addQueryForm');
|
||||
var addQueryLoading = document.getElementById('addQueryLoading');
|
||||
var detailModal = document.getElementById('detailModal');
|
||||
var closeModal = document.getElementById('closeModal');
|
||||
var loadingState = document.getElementById('loadingState');
|
||||
var noResultState = document.getElementById('noResultState');
|
||||
var resultList = document.getElementById('resultList');
|
||||
var carOwnerCards = document.getElementById('carOwnerCards');
|
||||
|
||||
// 为查询历史记录行添加点击事件
|
||||
document.querySelectorAll('tr[data-history-id]').forEach(row => {
|
||||
row.addEventListener('click', function() {
|
||||
const historyId = this.getAttribute('data-history-id');
|
||||
var rows = document.querySelectorAll('tr[data-history-id]');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
rows[i].addEventListener('click', function() {
|
||||
var historyId = this.getAttribute('data-history-id');
|
||||
loadHistoryDetail(historyId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 增加查询按钮点击事件
|
||||
addQueryBtn.addEventListener('click', function() {
|
||||
// 兼容classList API
|
||||
if (addQueryModal.classList) {
|
||||
addQueryModal.classList.remove('hidden');
|
||||
} else {
|
||||
addQueryModal.className = addQueryModal.className.replace('hidden', '');
|
||||
}
|
||||
addQueryForm.reset();
|
||||
});
|
||||
|
||||
// 关闭增加查询模态框
|
||||
closeAddModal.addEventListener('click', function() {
|
||||
// 兼容classList API
|
||||
if (addQueryModal.classList) {
|
||||
addQueryModal.classList.add('hidden');
|
||||
} else {
|
||||
addQueryModal.className += ' hidden';
|
||||
}
|
||||
});
|
||||
|
||||
// 取消增加查询
|
||||
cancelAddBtn.addEventListener('click', function() {
|
||||
// 兼容classList API
|
||||
if (addQueryModal.classList) {
|
||||
addQueryModal.classList.add('hidden');
|
||||
} else {
|
||||
addQueryModal.className += ' hidden';
|
||||
}
|
||||
});
|
||||
|
||||
// 点击增加查询模态框背景关闭
|
||||
addQueryModal.addEventListener('click', function(e) {
|
||||
if (e.target === addQueryModal) {
|
||||
// 兼容classList API
|
||||
if (addQueryModal.classList) {
|
||||
addQueryModal.classList.add('hidden');
|
||||
} else {
|
||||
addQueryModal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭详情模态框
|
||||
closeModal.addEventListener('click', function() {
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.add('hidden');
|
||||
} else {
|
||||
detailModal.className += ' hidden';
|
||||
}
|
||||
});
|
||||
|
||||
// 点击详情模态框背景关闭
|
||||
detailModal.addEventListener('click', function(e) {
|
||||
if (e.target === detailModal) {
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.add('hidden');
|
||||
} else {
|
||||
detailModal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -279,8 +316,8 @@
|
||||
addQueryForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const plateNumber = document.getElementById('add_plate_number').value.trim();
|
||||
const phone = document.getElementById('add_phone').value.trim();
|
||||
var plateNumber = document.getElementById('add_plate_number').value.trim();
|
||||
var phone = document.getElementById('add_phone').value.trim();
|
||||
|
||||
if (!plateNumber && !phone) {
|
||||
alert('请至少输入车牌号或手机号');
|
||||
@@ -288,107 +325,179 @@
|
||||
}
|
||||
|
||||
// 显示加载状态
|
||||
// 兼容classList API
|
||||
if (addQueryForm.classList) {
|
||||
addQueryForm.classList.add('hidden');
|
||||
} else {
|
||||
addQueryForm.className += ' hidden';
|
||||
}
|
||||
if (addQueryLoading.classList) {
|
||||
addQueryLoading.classList.remove('hidden');
|
||||
} else {
|
||||
addQueryLoading.className = addQueryLoading.className.replace('hidden', '');
|
||||
}
|
||||
|
||||
// 构建表单数据
|
||||
const formData = new FormData();
|
||||
var formData = new FormData();
|
||||
formData.append('plate_number', plateNumber);
|
||||
formData.append('phone', phone);
|
||||
formData.append('is_add_query', 'true');
|
||||
|
||||
// 发送请求到查询路由
|
||||
fetch('/query', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
.then(function(response) {
|
||||
if (!response.ok) {
|
||||
throw new Error('网络错误');
|
||||
}
|
||||
// 重新加载页面以显示新的查询记录
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(error => {
|
||||
.catch(function(error) {
|
||||
console.error('Error submitting query:', error);
|
||||
alert('提交失败,请重试');
|
||||
// 恢复表单显示
|
||||
// 兼容classList API
|
||||
if (addQueryForm.classList) {
|
||||
addQueryForm.classList.remove('hidden');
|
||||
} else {
|
||||
addQueryForm.className = addQueryForm.className.replace('hidden', '');
|
||||
}
|
||||
if (addQueryLoading.classList) {
|
||||
addQueryLoading.classList.add('hidden');
|
||||
} else {
|
||||
addQueryLoading.className += ' hidden';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 加载查询历史详情
|
||||
function loadHistoryDetail(historyId) {
|
||||
// 显示模态框和加载状态
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.remove('hidden');
|
||||
} else {
|
||||
detailModal.className = detailModal.className.replace('hidden', '');
|
||||
}
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.remove('hidden');
|
||||
} else {
|
||||
loadingState.className = loadingState.className.replace('hidden', '');
|
||||
}
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.add('hidden');
|
||||
} else {
|
||||
noResultState.className += ' hidden';
|
||||
}
|
||||
if (resultList.classList) {
|
||||
resultList.classList.add('hidden');
|
||||
} else {
|
||||
resultList.className += ' hidden';
|
||||
}
|
||||
carOwnerCards.innerHTML = '';
|
||||
|
||||
// 发送AJAX请求获取详情
|
||||
fetch(`/query_history_detail/${historyId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
fetch('/query_history_detail/' + historyId)
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
// 隐藏加载状态
|
||||
// 兼容classList API
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.add('hidden');
|
||||
} else {
|
||||
loadingState.className += ' hidden';
|
||||
}
|
||||
|
||||
if (data.error) {
|
||||
// 显示错误信息
|
||||
noResultState.querySelector('p').textContent = data.error;
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
}
|
||||
} else if (data.car_owners && data.car_owners.length > 0) {
|
||||
// 显示结果列表
|
||||
// 兼容classList API
|
||||
if (resultList.classList) {
|
||||
resultList.classList.remove('hidden');
|
||||
} else {
|
||||
resultList.className = resultList.className.replace('hidden', '');
|
||||
}
|
||||
|
||||
// 添加车辆信息卡片
|
||||
data.car_owners.forEach(carOwner => {
|
||||
const card = document.createElement('div');
|
||||
for (var i = 0; i < data.car_owners.length; i++) {
|
||||
var carOwner = data.car_owners[i];
|
||||
var card = document.createElement('div');
|
||||
card.className = 'bg-white border border-gray-200 rounded-lg p-5 shadow-sm hover:shadow-md transition-shadow duration-200';
|
||||
card.innerHTML = `
|
||||
<h4 class="text-lg font-medium text-gray-800 mb-4 flex items-center">
|
||||
<i class="fa fa-car text-primary mr-2"></i>
|
||||
车辆信息
|
||||
</h4>
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">车牌号:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.plate_number}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">手机号:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.phone}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">车主姓名:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.name}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">身份证号:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.id_card}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">电子邮箱:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.email || '未提供'}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-500">居住地址:</span>
|
||||
<span class="font-medium text-gray-800">${carOwner.address || '未提供'}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 使用字符串拼接替代模板字符串
|
||||
var cardHtml = '';
|
||||
cardHtml += '<h4 class="text-lg font-medium text-gray-800 mb-4 flex items-center">';
|
||||
cardHtml += ' <i class="fa fa-car text-primary mr-2"></i>';
|
||||
cardHtml += ' 车辆信息';
|
||||
cardHtml += '</h4>';
|
||||
cardHtml += '<div class="space-y-3">';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">车牌号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.plate_number || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">手机号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.phone || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">车主姓名:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.name || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">身份证号:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.id_card || '') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">电子邮箱:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.email || '未提供') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += ' <div class="flex justify-between items-center">';
|
||||
cardHtml += ' <span class="text-gray-500">居住地址:</span>';
|
||||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.address || '未提供') + '</span>';
|
||||
cardHtml += ' </div>';
|
||||
cardHtml += '</div>';
|
||||
|
||||
card.innerHTML = cardHtml;
|
||||
carOwnerCards.appendChild(card);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 显示无结果状态
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
.catch(function(error) {
|
||||
// 隐藏加载状态,显示错误信息
|
||||
// 兼容classList API
|
||||
if (loadingState.classList) {
|
||||
loadingState.classList.add('hidden');
|
||||
} else {
|
||||
loadingState.className += ' hidden';
|
||||
}
|
||||
noResultState.querySelector('p').textContent = '加载详情时发生错误';
|
||||
// 兼容classList API
|
||||
if (noResultState.classList) {
|
||||
noResultState.classList.remove('hidden');
|
||||
} else {
|
||||
noResultState.className = noResultState.className.replace('hidden', '');
|
||||
}
|
||||
console.error('Error loading history detail:', error);
|
||||
});
|
||||
}
|
||||
@@ -396,17 +505,19 @@
|
||||
// 响应式处理:当窗口大小改变时,重新绑定事件(因为表格可能会重新渲染)
|
||||
window.addEventListener('resize', function() {
|
||||
// 重新绑定事件到查询历史记录行
|
||||
document.querySelectorAll('tr[data-history-id]').forEach(row => {
|
||||
var rows = document.querySelectorAll('tr[data-history-id]');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
// 先移除旧的事件监听器
|
||||
const newRow = row.cloneNode(true);
|
||||
var newRow = row.cloneNode(true);
|
||||
row.parentNode.replaceChild(newRow, row);
|
||||
|
||||
// 添加新的事件监听器
|
||||
newRow.addEventListener('click', function() {
|
||||
const historyId = this.getAttribute('data-history-id');
|
||||
var historyId = this.getAttribute('data-history-id');
|
||||
loadHistoryDetail(historyId);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -416,14 +527,33 @@
|
||||
|
||||
<script>
|
||||
// 全局搜索变量
|
||||
let searchQuery = '';
|
||||
var searchQuery = '';
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// ESC键关闭详情弹窗
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape' && !document.getElementById('detailModal').classList.contains('hidden')) {
|
||||
document.getElementById('detailModal').classList.add('hidden');
|
||||
// 使用keyCode替代key,提高兼容性
|
||||
var key = e.key || e.keyCode;
|
||||
var isEscape = key === 'Escape' || key === 'Esc' || key === 27;
|
||||
|
||||
var detailModal = document.getElementById('detailModal');
|
||||
var isHidden = false;
|
||||
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
isHidden = detailModal.classList.contains('hidden');
|
||||
} else {
|
||||
isHidden = detailModal.className.indexOf('hidden') !== -1;
|
||||
}
|
||||
|
||||
if (isEscape && !isHidden) {
|
||||
// 兼容classList API
|
||||
if (detailModal.classList) {
|
||||
detailModal.classList.add('hidden');
|
||||
} else {
|
||||
detailModal.className += ' hidden';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -286,11 +286,11 @@
|
||||
|
||||
// 加载用户列表
|
||||
function loadUsers() {
|
||||
apiRequest('{{ url_for('user.get_users') }}')
|
||||
apiRequest('/api/users')
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
usersData = data.users;
|
||||
totalUsers = usersData.length;
|
||||
usersData = data.data;
|
||||
totalUsers = data.total;
|
||||
renderUsersTable();
|
||||
} else {
|
||||
showMessage('加载用户列表失败:' + (data.error || '未知错误'), false);
|
||||
@@ -377,19 +377,18 @@
|
||||
const filterDepartment = document.getElementById('filterDepartment').value;
|
||||
const filterStatus = document.getElementById('filterStatus').value;
|
||||
|
||||
fetch('{{ url_for('user.get_users') }}')
|
||||
.then(response => response.json())
|
||||
apiRequest('/api/users')
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// 应用过滤条件
|
||||
usersData = data.users.filter(user => {
|
||||
usersData = data.data.filter(user => {
|
||||
const matchesUsername = user.username.toLowerCase().includes(searchUsername);
|
||||
const matchesDepartment = !filterDepartment || user.department === filterDepartment;
|
||||
const matchesStatus = !filterStatus || user.status === filterStatus;
|
||||
return matchesUsername && matchesDepartment && matchesStatus;
|
||||
});
|
||||
|
||||
totalUsers = usersData.length;
|
||||
totalUsers = data.total;
|
||||
currentPage = 1; // 重置到第一页
|
||||
renderUsersTable();
|
||||
} else {
|
||||
|
||||
+67
-6
@@ -1,10 +1,13 @@
|
||||
import sqlite3
|
||||
import datetime
|
||||
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
# 连接到数据库并确保users表结构正确
|
||||
def update_users_table():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查users表的当前结构
|
||||
@@ -42,7 +45,10 @@ def update_users_table():
|
||||
print("已更新admin用户信息")
|
||||
|
||||
# 提交更改
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"提交更改时出错: {e}")
|
||||
|
||||
# 再次验证表结构
|
||||
cursor.execute("PRAGMA table_info(users)")
|
||||
@@ -59,14 +65,69 @@ def update_users_table():
|
||||
print(f"ID: {admin_user[0]}, 用户名: {admin_user[1]}, 姓名: {admin_user[2]}, 电话: {admin_user[3]}, 部门: {admin_user[4]}")
|
||||
|
||||
# 关闭连接
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
print("\n数据库更新完成")
|
||||
|
||||
except Exception as e:
|
||||
print(f"更新数据库时出错: {str(e)}")
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals():
|
||||
conn.close()
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
|
||||
# 更新数据库中的数据
|
||||
def update_database():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查是否存在测试数据表
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='test_data'")
|
||||
if not cursor.fetchone():
|
||||
# 如果不存在,创建测试数据表
|
||||
cursor.execute('''
|
||||
CREATE TABLE test_data (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
value TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
conn.commit()
|
||||
print("测试数据表创建成功")
|
||||
|
||||
# 检查是否有测试数据,如果没有则插入
|
||||
cursor.execute("SELECT COUNT(*) FROM test_data")
|
||||
count = cursor.fetchone()[0]
|
||||
|
||||
if count == 0:
|
||||
# 插入测试数据
|
||||
test_data = [
|
||||
('测试数据1', 'value1', datetime.datetime.now()),
|
||||
('测试数据2', 'value2', datetime.datetime.now()),
|
||||
('测试数据3', 'value3', datetime.datetime.now())
|
||||
]
|
||||
|
||||
for data in test_data:
|
||||
cursor.execute(
|
||||
"INSERT INTO test_data (name, value, create_time, update_time) VALUES (?, ?, ?, ?)",
|
||||
data
|
||||
)
|
||||
conn.commit()
|
||||
print("测试数据插入成功")
|
||||
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
return True, "数据库更新成功"
|
||||
|
||||
except Exception as e:
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
return False, f"数据库更新失败:{str(e)}"
|
||||
|
||||
# 如果直接运行此脚本,则执行更新操作
|
||||
if __name__ == "__main__":
|
||||
update_users_table()
|
||||
success, message = update_database()
|
||||
print(message)
|
||||
@@ -1,13 +1,15 @@
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, session
|
||||
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
# 创建用户相关的蓝图
|
||||
bp = Blueprint('user', __name__)
|
||||
|
||||
# 初始化数据库(用户相关部分)
|
||||
def init_user_db():
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 创建用户表
|
||||
@@ -48,8 +50,12 @@ def init_user_db():
|
||||
user
|
||||
)
|
||||
|
||||
try:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"初始化用户数据库时出错: {e}")
|
||||
finally:
|
||||
close_db_connection(conn)
|
||||
|
||||
# 登录路由
|
||||
@bp.route('/login', methods=['GET', 'POST'])
|
||||
@@ -59,7 +65,7 @@ def login():
|
||||
password = request.form.get('password')
|
||||
|
||||
# 连接数据库
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 验证用户名和密码
|
||||
@@ -69,7 +75,7 @@ def login():
|
||||
if user:
|
||||
# 检查用户状态
|
||||
if user[6] != 'active':
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return render_template('login.html', error='用户已被禁用')
|
||||
|
||||
# 设置会话信息
|
||||
@@ -78,14 +84,12 @@ def login():
|
||||
session['department'] = user[5] # 部门
|
||||
session['login_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
# 登录成功,跳转到查询页面
|
||||
return redirect(url_for('query'))
|
||||
else:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return render_template('login.html', error='用户名或密码错误')
|
||||
|
||||
return render_template('login.html')
|
||||
@@ -114,72 +118,31 @@ def register():
|
||||
return render_template('register.html', error='密码长度至少8位,且必须包含字母和数字')
|
||||
|
||||
# 连接数据库,检查用户名是否已存在
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||
if cursor.fetchone():
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return render_template('register.html', error='用户名已存在')
|
||||
|
||||
try:
|
||||
# 插入新用户
|
||||
cursor.execute(
|
||||
"INSERT INTO users (username, password, name, phone, department) VALUES (?, ?, ?, ?, ?)",
|
||||
(username, password, name, phone, department)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
# 注册成功,跳转到登录页并显示成功消息
|
||||
return render_template('login.html', success='注册成功,请登录')
|
||||
close_db_connection(conn)
|
||||
|
||||
# 注册成功,跳转到登录页面
|
||||
return redirect(url_for('user.login', success='注册成功,请登录'))
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
return render_template('register.html', error=f'注册失败,请重试。错误:{str(e)}')
|
||||
close_db_connection(conn)
|
||||
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']))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return jsonify({'success': True, 'message': '修改密码成功,请重新登录'})
|
||||
|
||||
# 获取个人信息路由
|
||||
@bp.route('/get_user_profile', methods=['GET'])
|
||||
def get_user_profile():
|
||||
@@ -187,12 +150,12 @@ def get_user_profile():
|
||||
return jsonify({'success': False, 'error': '未登录'}), 401
|
||||
|
||||
# 连接数据库,获取用户信息
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT username, name, phone, department FROM users WHERE username = ?", (session['username'],))
|
||||
user = cursor.fetchone()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
if not user:
|
||||
return jsonify({'success': False, 'error': '用户不存在'})
|
||||
@@ -207,81 +170,8 @@ def get_user_profile():
|
||||
|
||||
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('/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'])
|
||||
# 获取所有用户列表的API
|
||||
@bp.route('/api/users', methods=['GET'])
|
||||
def get_users():
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'error': '未登录'}), 401
|
||||
@@ -290,13 +180,61 @@ def get_users():
|
||||
if session['username'] != 'admin':
|
||||
return jsonify({'success': False, 'error': '无权限访问'}), 403
|
||||
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
# 获取URL参数中的页码、每页数量、排序字段和排序方式
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('pageSize', 10, type=int)
|
||||
sort_field = request.args.get('sortField', 'id')
|
||||
sort_order = request.args.get('sortOrder', 'asc')
|
||||
department = request.args.get('department', '')
|
||||
search = request.args.get('search', '')
|
||||
|
||||
# 验证排序字段是否有效
|
||||
valid_sort_fields = ['id', 'username', 'name', 'phone', 'department', 'status']
|
||||
if sort_field not in valid_sort_fields:
|
||||
sort_field = 'id'
|
||||
|
||||
# 验证排序方式是否有效
|
||||
if sort_order not in ['asc', 'desc']:
|
||||
sort_order = 'asc'
|
||||
|
||||
# 计算偏移量
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取所有用户信息
|
||||
cursor.execute("SELECT id, username, name, department, status FROM users")
|
||||
# 构建查询条件
|
||||
conditions = []
|
||||
params = []
|
||||
|
||||
if department:
|
||||
conditions.append("department = ?")
|
||||
params.append(department)
|
||||
|
||||
if search:
|
||||
conditions.append("(username LIKE ? OR name LIKE ? OR phone LIKE ?)")
|
||||
params.extend([f'%{search}%', f'%{search}%', f'%{search}%'])
|
||||
|
||||
# 构建SQL查询语句
|
||||
where_clause = " AND ".join(conditions) if conditions else ""
|
||||
if where_clause:
|
||||
where_clause = "WHERE " + where_clause
|
||||
|
||||
# 查询用户列表
|
||||
cursor.execute(
|
||||
f"SELECT id, username, name, phone, department, status FROM users {where_clause} ORDER BY {sort_field} {sort_order} LIMIT ? OFFSET ?",
|
||||
params + [page_size, offset]
|
||||
)
|
||||
users = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
# 查询总记录数
|
||||
cursor.execute(f"SELECT COUNT(*) FROM users {where_clause}", params)
|
||||
total = cursor.fetchone()[0]
|
||||
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
|
||||
# 格式化用户数据
|
||||
formatted_users = []
|
||||
@@ -305,11 +243,23 @@ def get_users():
|
||||
'id': user[0],
|
||||
'username': user[1],
|
||||
'name': user[2],
|
||||
'department': user[3],
|
||||
'status': user[4]
|
||||
'phone': user[3],
|
||||
'department': user[4],
|
||||
'status': user[5]
|
||||
})
|
||||
|
||||
return jsonify({'success': True, 'users': formatted_users})
|
||||
# 返回分页结果
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': formatted_users,
|
||||
'total': total,
|
||||
'page': page,
|
||||
'pageSize': page_size
|
||||
})
|
||||
except Exception as e:
|
||||
# 确保在异常情况下也关闭连接
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
# 更新用户状态路由
|
||||
@bp.route('/update_user_status', methods=['POST'])
|
||||
@@ -329,29 +279,21 @@ def update_user_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': '不能禁用管理员用户'})
|
||||
if user_id == 1:
|
||||
return jsonify({'success': False, 'error': '不能修改管理员用户的状态'})
|
||||
|
||||
# 更新用户状态
|
||||
try:
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("UPDATE users SET status = ? WHERE id = ?", (status, user_id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
return jsonify({'success': True, 'message': '用户状态更新成功'})
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': f'更新失败:{str(e)}'})
|
||||
|
||||
# 更新用户部门路由
|
||||
@@ -374,15 +316,15 @@ def update_user_department():
|
||||
|
||||
# 更新用户部门
|
||||
try:
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("UPDATE users SET department = ? WHERE id = ?", (department, user_id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
return jsonify({'success': True, 'message': '部门信息更新成功'})
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': f'更新失败:{str(e)}'})
|
||||
|
||||
# 重置用户密码路由
|
||||
@@ -407,7 +349,7 @@ def reset_user_password():
|
||||
default_password = 'default123'
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查用户ID和用户名是否匹配
|
||||
@@ -415,26 +357,48 @@ def reset_user_password():
|
||||
db_user_id = cursor.fetchone()
|
||||
|
||||
if not db_user_id or db_user_id[0] != user_id:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': '用户信息不匹配'})
|
||||
|
||||
# 更新users表中的密码
|
||||
cursor.execute("UPDATE users SET password = ? WHERE id = ?", (default_password, user_id))
|
||||
|
||||
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
return jsonify({'success': True, 'message': '密码已初始化为:' + default_password})
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
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 = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT DISTINCT department FROM users")
|
||||
departments = [dept[0] for dept in cursor.fetchall()]
|
||||
close_db_connection(conn)
|
||||
|
||||
return render_template('users_management.html', departments=departments)
|
||||
|
||||
# 创建参数配置表(如果不存在)
|
||||
def create_parameter_config_table():
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 创建参数配置表
|
||||
@@ -459,10 +423,12 @@ def create_parameter_config_table():
|
||||
"INSERT INTO parameter_config (param1, param2, param3, param4, param5, update_time) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
('默认参数1', '默认参数2', '默认参数3', '默认参数4', '默认参数5', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
)
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"插入参数配置数据时出错: {e}")
|
||||
|
||||
conn.close()
|
||||
|
||||
close_db_connection(conn)
|
||||
|
||||
# 获取参数配置路由
|
||||
@bp.route('/get_parameter_config', methods=['GET'])
|
||||
@@ -470,32 +436,38 @@ def get_parameter_config():
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'error': '未登录'}), 401
|
||||
|
||||
# 确保参数配置表存在
|
||||
create_parameter_config_table()
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询参数配置
|
||||
cursor.execute("SELECT param1, param2, param3, param4, param5, update_time FROM parameter_config ORDER BY update_time DESC LIMIT 1")
|
||||
# 获取最新的参数配置
|
||||
cursor.execute("SELECT param1, param2, param3, param4, param5 FROM parameter_config ORDER BY update_time DESC LIMIT 1")
|
||||
config = cursor.fetchone()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
if not config:
|
||||
return jsonify({'success': False, 'error': '未找到参数配置'})
|
||||
|
||||
# 构造返回数据
|
||||
# 构建符合前端期望格式的响应
|
||||
parameters = {
|
||||
'param1': config[0],
|
||||
'param2': config[1],
|
||||
'param3': config[2],
|
||||
'param4': config[3],
|
||||
'param5': config[4],
|
||||
'update_time': config[5]
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
return jsonify({'success': True, 'parameters': parameters})
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'parameters': parameters
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': f'获取参数配置失败:{str(e)}'})
|
||||
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': str(e)})
|
||||
|
||||
# 保存参数配置路由
|
||||
@bp.route('/save_parameter_config', methods=['POST'])
|
||||
@@ -503,64 +475,40 @@ def save_parameter_config():
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'error': '未登录'}), 401
|
||||
|
||||
# 只有管理员可以修改参数配置
|
||||
if session['username'] != 'admin':
|
||||
return jsonify({'success': False, 'error': '无权限修改参数配置'}), 403
|
||||
# 确保参数配置表存在
|
||||
create_parameter_config_table()
|
||||
|
||||
# 获取请求数据
|
||||
data = request.get_json()
|
||||
if not data:
|
||||
return jsonify({'success': False, 'error': '请求数据格式错误'}), 400
|
||||
|
||||
param1 = data.get('param1', '').strip()
|
||||
param2 = data.get('param2', '').strip()
|
||||
param3 = data.get('param3', '').strip()
|
||||
param4 = data.get('param4', '').strip()
|
||||
param5 = data.get('param5', '').strip()
|
||||
|
||||
# 验证参数
|
||||
if not param1:
|
||||
return jsonify({'success': False, 'error': '参数1不能为空'})
|
||||
param1 = data.get('param1')
|
||||
param2 = data.get('param2')
|
||||
param3 = data.get('param3')
|
||||
param4 = data.get('param4')
|
||||
param5 = data.get('param5')
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 更新参数配置
|
||||
cursor.execute(
|
||||
"UPDATE parameter_config SET param1 = ?, param2 = ?, param3 = ?, param4 = ?, param5 = ?, update_time = ? WHERE id = 1",
|
||||
(param1, param2, param3, param4, param5, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
)
|
||||
|
||||
# 如果没有更新任何记录,插入新记录
|
||||
if cursor.rowcount == 0:
|
||||
# 插入新的参数配置记录(不更新旧记录,而是插入新记录)
|
||||
cursor.execute(
|
||||
"INSERT INTO parameter_config (param1, param2, param3, param4, param5, update_time) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(param1, param2, param3, param4, param5, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
return jsonify({'success': True, 'message': '参数配置保存成功'})
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': f'保存参数配置失败:{str(e)}'})
|
||||
|
||||
close_db_connection(conn)
|
||||
return jsonify({'success': False, 'error': str(e)})
|
||||
|
||||
# 参数配置页面路由
|
||||
@bp.route('/parameter_config_page', methods=['GET', 'POST'])
|
||||
@bp.route('/parameter_config_page')
|
||||
def parameter_config_page():
|
||||
if 'username' not in session:
|
||||
return redirect(url_for('user.login'))
|
||||
|
||||
# 只有管理员可以访问参数配置页面
|
||||
if session['username'] != 'admin':
|
||||
return redirect(url_for('user.user_profile_page', error='无权限访问参数配置页面'))
|
||||
|
||||
# 渲染参数配置页面
|
||||
return render_template('parameter_config.html', current_year=datetime.now().year)
|
||||
|
||||
|
||||
return render_template('parameter_config.html')
|
||||
|
||||
# 修改密码页面路由
|
||||
@bp.route('/change_password_page', methods=['GET', 'POST'])
|
||||
@@ -586,7 +534,7 @@ def change_password_page():
|
||||
return render_template('change_password.html', error='新密码长度至少8位,且必须包含字母和数字')
|
||||
|
||||
# 连接数据库,验证旧密码并更新新密码
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 验证旧密码是否正确
|
||||
@@ -594,20 +542,25 @@ def change_password_page():
|
||||
result = cursor.fetchone()
|
||||
|
||||
if not result or result[0] != old_password:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return render_template('change_password.html', error='旧密码不正确')
|
||||
|
||||
# 更新密码
|
||||
cursor.execute("UPDATE users SET password = ? WHERE username = ?", (new_password, session['username']))
|
||||
try:
|
||||
cursor.execute(
|
||||
"UPDATE users SET password = ? WHERE username = ?",
|
||||
(new_password, session['username'])
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
# 密码修改成功,先执行退出功能,再跳转到登录页面
|
||||
session.clear()
|
||||
return redirect(url_for('user.login', success='修改密码成功,请重新登录'))
|
||||
# 密码修改成功,跳转到登录页面
|
||||
return redirect(url_for('user.login', success='密码修改成功,请重新登录'))
|
||||
except Exception as e:
|
||||
close_db_connection(conn)
|
||||
return render_template('change_password.html', error=f'密码修改失败:{str(e)}')
|
||||
|
||||
# GET请求,渲染修改密码页面
|
||||
return render_template('change_password.html', current_year=datetime.now().year)
|
||||
return render_template('change_password.html')
|
||||
|
||||
# 个人信息页面路由
|
||||
@bp.route('/user_profile_page', methods=['GET', 'POST'])
|
||||
@@ -616,11 +569,11 @@ def user_profile_page():
|
||||
return redirect(url_for('user.login'))
|
||||
|
||||
# 连接数据库,获取用户信息
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT username, name, phone, department FROM users WHERE username = ?", (session['username'],))
|
||||
user_tuple = cursor.fetchone()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
if not user_tuple:
|
||||
return redirect(url_for('user.login', error='用户不存在'))
|
||||
@@ -643,7 +596,7 @@ def user_profile_page():
|
||||
return render_template('user_profile.html', user=user, error='请填写所有必填字段', current_year=datetime.now().year)
|
||||
|
||||
# 连接数据库,更新用户信息
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
@@ -657,14 +610,14 @@ def user_profile_page():
|
||||
session['department'] = department
|
||||
session['name'] = name
|
||||
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
# 重新获取用户信息
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT username, name, phone, department FROM users WHERE username = ?", (session['username'],))
|
||||
updated_user_tuple = cursor.fetchone()
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
|
||||
# 将元组转换为字典
|
||||
updated_user = {
|
||||
@@ -676,7 +629,7 @@ def user_profile_page():
|
||||
|
||||
return render_template('user_profile.html', user=updated_user, success='个人信息更新成功', current_year=datetime.now().year)
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
close_db_connection(conn)
|
||||
return render_template('user_profile.html', user=user, error=f'更新失败,请重试。错误:{str(e)}', current_year=datetime.now().year)
|
||||
|
||||
# GET请求,渲染个人信息页面
|
||||
|
||||
+55
-27
@@ -1,41 +1,69 @@
|
||||
import sqlite3
|
||||
# 导入数据库工具
|
||||
from db_utils import get_db_connection, close_db_connection
|
||||
|
||||
# 连接到数据库并验证users表结构
|
||||
def verify_users_table():
|
||||
# 验证数据库结构是否完整
|
||||
def verify_database_structure():
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = sqlite3.connect('car_info.db')
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 检查users表的当前结构
|
||||
print("验证users表结构:")
|
||||
cursor.execute("PRAGMA table_info(users)")
|
||||
# 需要检查的表
|
||||
tables_to_check = ['users', 'query_records']
|
||||
verification_results = []
|
||||
|
||||
for table in tables_to_check:
|
||||
# 检查表是否存在
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table,))
|
||||
table_exists = cursor.fetchone() is not None
|
||||
|
||||
if table_exists:
|
||||
# 检查表的列结构
|
||||
cursor.execute(f"PRAGMA table_info({table})")
|
||||
columns = cursor.fetchall()
|
||||
for column in columns:
|
||||
print(f"字段名: {column[1]}, 类型: {column[2]}, 是否可空: {column[3]}")
|
||||
column_names = [col[1] for col in columns]
|
||||
|
||||
# 检查admin用户的信息
|
||||
print("\n验证admin用户信息:")
|
||||
cursor.execute("SELECT id, username, name, phone, department FROM users WHERE username = ?", ('admin',))
|
||||
admin_user = cursor.fetchone()
|
||||
if admin_user:
|
||||
print(f"ID: {admin_user[0]}")
|
||||
print(f"用户名: {admin_user[1]}")
|
||||
print(f"姓名: {admin_user[2]}")
|
||||
print(f"电话: {admin_user[3]}")
|
||||
print(f"部门: {admin_user[4]}")
|
||||
verification_results.append({
|
||||
"table": table,
|
||||
"exists": True,
|
||||
"column_count": len(columns),
|
||||
"columns": column_names
|
||||
})
|
||||
else:
|
||||
print("未找到admin用户")
|
||||
verification_results.append({
|
||||
"table": table,
|
||||
"exists": False,
|
||||
"column_count": 0,
|
||||
"columns": []
|
||||
})
|
||||
|
||||
# 关闭连接
|
||||
conn.close()
|
||||
print("\n数据库验证完成")
|
||||
# 关闭数据库连接
|
||||
close_db_connection(conn)
|
||||
|
||||
# 构造返回结果
|
||||
all_tables_exist = all(result['exists'] for result in verification_results)
|
||||
|
||||
return {
|
||||
"success": all_tables_exist,
|
||||
"results": verification_results
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"验证数据库时出错: {str(e)}")
|
||||
# 确保在异常情况下也关闭连接
|
||||
if 'conn' in locals():
|
||||
conn.close()
|
||||
if 'conn' in locals() and conn:
|
||||
close_db_connection(conn)
|
||||
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# 如果直接运行此脚本,则执行验证操作
|
||||
if __name__ == "__main__":
|
||||
verify_users_table()
|
||||
result = verify_database_structure()
|
||||
print(f"数据库结构验证: {'通过' if result['success'] else '失败'}")
|
||||
if result['success']:
|
||||
print("验证详情:")
|
||||
for table_result in result['results']:
|
||||
print(f" - 表 {table_result['table']}: 存在,包含 {table_result['column_count']} 个字段")
|
||||
else:
|
||||
print(f"错误信息: {result['error']}")
|
||||
Reference in New Issue
Block a user