333 lines
10 KiB
Python
333 lines
10 KiB
Python
![]() |
from flask import Blueprint, request, jsonify, g, current_app
|
|||
|
import sqlite3
|
|||
|
from datetime import datetime
|
|||
|
|
|||
|
bp = Blueprint('personnel', __name__, url_prefix='/personnel')
|
|||
|
|
|||
|
# 定义全局有效的权限级别
|
|||
|
VALID_PERMISSIONS = {'Admin', 'Supervisor', 'Operator'}
|
|||
|
|
|||
|
# 数据库连接
|
|||
|
def get_db():
|
|||
|
if 'db' not in g:
|
|||
|
g.db = sqlite3.connect(
|
|||
|
current_app.config['DATABASE'],
|
|||
|
check_same_thread=False
|
|||
|
)
|
|||
|
g.db.row_factory = sqlite3.Row
|
|||
|
return g.db
|
|||
|
|
|||
|
# 关闭数据库连接
|
|||
|
@bp.teardown_request
|
|||
|
def close_db_connection(exception=None):
|
|||
|
db = g.pop('db', None)
|
|||
|
if db is not None:
|
|||
|
db.close()
|
|||
|
|
|||
|
# 创建表(初始化数据库)
|
|||
|
@bp.cli.command('init-db')
|
|||
|
def init_db():
|
|||
|
schema = """
|
|||
|
CREATE TABLE IF NOT EXISTS user (
|
|||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
username TEXT UNIQUE NOT NULL,
|
|||
|
password TEXT NOT NULL,
|
|||
|
permission_level TEXT NOT NULL CHECK (permission_level IN ('Admin', 'Supervisor', 'Operator')),
|
|||
|
hire_date TEXT NOT NULL,
|
|||
|
email TEXT,
|
|||
|
phone TEXT,
|
|||
|
status TEXT DEFAULT 'Active',
|
|||
|
linked_devices INTEGER DEFAULT 0,
|
|||
|
created_by TEXT,
|
|||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|||
|
);
|
|||
|
|
|||
|
CREATE TABLE IF NOT EXISTS operation_log (
|
|||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
user_id INTEGER NOT NULL,
|
|||
|
type TEXT NOT NULL,
|
|||
|
message TEXT NOT NULL,
|
|||
|
details TEXT,
|
|||
|
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|||
|
FOREIGN KEY (user_id) REFERENCES user (id)
|
|||
|
);
|
|||
|
"""
|
|||
|
with current_app.open_resource('schema.sql', mode='w') as f:
|
|||
|
f.write(schema)
|
|||
|
get_db().executescript(schema)
|
|||
|
print("数据库初始化完成")
|
|||
|
|
|||
|
# 用户列表接口
|
|||
|
@bp.route('/users', methods=['GET'])
|
|||
|
def get_users():
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
cursor = db.cursor()
|
|||
|
query = """
|
|||
|
SELECT
|
|||
|
id,
|
|||
|
username,
|
|||
|
email,
|
|||
|
phone,
|
|||
|
permission_level,
|
|||
|
DATE(hire_date) AS hire_date,
|
|||
|
status,
|
|||
|
linked_devices
|
|||
|
FROM user
|
|||
|
ORDER BY
|
|||
|
CASE permission_level
|
|||
|
WHEN 'Admin' THEN 1
|
|||
|
WHEN 'Supervisor' THEN 2
|
|||
|
WHEN 'Operator' THEN 3
|
|||
|
END,
|
|||
|
hire_date DESC
|
|||
|
"""
|
|||
|
filter_permission = request.args.get('filter_permission')
|
|||
|
if filter_permission and filter_permission != 'all':
|
|||
|
cursor.execute(query + " WHERE permission_level = ?", (filter_permission,))
|
|||
|
else:
|
|||
|
cursor.execute(query)
|
|||
|
users = cursor.fetchall()
|
|||
|
return jsonify({
|
|||
|
'code': 200,
|
|||
|
'data': [dict(user) for user in users]
|
|||
|
})
|
|||
|
except sqlite3.Error as e:
|
|||
|
current_app.logger.error(f"获取用户列表错误: {str(e)}")
|
|||
|
return jsonify({'code': 500, 'message': '服务器内部错误'}), 500
|
|||
|
|
|||
|
# 添加用户接口
|
|||
|
@bp.route('/users', methods=['POST'])
|
|||
|
def add_user():
|
|||
|
data = request.json
|
|||
|
# 明确必填字段(包括 password)
|
|||
|
required_fields = ['username', 'permissionLevel', 'hire_date', 'password']
|
|||
|
for field in required_fields:
|
|||
|
if not data.get(field):
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': f'缺少必填字段: {field}'
|
|||
|
}), 400
|
|||
|
|
|||
|
permission = data['permissionLevel']
|
|||
|
if permission not in VALID_PERMISSIONS: # 修改:使用全局常量
|
|||
|
current_app.logger.error(f"无效权限级别: {data['permissionLevel']}")
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': '权限级别格式错误,请使用Admin、Supervisor或Operator'
|
|||
|
}), 400
|
|||
|
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
cursor = db.cursor()
|
|||
|
# 插入所有字段(包括 email、phone)
|
|||
|
cursor.execute(
|
|||
|
"""INSERT INTO user (
|
|||
|
username,
|
|||
|
password,
|
|||
|
permission_level,
|
|||
|
hire_date,
|
|||
|
email,
|
|||
|
phone
|
|||
|
) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(username) DO NOTHING""",
|
|||
|
(
|
|||
|
data['username'],
|
|||
|
data['password'],
|
|||
|
permission,
|
|||
|
data['hire_date'],
|
|||
|
data.get('email', ''), # 允许为空
|
|||
|
data.get('phone', '') # 允许为空
|
|||
|
)
|
|||
|
)
|
|||
|
db.commit()
|
|||
|
|
|||
|
if cursor.rowcount == 0:
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': '用户名已存在'
|
|||
|
}), 400
|
|||
|
|
|||
|
# 记录操作日志
|
|||
|
cursor.execute(
|
|||
|
"INSERT INTO operation_log (user_id, type, message) VALUES (?, ?, ?)",
|
|||
|
(cursor.lastrowid, 'USER_CREATE', f'创建用户 {data["username"]}')
|
|||
|
)
|
|||
|
db.commit()
|
|||
|
|
|||
|
return jsonify({
|
|||
|
'code': 201,
|
|||
|
'message': '用户创建成功'
|
|||
|
}), 201
|
|||
|
|
|||
|
except sqlite3.IntegrityError as e:
|
|||
|
if 'CHECK constraint failed' in str(e):
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': '权限级别格式错误,请使用Admin、Supervisor或Operator'
|
|||
|
}), 400
|
|||
|
else:
|
|||
|
current_app.logger.error(f"添加用户错误: {str(e)}")
|
|||
|
db.rollback()
|
|||
|
return jsonify({
|
|||
|
'code': 500,
|
|||
|
'message': '服务器内部错误'
|
|||
|
}), 500
|
|||
|
except sqlite3.Error as e:
|
|||
|
current_app.logger.error(f"添加用户错误: {str(e)}")
|
|||
|
db.rollback()
|
|||
|
return jsonify({
|
|||
|
'code': 500,
|
|||
|
'message': '服务器内部错误'
|
|||
|
}), 500
|
|||
|
|
|||
|
# 编辑用户接口
|
|||
|
@bp.route('/users/<string:username>', methods=['PUT'])
|
|||
|
def edit_user(username):
|
|||
|
data = request.json
|
|||
|
db = get_db()
|
|||
|
cursor = db.cursor()
|
|||
|
cursor.execute("SELECT id FROM user WHERE username = ?", (username,))
|
|||
|
user = cursor.fetchone()
|
|||
|
if not user:
|
|||
|
return jsonify({
|
|||
|
'code': 404,
|
|||
|
'message': '用户不存在'
|
|||
|
}), 404
|
|||
|
|
|||
|
update_fields = []
|
|||
|
params = []
|
|||
|
|
|||
|
# 处理权限级别
|
|||
|
if 'permissionLevel' in data:
|
|||
|
permission = data['permissionLevel']
|
|||
|
if permission not in VALID_PERMISSIONS: # 修改:使用全局常量
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': '权限级别格式错误,请使用Admin、Supervisor或Operator'
|
|||
|
}), 400
|
|||
|
update_fields.append("permission_level = ?")
|
|||
|
params.append(permission)
|
|||
|
|
|||
|
# 处理其他字段
|
|||
|
if 'hire_date' in data:
|
|||
|
update_fields.append("hire_date = ?")
|
|||
|
params.append(data['hire_date'])
|
|||
|
if 'linkedDevices' in data:
|
|||
|
update_fields.append("linked_devices = ?")
|
|||
|
params.append(data['linkedDevices'])
|
|||
|
if 'status' in data:
|
|||
|
update_fields.append("status = ?")
|
|||
|
params.append(data['status'])
|
|||
|
if 'email' in data:
|
|||
|
update_fields.append("email = ?")
|
|||
|
params.append(data['email'])
|
|||
|
if 'phone' in data:
|
|||
|
update_fields.append("phone = ?")
|
|||
|
params.append(data['phone'])
|
|||
|
if 'password' in data: # 允许修改密码
|
|||
|
update_fields.append("password = ?")
|
|||
|
params.append(data['password'])
|
|||
|
|
|||
|
if not update_fields:
|
|||
|
return jsonify({
|
|||
|
'code': 400,
|
|||
|
'message': '未提供更新字段'
|
|||
|
}), 400
|
|||
|
|
|||
|
params.append(username)
|
|||
|
query = f"UPDATE user SET {', '.join(update_fields)} WHERE username = ?"
|
|||
|
try:
|
|||
|
cursor.execute(query, params)
|
|||
|
db.commit()
|
|||
|
|
|||
|
# 记录操作日志
|
|||
|
cursor.execute(
|
|||
|
"INSERT INTO operation_log (user_id, type, message) VALUES (?, ?, ?)",
|
|||
|
(user['id'], 'USER_UPDATE', f'更新用户 {username}')
|
|||
|
)
|
|||
|
db.commit()
|
|||
|
|
|||
|
return jsonify({
|
|||
|
'code': 200,
|
|||
|
'message': '更新成功'
|
|||
|
}), 200
|
|||
|
|
|||
|
except sqlite3.Error as e:
|
|||
|
current_app.logger.error(f"编辑用户错误: {str(e)}")
|
|||
|
db.rollback()
|
|||
|
return jsonify({
|
|||
|
'code': 500,
|
|||
|
'message': '服务器内部错误'
|
|||
|
}), 500
|
|||
|
|
|||
|
# 删除用户接口
|
|||
|
@bp.route('/users/<string:username>', methods=['DELETE'])
|
|||
|
def delete_user(username):
|
|||
|
db = get_db()
|
|||
|
cursor = db.cursor()
|
|||
|
cursor.execute("SELECT id FROM user WHERE username = ?", (username,))
|
|||
|
user = cursor.fetchone()
|
|||
|
if not user:
|
|||
|
return jsonify({
|
|||
|
'code': 404,
|
|||
|
'message': '用户不存在'
|
|||
|
}), 404
|
|||
|
|
|||
|
if username == 'root':
|
|||
|
return jsonify({
|
|||
|
'code': 403,
|
|||
|
'message': '禁止删除root用户'
|
|||
|
}), 403
|
|||
|
|
|||
|
try:
|
|||
|
cursor.execute("DELETE FROM user WHERE username = ?", (username,))
|
|||
|
db.commit()
|
|||
|
|
|||
|
# 记录操作日志
|
|||
|
cursor.execute(
|
|||
|
"INSERT INTO operation_log (user_id, type, message) VALUES (?, ?, ?)",
|
|||
|
(user['id'], 'USER_DELETE', f'删除用户 {username}')
|
|||
|
)
|
|||
|
db.commit()
|
|||
|
|
|||
|
return jsonify({
|
|||
|
'code': 200,
|
|||
|
'message': '用户删除成功'
|
|||
|
}), 200
|
|||
|
|
|||
|
except sqlite3.Error as e:
|
|||
|
current_app.logger.error(f"删除用户错误: {str(e)}")
|
|||
|
db.rollback()
|
|||
|
return jsonify({
|
|||
|
'code': 500,
|
|||
|
'message': '服务器内部错误'
|
|||
|
}), 500
|
|||
|
|
|||
|
# 操作日志接口
|
|||
|
@bp.route('/logs', methods=['GET'])
|
|||
|
def get_logs():
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
cursor = db.cursor()
|
|||
|
query = """
|
|||
|
SELECT
|
|||
|
id,
|
|||
|
strftime('%Y-%m-%d %H:%M:%S', timestamp) AS timestamp,
|
|||
|
type,
|
|||
|
message,
|
|||
|
(SELECT username FROM user WHERE id = user_id) AS user
|
|||
|
FROM operation_log
|
|||
|
ORDER BY timestamp DESC -- 按时间降序排列
|
|||
|
"""
|
|||
|
cursor.execute(query)
|
|||
|
logs = cursor.fetchall()
|
|||
|
return jsonify({
|
|||
|
'code': 200,
|
|||
|
'data': [dict(log) for log in logs]
|
|||
|
})
|
|||
|
except sqlite3.Error as e:
|
|||
|
current_app.logger.error(f"获取日志错误: {str(e)}")
|
|||
|
return jsonify({
|
|||
|
'code': 500,
|
|||
|
'message': '服务器内部错误'
|
|||
|
}), 500
|