<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>数据对比</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="shortcut icon" href="https:/chenwuzhu.cn/upload/IMG_0495.JPG"> <style> .container { height: 98vh; display: flex; } .left { flex: 40%; /* 左边 div 占 40% */ display: table; flex-direction: column; background-color: #f0f0f0; padding: 10px; box-sizing: border-box; overflow-y: auto; border-radius: 12px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); margin-right: 10px; } .config { flex: 1; /* 上半部分 */ display: unset; flex-direction: row; } .config-content { display: flex; flex: 100%; } .buttons { display: flex; flex-direction: revert-layer; align-items: center; margin-top: 10px; flex-shrink: 0; /* 防止按钮区域收缩 */ justify-content: space-around; } .result { flex: 60%; /* 右边 div 占 60% */ background-color: #f9eded; padding: 10px; box-sizing: border-box; overflow-y: auto; border-radius: 12px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); position: relative; } .description { color: gray; } .config .config1, .config2 { flex: 50%; /* 修改 flex 值为 50% */ display: flex; flex-direction: column; } .config-item { display: block; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 15px; background-color: white; padding: 2px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .config-keys { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .config-desc { grid-column: 1 / -1; text-align: left; } .config-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 98%; } input[type="text"] { padding: 8px; border: 1px solid #ddd; border-radius: 6px; width: 100%; } button { padding: 8px 16px; background-color: #4CAF50; color: white; border: none; border-radius: 6px; cursor: pointer; transition: background-color 0.3s; } button:hover { background-color: #45a049; } h1, h2 { color: #333; border-bottom: 2px solid #eee; padding-bottom: 8px; border-radius: 0 0 4px 4px; } .social-icons { position: absolute; top: 15px; right: 15px; display: flex; gap: 15px; } .social-icons a { color: #333; font-size: 24px; transition: color 0.3s; } .social-icons a:hover { color: #4CAF50; } pre { background-color: #fff; padding: 10px; border-radius: 8px; white-space: pre-wrap; word-wrap: break-word; max-height: 80vh; overflow-y: auto; } </style> </head> <body> <div class="container"> <div class="left"> <div class="config"> <h2>配置项</h2> <form action="{{ url_for('update_config') }}" method="post"> {% for key1 in config.__dict__.keys() if key1.endswith('_1') %} {% set base_key = key1[:-2] %} {% set key2 = base_key + '_2' %} {% set desc_key = 'desc_' + base_key %} <div class="config-item"> <div class="config-keys"> <label for="{{ key1 }}">{{ key1 }}</label> <label for="{{ key2 }}">{{ key2 }}</label> </div> <div class="config-desc"> <span class="description">{{ config.__dict__.get(desc_key, '') }}</span> </div> <div class="config-inputs"> <input type="text" id="{{ key1 }}" name="{{ key1 }}" value="{{ config.__dict__[key1] }}"> <input type="text" id="{{ key2 }}" name="{{ key2 }}" value="{{ config.__dict__[key2] }}"> </div> </div> {% endfor %} <div class="buttons"> <button type="submit">保存配置</button> <button type="button" id="runButton">运行</button> <button type="button" id="exitButton" style="background-color: #f44336;">退出程序</button> </div> </form> </div> </div> <div class="result"> <div class="social-icons"> <a href="https://chenwuzhu.cn" target="_blank" title="微信"><i class="fab fa-weixin"></i></a> <a href="https://git.chenwuzhu.cn/chenwu/Compare-PBI-Data" target="_blank" title="Git"><i class="fab fa-github"></i></a> </div> <h1>运行结果</h1> <pre id="resultOutput">{{ result }}</pre> </div> </div> <script> document.getElementById('runButton').addEventListener('click', function() { // 清空结果区域 document.getElementById('resultOutput').textContent = ''; // 获取表单数据 const form = document.querySelector('form'); const formData = new FormData(form); // 创建EventSource连接 const eventSource = new EventSource('/stream'); // 监听消息事件 eventSource.onmessage = function(event) { const resultOutput = document.getElementById('resultOutput'); // 解析JSON数据并显示消息内容 try { const jsonData = JSON.parse(event.data); if (jsonData.message) { resultOutput.textContent += jsonData.message + '\n\n'; resultOutput.scrollTop = resultOutput.scrollHeight; // 自动滚动到底部 } } catch (error) { console.error('解析JSON数据失败:', error); // 如果解析失败,则直接显示原始数据 resultOutput.textContent += event.data + '\n\n'; resultOutput.scrollTop = resultOutput.scrollHeight; } }; // 监听错误事件 eventSource.onerror = function() { eventSource.close(); }; // 发送运行请求 fetch('{{ url_for("run") }}', { method: 'POST', body: formData }).catch(function(error) { console.error('Error:', error); eventSource.close(); }); // 添加一个特殊的消息监听器,用于检测处理完成 const checkCompletion = function() { try { // 尝试解析JSON数据 const jsonData = JSON.parse(event.data); // 检测到结束分隔符时关闭连接 if (jsonData.message && jsonData.message.includes('---*********************************************************---')) { setTimeout(function() { eventSource.close(); }, 500); } else { setTimeout(checkCompletion, 500); } } catch (error) { // 如果解析失败,检查原始数据 if (event.data.includes('---*********************************************************---')) { setTimeout(function() { eventSource.close(); }, 500); } else { setTimeout(checkCompletion, 500); } } }; setTimeout(checkCompletion, 1000); }); // 添加退出按钮的事件监听器 document.getElementById('exitButton').addEventListener('click', function() { if (confirm('确定要退出程序吗?')) { fetch('{{ url_for("exit_app") }}', { method: 'POST' }).then(function(response) { window.close(); // 如果window.close()不起作用(在某些浏览器中可能被阻止),显示一条消息 setTimeout(function() { alert('程序已关闭,请手动关闭此窗口。'); }, 1000); }).catch(function(error) { console.error('Error:', error); alert('关闭程序时出错,请手动关闭窗口。'); }); } }); </script> </body> </html>