Kamixitong/app/api/device.py
2025-11-13 16:51:51 +08:00

263 lines
9.0 KiB
Python

from flask import request, jsonify, current_app
from datetime import datetime
from app import db
from app.models import Device, Product, License
from . import api_bp
from .decorators import require_admin
from sqlalchemy import func, or_
# 简化版权限验证装饰器
def check_admin_permission(f):
"""简化版管理员权限验证"""
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
from flask_login import current_user
from flask import current_app, jsonify
# 检查用户是否已认证
if not hasattr(current_user, 'is_authenticated') or not current_user.is_authenticated:
return jsonify({
'success': False,
'message': '需要登录'
}), 401
# 检查是否为管理员
if not hasattr(current_user, 'is_super_admin') or not current_user.is_super_admin():
return jsonify({
'success': False,
'message': '需要管理员权限'
}), 403
return f(*args, **kwargs)
return decorated_function
# 将所有使用require_admin的地方替换为check_admin_permission
@api_bp.route('/devices', methods=['GET'])
@require_admin
def get_devices():
"""获取设备列表"""
try:
page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 20, type=int), 100)
product_id = request.args.get('product_id')
software_version = request.args.get('software_version')
status = request.args.get('status', type=int)
keyword = request.args.get('keyword', '').strip()
product = request.args.get('product')
license_key = request.args.get('license')
query = Device.query.join(Product, Device.product_id == Product.product_id)
# 添加搜索条件
if product_id:
query = query.filter(Device.product_id == product_id)
if software_version:
query = query.filter(Device.software_version == software_version)
if status is not None:
query = query.filter(Device.status == status)
if keyword:
query = query.filter(
or_(
func.lower(Device.machine_code).like(f'%{keyword.lower()}%'),
func.cast(Device.device_id, db.String).like(f'%{keyword}%')
)
)
if product:
query = query.filter(
or_(
db.cast(Product.product_id, db.String).like(f'%{product}%'),
Product.product_name.like(f'%{product}%')
)
)
if license_key and license_key.strip():
query = query.join(License, Device.license_id == License.license_id)
query = query.filter(db.cast(License.license_key, db.String).like(f'%{license_key}%'))
query = query.order_by(db.desc(Device.last_verify_time))
pagination = query.paginate(page=page, per_page=per_page, error_out=False)
devices = [device.to_dict() for device in pagination.items]
return jsonify({
'success': True,
'data': {
'devices': devices,
'pagination': {
'page': page,
'per_page': per_page,
'total': pagination.total,
'pages': pagination.pages,
'has_prev': pagination.has_prev,
'has_next': pagination.has_next
}
}
})
except Exception as e:
current_app.logger.error(f"获取设备列表失败: {str(e)}")
return jsonify({'success': False, 'message': '服务器内部错误'}), 500
@api_bp.route('/devices/<int:device_id>/status', methods=['PUT'])
@require_admin
def update_device_status(device_id):
"""更新设备状态"""
try:
device = Device.query.get(device_id)
if not device:
return jsonify({'success': False, 'message': '设备不存在'}), 404
data = request.get_json()
status = data.get('status')
if status is None:
return jsonify({'success': False, 'message': '状态参数不能为空'}), 400
if status not in [0, 1, 2]:
return jsonify({'success': False, 'message': '无效的状态值'}), 400
device.status = status
db.session.commit()
return jsonify({
'success': True,
'message': '设备状态更新成功',
'data': device.to_dict()
})
except Exception as e:
db.session.rollback()
current_app.logger.error(f"更新设备状态失败: {str(e)}")
return jsonify({'success': False, 'message': '服务器内部错误'}), 500
@api_bp.route('/devices/<int:device_id>', methods=['DELETE'])
@require_admin
def delete_device(device_id):
"""删除设备"""
try:
device = Device.query.get(device_id)
if not device:
return jsonify({'success': False, 'message': '设备不存在'}), 404
db.session.delete(device)
db.session.commit()
return jsonify({
'success': True,
'message': '设备删除成功'
})
except Exception as e:
db.session.rollback()
current_app.logger.error(f"删除设备失败: {str(e)}")
return jsonify({'success': False, 'message': '服务器内部错误'}), 500
@api_bp.route('/devices/batch', methods=['DELETE'])
@require_admin
def batch_delete_devices():
"""批量删除设备"""
try:
data = request.get_json()
if not data or 'device_ids' not in data:
return jsonify({
'success': False,
'message': '请求数据为空或缺少device_ids字段'
}), 400
device_ids = data['device_ids']
if not isinstance(device_ids, list) or len(device_ids) == 0:
return jsonify({
'success': False,
'message': 'device_ids必须是非空列表'
}), 400
# 查找所有要删除的设备
devices = Device.query.filter(Device.device_id.in_(device_ids)).all()
if len(devices) != len(device_ids):
found_ids = [d.device_id for d in devices]
missing_ids = [did for did in device_ids if did not in found_ids]
return jsonify({
'success': False,
'message': f'以下设备不存在: {", ".join(map(str, missing_ids))}'
}), 404
# 批量删除设备
for device in devices:
db.session.delete(device)
db.session.commit()
return jsonify({
'success': True,
'message': f'成功删除 {len(devices)} 个设备'
})
except Exception as e:
db.session.rollback()
current_app.logger.error(f"批量删除设备失败: {str(e)}")
return jsonify({
'success': False,
'message': '服务器内部错误'
}), 500
@api_bp.route('/devices/batch/status', methods=['PUT'])
@require_admin
def batch_update_device_status():
"""批量更新设备状态"""
try:
data = request.get_json()
if not data or 'device_ids' not in data or 'status' not in data:
return jsonify({
'success': False,
'message': '请求数据为空或缺少device_ids/status字段'
}), 400
device_ids = data['device_ids']
status = data['status']
if not isinstance(device_ids, list) or len(device_ids) == 0:
return jsonify({
'success': False,
'message': 'device_ids必须是非空列表'
}), 400
if status not in [0, 1, 2]:
return jsonify({
'success': False,
'message': 'status必须是0(禁用)、1(正常)或2(离线)'
}), 400
# 查找所有要更新的设备
devices = Device.query.filter(Device.device_id.in_(device_ids)).all()
if len(devices) != len(device_ids):
found_ids = [d.device_id for d in devices]
missing_ids = [did for did in device_ids if did not in found_ids]
return jsonify({
'success': False,
'message': f'以下设备不存在: {", ".join(map(str, missing_ids))}'
}), 404
# 批量更新设备状态
for device in devices:
device.status = status
db.session.commit()
status_names = {0: '禁用', 1: '正常', 2: '离线'}
status_name = status_names.get(status, '未知')
return jsonify({
'success': True,
'message': f'成功将 {len(devices)} 个设备状态更新为{status_name}'
})
except Exception as e:
db.session.rollback()
current_app.logger.error(f"批量更新设备状态失败: {str(e)}")
return jsonify({
'success': False,
'message': '服务器内部错误'
}), 500