Kamixitong/app/api/device.py

261 lines
9.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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')
# 使用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:
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.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_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