diff --git a/app.py b/app.py index eeb5d99..da5e115 100644 --- a/app.py +++ b/app.py @@ -76,6 +76,15 @@ if __name__ == '__main__': logger.info("=== BigDataTool 启动 ===") logger.info("应用架构:模块化") logger.info("支持功能:单表查询、分表查询、多主键查询、配置管理、查询历史") - logger.info("访问地址:http://localhost:5000") + + # 从环境变量获取配置,支持Docker部署 + import os + host = os.getenv('FLASK_HOST', '0.0.0.0') + port = int(os.getenv('FLASK_PORT', 5000)) + debug = os.getenv('FLASK_DEBUG', 'True').lower() == 'true' + + logger.info(f"访问地址:http://{host}:{port}") logger.info("API文档:/api/* 路径下的所有端点") - app.run(debug=True, port=5000) \ No newline at end of file + logger.info(f"配置信息 - 主机: {host}, 端口: {port}, 调试: {debug}") + + app.run(debug=debug, host=host, port=port) \ No newline at end of file diff --git a/modules/api_routes.py b/modules/api_routes.py index 67d66f3..acd6929 100644 --- a/modules/api_routes.py +++ b/modules/api_routes.py @@ -68,6 +68,32 @@ def setup_routes(app, query_log_collector): return render_template('redis_test.html') # 基础API + @app.route('/api/health') + def health_check(): + """健康检查端点,用于Docker健康检查和服务监控""" + try: + # 检查应用基本状态 + current_time = datetime.now().isoformat() + + # 简单的数据库连接检查(可选) + from .database import ensure_database + db_status = ensure_database() + + return jsonify({ + 'status': 'healthy', + 'timestamp': current_time, + 'service': 'BigDataTool', + 'version': '2.0', + 'database': 'ok' if db_status else 'warning' + }) + except Exception as e: + logger.error(f"健康检查失败: {str(e)}") + return jsonify({ + 'status': 'unhealthy', + 'error': str(e), + 'timestamp': datetime.now().isoformat() + }), 503 + @app.route('/api/default-config') def get_default_config(): return jsonify(DEFAULT_CONFIG) diff --git a/static/js/app.js b/static/js/app.js index b6bd977..46ab4d0 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -908,35 +908,65 @@ function displayStats(results) { function displayDifferences() { const differencesContainer = document.getElementById('differences'); + // 保存当前搜索框的值 + const currentSearchValue = document.getElementById('differenceSearch')?.value || ''; + if (!filteredDifferenceResults.length) { differencesContainer.innerHTML = '
未发现差异
'; return; } - // 计算分页 - const totalPages = Math.ceil(filteredDifferenceResults.length / differencePageSize); + // 按主键分组差异 + const groupedDifferences = groupDifferencesByKey(filteredDifferenceResults); + const totalGroups = Object.keys(groupedDifferences).length; + + // 计算分页(基于主键组) + const groupKeys = Object.keys(groupedDifferences); + const totalPages = Math.ceil(groupKeys.length / differencePageSize); const startIndex = (currentDifferencePage - 1) * differencePageSize; const endIndex = startIndex + differencePageSize; - const currentPageData = filteredDifferenceResults.slice(startIndex, endIndex); + const currentPageKeys = groupKeys.slice(startIndex, endIndex); + + // 统计字段差异类型 + const fieldStats = {}; + filteredDifferenceResults.forEach(diff => { + if (diff.field) { + fieldStats[diff.field] = (fieldStats[diff.field] || 0) + 1; + } + }); let html = ` + +主键: ${formatCompositeKey(diff.key)}
-${diff.message}
主键: ${formatCompositeKey(key)}
主键: ${formatCompositeKey(diff.key)}
-差异字段: ${diff.field}
+${escapeHtml(diff.pro_value)}+
${escapeHtml(diff.pro_value)} -${escapeHtml(diff.test_value)}- +
${escapeHtml(diff.test_value)}
没有完全相同的记录
'; return; @@ -1111,7 +1170,15 @@ function displayIdenticalResults() {持续完善的数据处理生态系统
-- 企业级数据迁移平台,支持多种数据库和存储系统之间的数据传输, - 提供实时同步、增量更新和数据转换功能。 -
-- 智能数据质量评估系统,自动检测数据完整性、一致性和准确性问题, - 提供实时监控、告警通知和质量报告生成。 -
-