import logging import threading from flask import Blueprint, request, jsonify from lib import batch_processor from lib.word_signer import _new_trace_id batch_api_bp = Blueprint('batch_api', __name__) logger = logging.getLogger(__name__) _picker_lock = threading.Lock() @batch_api_bp.route('/api/batch/rules', methods=['GET']) def batch_rules_get(): path = request.args.get('path') or None try: result = batch_processor.load_rules(path) return jsonify({'success': True, 'rules': result['rules'], 'warning': result.get('warning'), 'path': batch_processor.resolve_rules_path(path)}) except Exception as e: logger.error("加载规则失败: %s", str(e)) return jsonify({'success': False, 'message': str(e), 'rules': []}), 500 @batch_api_bp.route('/api/batch/rules', methods=['POST']) def batch_rules_save(): payload = request.get_json(silent=True) or {} rules = payload.get('rules') or [] path = payload.get('path') or None try: result = batch_processor.save_rules(rules, path) return jsonify({'success': True, 'rules': result['rules'], 'path': result['path'], 'warnings': result.get('warnings', [])}) except RuntimeError as e: return jsonify({'success': False, 'message': str(e)}), 400 except Exception as e: logger.error("保存规则失败: %s", str(e)) return jsonify({'success': False, 'message': str(e)}), 500 @batch_api_bp.route('/api/batch/regex-snippets', methods=['GET']) def batch_snippets(): return jsonify(batch_processor.get_regex_snippets()) @batch_api_bp.route('/api/batch/rules/test', methods=['POST']) def batch_rules_test(): payload = request.get_json(silent=True) or {} rules = payload.get('rules') or [] text = payload.get('text') or '' try: result = batch_processor.test_rules(rules, text) return jsonify({'success': True, **result}) except Exception as e: logger.error("测试规则失败: %s", str(e)) return jsonify({'success': False, 'message': str(e)}), 500 @batch_api_bp.route('/api/batch/pick-folder', methods=['GET']) def batch_pick_folder(): title = request.args.get('title') or '选择文件夹' initialdir = request.args.get('initialdir') or None try: with _picker_lock: import tkinter as tk from tkinter import filedialog root = tk.Tk() root.withdraw() root.attributes('-topmost', True) folder = filedialog.askdirectory( title=title, initialdir=initialdir, mustexist=True ) root.destroy() return jsonify({'success': True, 'folder': folder or ''}) except Exception as e: logger.error("选择目录失败: %s", str(e)) return jsonify({'success': False, 'message': str(e), 'folder': ''}), 500 @batch_api_bp.route('/api/batch/process', methods=['POST']) def batch_process(): payload = request.get_json(silent=True) or {} folder = payload.get('folder') if not folder: return jsonify({'success': False, 'message': '请提供 Word 根目录路径'}), 400 recursive = bool(payload.get('recursive', True)) auto_sign = bool(payload.get('auto_sign', True)) rules = payload.get('rules') or [] request_options = payload.get('request_options') or {} trace_id = _new_trace_id() try: summary = batch_processor.process_folder( folder, recursive=recursive, auto_sign=auto_sign, rules=rules, request_options=request_options, log_source='批量', trace_id=trace_id, ) return jsonify({'success': summary['success'], **summary, 'trace_id': trace_id}) except Exception as e: logger.error("批量处理失败: %s", str(e), extra={'log_source': '批量', 'trace_id': trace_id}) return jsonify({'success': False, 'message': str(e), 'trace_id': trace_id}), 500