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}%'), Product.product_name.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//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/', 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