修复reids
This commit is contained in:
4
app.py
4
app.py
@@ -52,6 +52,6 @@ if __name__ == '__main__':
|
||||
logger.info("=== BigDataTool 启动 ===")
|
||||
logger.info("应用架构:模块化")
|
||||
logger.info("支持功能:单表查询、分表查询、多主键查询、配置管理、查询历史")
|
||||
logger.info("访问地址:http://localhost:5001")
|
||||
logger.info("访问地址:http://localhost:5000")
|
||||
logger.info("API文档:/api/* 路径下的所有端点")
|
||||
app.run(debug=True, port=5001)
|
||||
app.run(debug=True, port=5000)
|
@@ -51,6 +51,10 @@ def setup_routes(app, query_log_collector):
|
||||
def redis_compare():
|
||||
return render_template('redis_compare.html')
|
||||
|
||||
@app.route('/redis-js-test')
|
||||
def redis_js_test():
|
||||
return render_template('redis_js_test.html')
|
||||
|
||||
@app.route('/redis-test')
|
||||
def redis_test():
|
||||
return render_template('redis_test.html')
|
||||
@@ -783,6 +787,62 @@ def setup_routes(app, query_log_collector):
|
||||
logger.info(f"Redis比较完成")
|
||||
logger.info(f"比较统计: 总计{result['stats']['total_keys']}个key,相同{result['stats']['identical_count']}个,不同{result['stats']['different_count']}个")
|
||||
|
||||
# 增强结果,添加原生数据信息
|
||||
enhanced_result = result.copy()
|
||||
enhanced_result['raw_data'] = {
|
||||
'cluster1_data': [],
|
||||
'cluster2_data': []
|
||||
}
|
||||
|
||||
# 从比较结果中提取原生数据信息
|
||||
for item in result.get('identical_results', []):
|
||||
if 'key' in item and 'value' in item:
|
||||
enhanced_result['raw_data']['cluster1_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['value'],
|
||||
'type': 'identical'
|
||||
})
|
||||
enhanced_result['raw_data']['cluster2_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['value'],
|
||||
'type': 'identical'
|
||||
})
|
||||
|
||||
for item in result.get('different_results', []):
|
||||
if 'key' in item:
|
||||
if 'cluster1_value' in item:
|
||||
enhanced_result['raw_data']['cluster1_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['cluster1_value'],
|
||||
'type': 'different'
|
||||
})
|
||||
if 'cluster2_value' in item:
|
||||
enhanced_result['raw_data']['cluster2_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['cluster2_value'],
|
||||
'type': 'different'
|
||||
})
|
||||
|
||||
for item in result.get('missing_results', []):
|
||||
if 'key' in item:
|
||||
if 'cluster1_value' in item and item['cluster1_value'] is not None:
|
||||
enhanced_result['raw_data']['cluster1_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['cluster1_value'],
|
||||
'type': 'missing'
|
||||
})
|
||||
if 'cluster2_value' in item and item['cluster2_value'] is not None:
|
||||
enhanced_result['raw_data']['cluster2_data'].append({
|
||||
'key': item['key'],
|
||||
'value': item['cluster2_value'],
|
||||
'type': 'missing'
|
||||
})
|
||||
|
||||
logger.info(f"原生数据统计: 集群1={len(enhanced_result['raw_data']['cluster1_data'])}条, 集群2={len(enhanced_result['raw_data']['cluster2_data'])}条")
|
||||
|
||||
# 使用增强结果进行后续处理
|
||||
result = enhanced_result
|
||||
|
||||
# 自动保存Redis查询历史记录
|
||||
try:
|
||||
# 生成历史记录名称
|
||||
@@ -790,29 +850,42 @@ def setup_routes(app, query_log_collector):
|
||||
history_name = f"Redis比较_{timestamp}"
|
||||
history_description = f"自动保存 - Redis比较{result['stats']['total_keys']}个Key,发现{result['stats']['different_count']}处差异"
|
||||
|
||||
# 保存历史记录
|
||||
history_id = save_query_history(
|
||||
# 计算查询键值列表
|
||||
query_keys = []
|
||||
if query_options.get('mode') == 'specified':
|
||||
query_keys = query_options.get('keys', [])
|
||||
elif query_options.get('mode') == 'random':
|
||||
# 对于随机模式,从结果中提取实际查询的键
|
||||
for item in result.get('identical_results', []):
|
||||
if 'key' in item:
|
||||
query_keys.append(item['key'])
|
||||
for item in result.get('different_results', []):
|
||||
if 'key' in item:
|
||||
query_keys.append(item['key'])
|
||||
for item in result.get('missing_results', []):
|
||||
if 'key' in item:
|
||||
query_keys.append(item['key'])
|
||||
|
||||
# 保存Redis查询历史记录
|
||||
history_id = save_redis_query_history(
|
||||
name=history_name,
|
||||
description=history_description,
|
||||
pro_config=cluster1_config,
|
||||
test_config=cluster2_config,
|
||||
query_config=query_options,
|
||||
query_keys=result.get('query_options', {}).get('keys', []),
|
||||
cluster1_config=cluster1_config,
|
||||
cluster2_config=cluster2_config,
|
||||
query_options=query_options,
|
||||
query_keys=query_keys,
|
||||
results_summary=result['stats'],
|
||||
execution_time=result['performance_report']['total_time'],
|
||||
total_keys=result['stats']['total_keys'],
|
||||
differences_count=result['stats']['different_count'],
|
||||
different_count=result['stats']['different_count'],
|
||||
identical_count=result['stats']['identical_count'],
|
||||
query_type='redis',
|
||||
# 添加查询结果数据
|
||||
missing_count=result['stats']['missing_in_cluster1'] + result['stats']['missing_in_cluster2'] + result['stats']['both_missing'],
|
||||
raw_results={
|
||||
'identical_results': result['identical_results'],
|
||||
'different_results': result['different_results'],
|
||||
'missing_results': result['missing_results'],
|
||||
'performance_report': result['performance_report']
|
||||
},
|
||||
differences_data=result['different_results'],
|
||||
identical_data=result['identical_results']
|
||||
}
|
||||
)
|
||||
|
||||
# 关联查询日志与历史记录
|
||||
@@ -824,6 +897,8 @@ def setup_routes(app, query_log_collector):
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"保存Redis查询历史记录失败: {e}")
|
||||
import traceback
|
||||
logger.error(f"详细错误信息: {traceback.format_exc()}")
|
||||
|
||||
# 结束查询批次
|
||||
query_log_collector.end_current_batch()
|
||||
@@ -1022,3 +1097,43 @@ def setup_routes(app, query_log_collector):
|
||||
return jsonify({'success': True, 'message': 'Redis查询历史记录删除成功'})
|
||||
else:
|
||||
return jsonify({'success': False, 'error': 'Redis查询历史记录删除失败'}), 500
|
||||
|
||||
# Redis查询日志API
|
||||
@app.route('/api/redis/query-logs', methods=['GET'])
|
||||
def api_get_redis_query_logs():
|
||||
"""获取Redis查询日志"""
|
||||
try:
|
||||
limit = request.args.get('limit', 100, type=int)
|
||||
# 获取最新的查询日志
|
||||
logs = query_log_collector.get_logs(limit=limit)
|
||||
|
||||
# 过滤Redis相关的日志
|
||||
redis_logs = []
|
||||
for log in logs:
|
||||
if (log.get('message') and 'redis' in log.get('message', '').lower()) or log.get('query_type') == 'redis':
|
||||
redis_logs.append(log)
|
||||
|
||||
return jsonify({'success': True, 'data': redis_logs})
|
||||
except Exception as e:
|
||||
logger.error(f"获取Redis查询日志失败: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/redis/query-logs/history/<int:history_id>', methods=['GET'])
|
||||
def api_get_redis_query_logs_by_history(history_id):
|
||||
"""获取特定历史记录的Redis查询日志"""
|
||||
try:
|
||||
logs = query_log_collector.get_logs_by_history_id(history_id)
|
||||
return jsonify({'success': True, 'data': logs})
|
||||
except Exception as e:
|
||||
logger.error(f"获取历史记录 {history_id} 的Redis查询日志失败: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/redis/query-logs', methods=['DELETE'])
|
||||
def api_clear_redis_query_logs():
|
||||
"""清空Redis查询日志"""
|
||||
try:
|
||||
query_log_collector.clear_logs()
|
||||
return jsonify({'success': True, 'message': 'Redis查询日志清空成功'})
|
||||
except Exception as e:
|
||||
logger.error(f"清空Redis查询日志失败: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
File diff suppressed because it is too large
Load Diff
@@ -67,11 +67,28 @@
|
||||
.node-input input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.performance-section {
|
||||
background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%);
|
||||
.btn-redis {
|
||||
background: linear-gradient(135deg, #dc143c 0%, #b91c1c 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
.btn-redis:hover {
|
||||
background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);
|
||||
color: white;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.redis-logo {
|
||||
color: #dc143c;
|
||||
}
|
||||
.cluster-config {
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.cluster-config.active {
|
||||
border-color: #dc143c;
|
||||
background-color: #fff8f8;
|
||||
}
|
||||
.log-viewer {
|
||||
background-color: #1e1e1e;
|
||||
@@ -94,28 +111,22 @@
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
.btn-redis {
|
||||
background: linear-gradient(135deg, #dc143c 0%, #b91c1c 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
.pagination {
|
||||
--bs-pagination-padding-x: 0.5rem;
|
||||
--bs-pagination-padding-y: 0.25rem;
|
||||
--bs-pagination-font-size: 0.875rem;
|
||||
}
|
||||
.btn-redis:hover {
|
||||
background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);
|
||||
color: white;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.redis-logo {
|
||||
color: #dc143c;
|
||||
}
|
||||
.cluster-config {
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.cluster-config.active {
|
||||
border-color: #dc143c;
|
||||
background-color: #fff8f8;
|
||||
|
||||
/* 确保提示消息在最顶层 */
|
||||
.alert {
|
||||
position: fixed !important;
|
||||
top: 20px !important;
|
||||
left: 50% !important;
|
||||
transform: translateX(-50%) !important;
|
||||
z-index: 9999 !important;
|
||||
min-width: 300px !important;
|
||||
max-width: 600px !important;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -141,7 +152,7 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<div class="container-fluid mt-4">
|
||||
<!-- 面包屑导航 -->
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
@@ -151,31 +162,25 @@
|
||||
</nav>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<div class="row mb-4">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fab fa-redis redis-logo fs-1 me-3"></i>
|
||||
<div>
|
||||
<h1 class="mb-1">Redis集群比对工具</h1>
|
||||
<p class="text-muted mb-0">专业的Redis集群数据比对工具,支持随机采样和指定Key查询</p>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-center mb-4">
|
||||
<i class="fab fa-redis redis-logo"></i> Redis集群比对工具
|
||||
<small class="text-muted d-block fs-6 mt-2">专业的Redis集群数据比对工具,支持随机采样和指定Key查询</small>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 配置区域 -->
|
||||
<div class="row">
|
||||
<!-- 配置管理 -->
|
||||
<div class="col-lg-12">
|
||||
<div class="config-section mb-4">
|
||||
<h4><i class="fas fa-cogs me-2"></i>配置管理</h4>
|
||||
<!-- 配置面板 -->
|
||||
<div class="col-lg-4">
|
||||
<div class="config-section">
|
||||
<h4><i class="fas fa-cogs"></i> 配置管理</h4>
|
||||
|
||||
<div class="row">
|
||||
<!-- 配置组管理 -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-layer-group me-2"></i>配置组管理</h6>
|
||||
<h6><i class="fas fa-layer-group"></i> 配置组管理</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
@@ -191,196 +196,130 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="col-4">
|
||||
<button class="btn btn-success btn-sm w-100" onclick="showSaveRedisConfigDialog()">
|
||||
<i class="fas fa-save"></i> 保存配置
|
||||
<i class="fas fa-save"></i> 保存配置组
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="col-4">
|
||||
<button class="btn btn-info btn-sm w-100" onclick="showManageRedisConfigDialog()">
|
||||
<i class="fas fa-cog"></i> 管理配置
|
||||
<i class="fas fa-cog"></i> 管理配置组
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button class="btn btn-warning btn-sm w-100" onclick="showImportRedisConfigDialog()">
|
||||
<i class="fas fa-file-import"></i> 导入配置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 查询历史 -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-history me-2"></i>查询历史</h6>
|
||||
<!-- 查询历史和日志 -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<h6><i class="fas fa-history"></i> 历史记录与日志</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-8">
|
||||
<select class="form-select form-select-sm" id="redisHistorySelect">
|
||||
<option value="">选择历史记录...</option>
|
||||
<option value="">选择查询历史...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button class="btn btn-warning btn-sm w-100" onclick="loadSelectedRedisHistory()">
|
||||
<i class="fas fa-history"></i> 加载
|
||||
<i class="fas fa-download"></i> 加载
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<button class="btn btn-secondary btn-sm w-100" onclick="showSaveRedisHistoryDialog()">
|
||||
<i class="fas fa-bookmark"></i> 保存历史
|
||||
<button class="btn btn-info btn-sm w-100" onclick="showManageRedisHistoryDialog()">
|
||||
<i class="fas fa-history"></i> 管理历史
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-info btn-sm w-100" onclick="showManageRedisHistoryDialog()">
|
||||
<i class="fas fa-list"></i> 管理历史
|
||||
<button class="btn btn-outline-info btn-sm w-100" onclick="showRedisQueryLogsDialog()">
|
||||
<i class="fas fa-file-alt"></i> 查询日志
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 一键导入区域 -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-download me-2"></i>配置导入</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<button class="btn btn-outline-primary btn-sm me-2" onclick="showImportRedisConfigDialog('cluster1')">
|
||||
<i class="fas fa-download"></i> 导入集群1配置
|
||||
</button>
|
||||
<button class="btn btn-outline-primary btn-sm" onclick="showImportRedisConfigDialog('cluster2')">
|
||||
<i class="fas fa-download"></i> 导入集群2配置
|
||||
</button>
|
||||
<small class="form-text text-muted d-block mt-2">
|
||||
支持YAML格式配置导入,如:clusterName、clusterAddress、clusterPassword等
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-file-alt me-2"></i>查询日志</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<button class="btn btn-outline-info btn-sm" onclick="showRedisQueryLogsDialog()">
|
||||
<i class="fas fa-eye"></i> 查看查询日志
|
||||
</button>
|
||||
<small class="form-text text-muted d-block mt-2">
|
||||
查看Redis比较操作的详细执行日志
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis集群配置 -->
|
||||
<div class="col-lg-12">
|
||||
<div class="config-section">
|
||||
<h4><i class="fas fa-server me-2"></i>Redis集群配置</h4>
|
||||
|
||||
<div class="row">
|
||||
<!-- 第一个集群配置 -->
|
||||
<div class="col-md-6">
|
||||
<div class="cluster-config" id="cluster1-config">
|
||||
<h5><i class="fas fa-database me-2"></i>集群1 (生产环境)</h5>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">集群名称</label>
|
||||
<input type="text" class="form-control" id="cluster1-name" value="生产集群" placeholder="输入集群名称">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-server"></i> Redis集群配置</h6>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">节点列表</label>
|
||||
<div id="cluster1-nodes">
|
||||
<div class="card-body">
|
||||
<!-- 集群1配置 -->
|
||||
<div class="cluster-config mb-3">
|
||||
<h6 class="text-primary"><i class="fas fa-server"></i> 集群1 (生产)</h6>
|
||||
<div class="row mb-2">
|
||||
<div class="col-12">
|
||||
<label class="form-label">集群名称</label>
|
||||
<input type="text" class="form-control form-control-sm" id="cluster1Name" placeholder="生产集群" value="生产集群">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label">Redis节点</label>
|
||||
<div id="cluster1Nodes">
|
||||
<div class="node-input">
|
||||
<input type="text" class="form-control node-host" placeholder="主机地址" value="127.0.0.1">
|
||||
<input type="number" class="form-control node-port" placeholder="端口" value="7000" style="width: 100px;">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm remove-node">
|
||||
<input type="text" class="form-control form-control-sm me-2" placeholder="127.0.0.1" value="127.0.0.1" style="flex: 2;">
|
||||
<input type="number" class="form-control form-control-sm me-2" placeholder="6379" value="6379" style="flex: 1;">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" onclick="removeRedisNode(this, 'cluster1')">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addNode('cluster1')">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addRedisNode('cluster1')">
|
||||
<i class="fas fa-plus"></i> 添加节点
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">密码 (可选)</label>
|
||||
<input type="password" class="form-control" id="cluster1-password" placeholder="Redis密码">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label class="form-label">连接超时 (秒)</label>
|
||||
<input type="number" class="form-control" id="cluster1-timeout" value="3" min="1" max="30">
|
||||
<label class="form-label">密码</label>
|
||||
<input type="password" class="form-control form-control-sm" id="cluster1Password" placeholder="可选">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label">最大连接数</label>
|
||||
<input type="number" class="form-control" id="cluster1-max-conn" value="16" min="1" max="100">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="button" class="btn btn-outline-success btn-sm" onclick="testConnection('cluster1')">
|
||||
<button class="btn btn-outline-primary btn-sm mt-4 w-100" onclick="testConnection('cluster1')">
|
||||
<i class="fas fa-plug"></i> 测试连接
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第二个集群配置 -->
|
||||
<div class="col-md-6">
|
||||
<div class="cluster-config" id="cluster2-config">
|
||||
<h5><i class="fas fa-database me-2"></i>集群2 (测试环境)</h5>
|
||||
|
||||
<div class="mb-3">
|
||||
<!-- 集群2配置 -->
|
||||
<div class="cluster-config">
|
||||
<h6 class="text-success"><i class="fas fa-server"></i> 集群2 (测试)</h6>
|
||||
<div class="row mb-2">
|
||||
<div class="col-12">
|
||||
<label class="form-label">集群名称</label>
|
||||
<input type="text" class="form-control" id="cluster2-name" value="测试集群" placeholder="输入集群名称">
|
||||
<input type="text" class="form-control form-control-sm" id="cluster2Name" placeholder="测试集群" value="测试集群">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">节点列表</label>
|
||||
<div id="cluster2-nodes">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label">Redis节点</label>
|
||||
<div id="cluster2Nodes">
|
||||
<div class="node-input">
|
||||
<input type="text" class="form-control node-host" placeholder="主机地址" value="127.0.0.1">
|
||||
<input type="number" class="form-control node-port" placeholder="端口" value="7001" style="width: 100px;">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm remove-node">
|
||||
<input type="text" class="form-control form-control-sm me-2" placeholder="127.0.0.1" value="127.0.0.1" style="flex: 2;">
|
||||
<input type="number" class="form-control form-control-sm me-2" placeholder="6380" value="6380" style="flex: 1;">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" onclick="removeRedisNode(this, 'cluster2')">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addNode('cluster2')">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addRedisNode('cluster2')">
|
||||
<i class="fas fa-plus"></i> 添加节点
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">密码 (可选)</label>
|
||||
<input type="password" class="form-control" id="cluster2-password" placeholder="Redis密码">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label class="form-label">连接超时 (秒)</label>
|
||||
<input type="number" class="form-control" id="cluster2-timeout" value="3" min="1" max="30">
|
||||
<label class="form-label">密码</label>
|
||||
<input type="password" class="form-control form-control-sm" id="cluster2Password" placeholder="可选">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label">最大连接数</label>
|
||||
<input type="number" class="form-control" id="cluster2-max-conn" value="16" min="1" max="100">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="button" class="btn btn-outline-success btn-sm" onclick="testConnection('cluster2')">
|
||||
<button class="btn btn-outline-primary btn-sm mt-4 w-100" onclick="testConnection('cluster2')">
|
||||
<i class="fas fa-plug"></i> 测试连接
|
||||
</button>
|
||||
</div>
|
||||
@@ -391,141 +330,189 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 查询选项 -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<!-- 查询面板和结果展示 -->
|
||||
<div class="col-lg-8">
|
||||
<div class="config-section">
|
||||
<h4><i class="fas fa-search me-2"></i>查询选项</h4>
|
||||
<h4><i class="fas fa-search"></i> 查询配置</h4>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">查询模式</label>
|
||||
<!-- 查询模式选择 -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-sliders-h"></i> 查询模式</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="queryMode" id="randomMode" value="random" checked>
|
||||
<input class="form-check-input" type="radio" name="queryMode" id="randomMode" value="random" checked onchange="toggleQueryMode()">
|
||||
<label class="form-check-label" for="randomMode">
|
||||
<i class="fas fa-random me-1"></i>随机采样查询
|
||||
<strong>随机采样模式</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="queryMode" id="specifiedMode" value="specified">
|
||||
<label class="form-check-label" for="specifiedMode">
|
||||
<i class="fas fa-list me-1"></i>指定Key查询
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 随机采样选项 -->
|
||||
<div id="randomOptions">
|
||||
<div id="randomOptions" class="mt-2">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="col-6">
|
||||
<label class="form-label">采样数量</label>
|
||||
<input type="number" class="form-control" id="sampleCount" value="100" min="1" max="10000">
|
||||
<input type="number" class="form-control form-control-sm" id="sampleCount" value="100" min="1" max="10000">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Key匹配模式</label>
|
||||
<input type="text" class="form-control" id="keyPattern" value="*" placeholder="例如: user:*">
|
||||
<div class="col-6">
|
||||
<label class="form-label">Key模式</label>
|
||||
<input type="text" class="form-control form-control-sm" id="keyPattern" value="*" placeholder="*">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">数据源集群</label>
|
||||
<select class="form-select" id="sourceCluster">
|
||||
<option value="cluster1">集群1 (生产环境)</option>
|
||||
<option value="cluster2" selected>集群2 (测试环境)</option>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<label class="form-label">源集群</label>
|
||||
<select class="form-select form-select-sm" id="sourceCluster">
|
||||
<option value="cluster1">从集群1获取Key</option>
|
||||
<option value="cluster2" selected>从集群2获取Key</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 指定Key选项 -->
|
||||
<div id="specifiedOptions" style="display: none;">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">指定Key列表 (每行一个)</label>
|
||||
<textarea class="form-control query-keys" id="specifiedKeys"
|
||||
placeholder="请输入要查询的Key,每行一个 例如: user:1001 user:1002 session:abc123"></textarea>
|
||||
<div class="col-md-6">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="queryMode" id="specifiedMode" value="specified" onchange="toggleQueryMode()">
|
||||
<label class="form-check-label" for="specifiedMode">
|
||||
<strong>指定Key模式</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div id="specifiedOptions" class="mt-2" style="display: none;">
|
||||
<label class="form-label">Key列表 (每行一个)</label>
|
||||
<textarea class="form-control query-keys" id="specifiedKeys" rows="6" placeholder="输入要查询的Key,每行一个 例如: user:1001 user:1002 session:abc123"></textarea>
|
||||
<small class="form-text text-muted">支持大批量Key查询,建议单次不超过1000个</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="text-center">
|
||||
<!-- 执行按钮 -->
|
||||
<div class="text-center mb-4">
|
||||
<button type="button" class="btn btn-redis btn-lg me-3" onclick="executeRedisComparison()">
|
||||
<i class="fas fa-play me-2"></i>开始比较
|
||||
<i class="fas fa-play me-2"></i>开始Redis数据比较
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" onclick="clearResults()">
|
||||
<i class="fas fa-eraser me-2"></i>清空结果
|
||||
</button>
|
||||
|
||||
<div class="loading mt-3">
|
||||
<div class="spinner-border text-danger me-2" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<span>正在执行Redis数据比较,请稍候...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 结果展示区域 -->
|
||||
<div class="result-section" id="results" style="display: none;">
|
||||
<!-- 统计卡片 -->
|
||||
<div class="row" id="statsCards">
|
||||
<!-- 统计卡片将通过JavaScript动态生成 -->
|
||||
<div class="result-section" id="resultSection" style="display: none;">
|
||||
<!-- 统计信息 -->
|
||||
<div class="row" id="stats">
|
||||
<!-- 统计卡片将在这里动态生成 -->
|
||||
</div>
|
||||
|
||||
<!-- 详细结果 -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<ul class="nav nav-tabs" id="resultTabs" role="tablist">
|
||||
<!-- 结果选项卡导航 -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs" id="resultTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="differences-tab" data-bs-toggle="tab" data-bs-target="#differences" type="button" role="tab">
|
||||
<i class="fas fa-exclamation-triangle me-1"></i>差异数据 (<span id="diff-count">0</span>)
|
||||
<button class="nav-link active" id="differences-tab" data-bs-toggle="tab" data-bs-target="#differences-panel" type="button" role="tab">
|
||||
<i class="fas fa-exclamation-triangle"></i> 差异详情 <span class="badge bg-danger ms-1" id="diff-count">0</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="identical-tab" data-bs-toggle="tab" data-bs-target="#identical" type="button" role="tab">
|
||||
<i class="fas fa-check-circle me-1"></i>相同数据 (<span id="identical-count">0</span>)
|
||||
<button class="nav-link" id="identical-tab" data-bs-toggle="tab" data-bs-target="#identical-panel" type="button" role="tab">
|
||||
<i class="fas fa-check-circle"></i> 相同结果 <span class="badge bg-success ms-1" id="identical-count">0</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="missing-tab" data-bs-toggle="tab" data-bs-target="#missing" type="button" role="tab">
|
||||
<i class="fas fa-question-circle me-1"></i>缺失数据 (<span id="missing-count">0</span>)
|
||||
<button class="nav-link" id="missing-tab" data-bs-toggle="tab" data-bs-target="#missing-panel" type="button" role="tab">
|
||||
<i class="fas fa-question-circle"></i> 缺失数据 <span class="badge bg-warning ms-1" id="missing-count">0</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="performance-tab" data-bs-toggle="tab" data-bs-target="#performance" type="button" role="tab">
|
||||
<i class="fas fa-chart-line me-1"></i>性能报告
|
||||
<button class="nav-link" id="raw-data-tab" data-bs-toggle="tab" data-bs-target="#raw-data-panel" type="button" role="tab">
|
||||
<i class="fas fa-database"></i> 原生数据
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="summary-tab" data-bs-toggle="tab" data-bs-target="#summary-panel" type="button" role="tab">
|
||||
<i class="fas fa-chart-pie"></i> 比较总结
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content" id="resultTabContent">
|
||||
<!-- 差异数据 -->
|
||||
<div class="tab-pane fade show active" id="differences" role="tabpanel">
|
||||
<div class="mt-3" id="differenceResults">
|
||||
<!-- 差异结果将通过JavaScript动态生成 -->
|
||||
<!-- 差异详情面板 -->
|
||||
<div class="tab-pane fade show active" id="differences-panel" role="tabpanel">
|
||||
<div id="differences-content">
|
||||
<!-- 差异内容将在这里动态生成 -->
|
||||
</div>
|
||||
<div id="differences-pagination" class="d-flex justify-content-center mt-3">
|
||||
<!-- 分页将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 相同数据 -->
|
||||
<div class="tab-pane fade" id="identical" role="tabpanel">
|
||||
<div class="mt-3" id="identicalResults">
|
||||
<!-- 相同结果将通过JavaScript动态生成 -->
|
||||
<!-- 相同结果面板 -->
|
||||
<div class="tab-pane fade" id="identical-panel" role="tabpanel">
|
||||
<div id="identical-content">
|
||||
<!-- 相同结果内容将在这里动态生成 -->
|
||||
</div>
|
||||
<div id="identical-pagination" class="d-flex justify-content-center mt-3">
|
||||
<!-- 分页将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 缺失数据 -->
|
||||
<div class="tab-pane fade" id="missing" role="tabpanel">
|
||||
<div class="mt-3" id="missingResults">
|
||||
<!-- 缺失结果将通过JavaScript动态生成 -->
|
||||
<!-- 缺失数据面板 -->
|
||||
<div class="tab-pane fade" id="missing-panel" role="tabpanel">
|
||||
<div id="missing-content">
|
||||
<!-- 缺失数据内容将在这里动态生成 -->
|
||||
</div>
|
||||
<div id="missing-pagination" class="d-flex justify-content-center mt-3">
|
||||
<!-- 分页将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 性能报告 -->
|
||||
<div class="tab-pane fade" id="performance" role="tabpanel">
|
||||
<div class="performance-section mt-3" id="performanceReport">
|
||||
<!-- 性能报告将通过JavaScript动态生成 -->
|
||||
<!-- 原生数据面板 -->
|
||||
<div class="tab-pane fade" id="raw-data-panel" role="tabpanel">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5><i class="fas fa-server text-primary"></i> 集群1 原生数据</h5>
|
||||
<div class="mb-3">
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-primary active" onclick="switchRawDataView('cluster1', 'formatted')">格式化</button>
|
||||
<button type="button" class="btn btn-outline-primary" onclick="switchRawDataView('cluster1', 'raw')">原始</button>
|
||||
<button type="button" class="btn btn-outline-primary" onclick="exportRawData('cluster1')">导出</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster1-raw-data" class="redis-value" style="max-height: 500px; overflow-y: auto;">
|
||||
<!-- 集群1原生数据将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h5><i class="fas fa-server text-success"></i> 集群2 原生数据</h5>
|
||||
<div class="mb-3">
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-success active" onclick="switchRawDataView('cluster2', 'formatted')">格式化</button>
|
||||
<button type="button" class="btn btn-outline-success" onclick="switchRawDataView('cluster2', 'raw')">原始</button>
|
||||
<button type="button" class="btn btn-outline-success" onclick="exportRawData('cluster2')">导出</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster2-raw-data" class="redis-value" style="max-height: 500px; overflow-y: auto;">
|
||||
<!-- 集群2原生数据将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<strong>提示:</strong>原生数据显示实际从Redis查询到的数据。格式化视图便于阅读,原始视图保持数据原始格式。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 比较总结面板 -->
|
||||
<div class="tab-pane fade" id="summary-panel" role="tabpanel">
|
||||
<div id="performanceReport">
|
||||
<!-- 性能报告将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -534,22 +521,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis配置组保存模态框 -->
|
||||
<!-- 加载提示 -->
|
||||
<div class="loading" id="loadingIndicator">
|
||||
<div class="position-fixed top-50 start-50 translate-middle bg-dark text-white p-4 rounded shadow" style="z-index: 9999;">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="spinner-border spinner-border-sm me-3" role="status"></div>
|
||||
<span id="loadingText">正在执行Redis数据比较,请稍候...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 配置组保存对话框 -->
|
||||
<div class="modal fade" id="saveRedisConfigModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-save me-2"></i>保存Redis配置组</h5>
|
||||
<h5 class="modal-title">保存Redis配置组</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">配置组名称 *</label>
|
||||
<input type="text" class="form-control" id="redisConfigGroupName" placeholder="输入配置组名称">
|
||||
<label for="redisConfigName" class="form-label">配置组名称</label>
|
||||
<input type="text" class="form-control" id="redisConfigName" placeholder="输入配置组名称">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">描述</label>
|
||||
<textarea class="form-control" id="redisConfigGroupDescription" placeholder="输入配置组描述(可选)"></textarea>
|
||||
<label for="redisConfigDescription" class="form-label">描述</label>
|
||||
<textarea class="form-control" id="redisConfigDescription" rows="3" placeholder="配置组描述(可选)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -560,12 +557,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis配置管理模态框 -->
|
||||
<!-- 配置组管理对话框 -->
|
||||
<div class="modal fade" id="manageRedisConfigModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-cog me-2"></i>Redis配置组管理</h5>
|
||||
<h5 class="modal-title">管理Redis配置组</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -573,35 +570,88 @@
|
||||
<!-- 配置组列表将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 历史记录管理对话框 -->
|
||||
<div class="modal fade" id="manageRedisHistoryModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">管理Redis查询历史</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="redisHistoryList">
|
||||
<!-- 历史记录列表将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis配置导入模态框 -->
|
||||
<!-- 查询日志对话框 -->
|
||||
<div class="modal fade" id="redisQueryLogsModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Redis查询日志</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<button class="btn btn-sm btn-outline-primary me-2" onclick="refreshRedisQueryLogs()">
|
||||
<i class="fas fa-sync-alt"></i> 刷新
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="clearRedisQueryLogs()">
|
||||
<i class="fas fa-trash"></i> 清空日志
|
||||
</button>
|
||||
</div>
|
||||
<div class="log-viewer" id="redisQueryLogs">
|
||||
<!-- 查询日志将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 导入配置对话框 -->
|
||||
<div class="modal fade" id="importRedisConfigModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-download me-2"></i>导入Redis配置</h5>
|
||||
<h5 class="modal-title">导入Redis配置</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info">
|
||||
<strong>支持的配置格式:</strong><br>
|
||||
clusterName: "redis-test"<br>
|
||||
clusterAddress: "10.20.2.109:6470"<br>
|
||||
clusterPassword: ""<br>
|
||||
cachePrefix: message.status.Writer.<br>
|
||||
cacheTtl: 2000<br>
|
||||
async: true
|
||||
<div class="mb-3">
|
||||
<label for="configFormat" class="form-label">配置格式</label>
|
||||
<select class="form-select" id="configFormat" onchange="updateConfigTemplate()">
|
||||
<option value="yaml">YAML格式</option>
|
||||
<option value="json">JSON格式</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">配置内容</label>
|
||||
<textarea class="form-control" id="redisConfigImportText" rows="8"
|
||||
placeholder="请粘贴Redis配置内容..."></textarea>
|
||||
<label for="configContent" class="form-label">配置内容</label>
|
||||
<textarea class="form-control" id="configContent" rows="15" placeholder="请粘贴配置内容..."></textarea>
|
||||
<small class="form-text text-muted">支持YAML和JSON格式的Redis配置</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="accordion" id="configTemplateAccordion">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="templateHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#templateCollapse">
|
||||
<i class="fas fa-code me-2"></i>配置示例
|
||||
</button>
|
||||
</h2>
|
||||
<div id="templateCollapse" class="accordion-collapse collapse" data-bs-parent="#configTemplateAccordion">
|
||||
<div class="accordion-body">
|
||||
<pre id="configTemplate" class="bg-light p-3 rounded" style="font-size: 0.85em;"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -612,84 +662,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis查询历史保存模态框 -->
|
||||
<div class="modal fade" id="saveRedisHistoryModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-bookmark me-2"></i>保存Redis查询历史</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">历史记录名称 *</label>
|
||||
<input type="text" class="form-control" id="redisHistoryName" placeholder="输入历史记录名称">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">描述</label>
|
||||
<textarea class="form-control" id="redisHistoryDescription" placeholder="输入历史记录描述(可选)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-success" onclick="saveRedisQueryHistory()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis查询历史管理模态框 -->
|
||||
<div class="modal fade" id="manageRedisHistoryModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-list me-2"></i>Redis查询历史管理</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="redisHistoryList">
|
||||
<!-- 查询历史列表将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Redis查询日志模态框 -->
|
||||
<div class="modal fade" id="redisQueryLogsModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-file-alt me-2"></i>Redis查询日志</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0">Redis查询执行日志</h6>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-outline-primary me-2" onclick="refreshRedisQueryLogs()">
|
||||
<i class="fas fa-sync-alt"></i> 刷新
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="clearRedisQueryLogs()">
|
||||
<i class="fas fa-trash"></i> 清空
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="redisQueryLogs" class="log-viewer">
|
||||
<!-- 查询日志将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 引入必要的JavaScript -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/static/js/redis_compare.js"></script>
|
||||
</body>
|
||||
|
Reference in New Issue
Block a user