commit 1735c19f48af2db0983df04c7ed2f5c3b85d1188 Author: DelLevin-Home Date: Tue Jun 16 03:28:24 2026 +0800 功能完善1 diff --git a/flask-dev-api/app.py b/flask-dev-api/app.py new file mode 100644 index 0000000..d54103e --- /dev/null +++ b/flask-dev-api/app.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- +""" +整合工具集主入口 +只负责创建 Flask 应用、注册蓝图和启动服务 +""" +import sys +import os +import time +from datetime import datetime +from flask import Flask, render_template, jsonify, g, request + +from config import PORT +from blueprints import pin_tu_bp, base64_bp, down_video_bp, fen_ci_bp, content_tag_bp, chmod_calc_bp, json_format_bp, qr_code_bp, http_status_bp, url_parser_bp, token_gen_bp, sovits_tts_bp, stt_bp, ai_dubbing_bp, rvc_bp +from utils.stats_db import init_db, record_call, get_total_count, get_avg_duration, get_daily_counts, get_monthly_counts, get_available_years, get_available_months, get_daily_counts_by_month, get_hourly_counts, get_endpoint_stats, get_today_count, get_yesterday_count, get_month_count, get_success_rate, get_duration_distribution, get_slowest_endpoints, get_week_compare, get_recent_calls, get_active_days +from utils.stats_db import ALLOWED_TABLES, get_table_info, get_table_rows, get_table_count, insert_row, update_row, delete_rows, clear_table + +TOOL_COUNT = 15 + + +def create_app(): + # 打包模式下,模板和静态文件在 sys._MEIPASS 临时目录 + if getattr(sys, 'frozen', False): + base = sys._MEIPASS + app = Flask(__name__, + template_folder=os.path.join(base, 'templates'), + static_folder=os.path.join(base, 'static')) + else: + app = Flask(__name__) + + init_db() + + # 主页 + @app.route('/') + def index(): + return render_template('index.html') + + # 数据管理页面 + @app.route('/data-manage') + def data_manage(): + return render_template('data_manage.html') + + # 仪表盘统计接口 + @app.route('/api/stats') + def api_stats(): + year = request.args.get('year') + if not year: + year = datetime.now().strftime('%Y') + return jsonify({ + 'tool_count': TOOL_COUNT, + 'total_calls': get_total_count(), + 'avg_duration': get_avg_duration(), + 'daily': get_daily_counts(30), + 'years': get_available_years(), + 'months': get_available_months(year) + }) + + # 某月每日调用统计 + @app.route('/api/stats/daily-by-month') + def api_stats_daily_by_month(): + year = request.args.get('year', datetime.now().strftime('%Y')) + month = request.args.get('month', datetime.now().strftime('%m')) + return jsonify({ + 'year': year, + 'month': month, + 'daily': get_daily_counts_by_month(year, int(month)) + }) + + # 每天按小时统计 + @app.route('/api/stats/hourly') + def api_stats_hourly(): + date_str = request.args.get('date') + if not date_str: + date_str = datetime.now().strftime('%Y-%m-%d') + return jsonify({ + 'date': date_str, + 'hourly': get_hourly_counts(date_str) + }) + + # 接口调用分布 + @app.route('/api/stats/endpoints') + def api_stats_endpoints(): + date = request.args.get('date') + return jsonify({'endpoints': get_endpoint_stats(date)}) + + # 高级统计数据 + @app.route('/api/stats/advanced') + def api_stats_advanced(): + return jsonify({ + 'today_count': get_today_count(), + 'yesterday_count': get_yesterday_count(), + 'month_count': get_month_count(), + 'success_rate': get_success_rate(), + 'duration_distribution': get_duration_distribution(), + 'slowest_endpoints': get_slowest_endpoints(), + 'week_compare': get_week_compare(), + 'recent_calls': get_recent_calls(), + 'active_days': get_active_days() + }) + + # ===== 数据管理 API ===== + + @app.route('/api/db/tables') + def api_db_tables(): + return jsonify({'tables': get_table_info()}) + + @app.route('/api/db/') + def api_db_list(table): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + page = int(request.args.get('page', 1)) + page_size = int(request.args.get('page_size', 20)) + search = request.args.get('search', '').strip() + rows = get_table_rows(table, page, page_size, search) + total = get_table_count(table, search) + return jsonify({'success': True, 'rows': rows, 'total': total, 'page': page, 'page_size': page_size}) + + @app.route('/api/db/
', methods=['POST']) + def api_db_insert(table): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + data = request.get_json() + if not data: + return jsonify({'success': False, 'error': '缺少数据'}), 400 + new_id = insert_row(table, data) + if new_id: + return jsonify({'success': True, 'id': new_id}) + return jsonify({'success': False, 'error': '插入失败'}), 400 + + @app.route('/api/db/
/', methods=['PUT']) + def api_db_update(table, row_id): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + data = request.get_json() + if not data: + return jsonify({'success': False, 'error': '缺少数据'}), 400 + if update_row(table, row_id, data): + return jsonify({'success': True}) + return jsonify({'success': False, 'error': '更新失败'}), 400 + + @app.route('/api/db/
/', methods=['DELETE']) + def api_db_delete(table, row_id): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + deleted = delete_rows(table, [row_id]) + return jsonify({'success': deleted > 0}) + + @app.route('/api/db/
/delete-batch', methods=['POST']) + def api_db_delete_batch(table): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + data = request.get_json() + ids = data.get('ids', []) if data else [] + if not ids: + return jsonify({'success': False, 'error': '未选择记录'}), 400 + deleted = delete_rows(table, ids) + return jsonify({'success': True, 'deleted': deleted}) + + @app.route('/api/db/
/clear', methods=['POST']) + def api_db_clear(table): + if table not in ALLOWED_TABLES: + return jsonify({'success': False, 'error': '不允许的表名'}), 400 + deleted = clear_table(table) + return jsonify({'success': True, 'deleted': deleted}) + + # 请求计时 + @app.before_request + def _start_timer(): + g.start_time = time.time() + + # 请求追踪 + @app.after_request + def _track_request(response): + path = request.path + if path == '/' or path.startswith('/static/') or path.startswith('/api/'): + return response + if request.method != 'POST': + return response + duration_ms = (time.time() - g.start_time) * 1000 + record_call(path, request.method, response.status_code, duration_ms) + return response + + # 注册蓝图 + app.register_blueprint(pin_tu_bp) + app.register_blueprint(base64_bp) + app.register_blueprint(down_video_bp) + app.register_blueprint(fen_ci_bp) + app.register_blueprint(content_tag_bp) + app.register_blueprint(chmod_calc_bp) + app.register_blueprint(json_format_bp) + app.register_blueprint(qr_code_bp) + app.register_blueprint(http_status_bp) + app.register_blueprint(url_parser_bp) + app.register_blueprint(token_gen_bp) + app.register_blueprint(sovits_tts_bp) + app.register_blueprint(stt_bp) + app.register_blueprint(ai_dubbing_bp) + app.register_blueprint(rvc_bp) + + return app + +app = create_app() + + +def start_flask(): + """供桌面启动器调用,以非调试模式运行 Flask""" + a = create_app() + a.run(host='127.0.0.1', port=PORT, use_reloader=False, threaded=True) + + +if __name__ == '__main__': + # import webbrowser + # import threading as _t + # _t.Timer(1, webbrowser.open, args=[f'http://127.0.0.1:{PORT}']).start() + app.run(debug=True, host='0.0.0.0', port=PORT, threaded=True)