第一次提交
This commit is contained in:
267
app/api/device.py
Normal file
267
app/api/device.py
Normal file
@@ -0,0 +1,267 @@
|
||||
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_login, require_admin
|
||||
from sqlalchemy import func, or_
|
||||
from app.utils.logger import log_operation
|
||||
|
||||
@api_bp.route('/devices', methods=['GET'])
|
||||
@require_login
|
||||
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_key', '').strip()
|
||||
|
||||
# 使用join预加载Product和License关系,避免N+1查询
|
||||
query = db.session.query(Device).join(Product, Device.product_id == Product.product_id).outerjoin(License, Device.license_id == License.license_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:
|
||||
escaped_keyword = keyword.replace('%', r'\%').replace('_', r'\_')
|
||||
pattern = f'%{escaped_keyword.lower()}%'
|
||||
query = query.filter(
|
||||
or_(
|
||||
func.lower(Device.machine_code).like(pattern, escape='\\'),
|
||||
func.cast(Device.device_id, db.String).like(pattern, escape='\\'),
|
||||
func.lower(Product.product_name).like(pattern, escape='\\')
|
||||
)
|
||||
)
|
||||
if product:
|
||||
escaped_product = product.replace('%', r'\%').replace('_', r'\_')
|
||||
pattern = f'%{escaped_product}%'
|
||||
query = query.filter(
|
||||
or_(
|
||||
db.cast(Product.product_id, db.String).like(pattern, escape='\\'),
|
||||
Product.product_name.like(pattern, escape='\\')
|
||||
)
|
||||
)
|
||||
if license_key and license_key.strip():
|
||||
escaped_license = license_key.replace('%', r'\%').replace('_', r'\_')
|
||||
pattern = f'%{escaped_license}%'
|
||||
query = query.filter(db.cast(License.license_key, db.String).like(pattern, escape='\\'))
|
||||
|
||||
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': {
|
||||
'current_page': page,
|
||||
'per_page': per_page,
|
||||
'total': pagination.total,
|
||||
'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_login
|
||||
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()
|
||||
|
||||
# 记录操作日志
|
||||
log_operation('UPDATE_DEVICE_STATUS', 'DEVICE', device.device_id, {
|
||||
'status': status
|
||||
})
|
||||
|
||||
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_login
|
||||
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()
|
||||
|
||||
# 记录操作日志
|
||||
log_operation('DELETE_DEVICE', 'DEVICE', device.device_id, {
|
||||
'machine_code': device.machine_code
|
||||
})
|
||||
|
||||
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_login
|
||||
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()
|
||||
|
||||
# 记录操作日志
|
||||
device_ids = [device.device_id for device in devices]
|
||||
log_operation('BATCH_DELETE_DEVICES', 'DEVICE', None, {
|
||||
'device_ids': device_ids,
|
||||
'count': len(devices)
|
||||
})
|
||||
|
||||
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_login
|
||||
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()
|
||||
|
||||
# 记录操作日志
|
||||
device_ids = [device.device_id for device in devices]
|
||||
log_operation('BATCH_UPDATE_DEVICE_STATUS', 'DEVICE', None, {
|
||||
'device_ids': device_ids,
|
||||
'status': status,
|
||||
'count': len(devices)
|
||||
})
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user