You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
4.9 KiB

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Excel Merge</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
* { box-sizing: border-box; }
body {
margin: 0;
padding: 32px 24px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial;
background: radial-gradient(circle at top, #111827, #0b0f14);
color: #e5e7eb;
}
.card-box {
max-width: 1200px;
margin: auto;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.08);
padding: 32px 28px;
border-radius: 18px;
backdrop-filter: blur(10px);
}
h3 { color: #f3f4f6; margin-bottom: 22px; font-size: 20px; }
label { color: #cbd5e1; font-size: 13px; display: block; margin-bottom: 6px; }
input, select, textarea {
background: rgba(255,255,255,0.06) !important;
border: 1px solid rgba(255,255,255,0.12) !important;
color: #e5e7eb !important;
border-radius: 10px !important;
}
input::placeholder, textarea::placeholder { color: rgba(229,231,235,0.45) !important; }
input:focus, select:focus, textarea:focus {
outline: none;
border-color: rgba(59,130,246,0.8) !important;
box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}
select option { background: #111827; color: #e5e7eb; }
.btn { margin-right: 10px; margin-top: 8px; }
.btn-primary { background: #2563eb; border: none; }
.btn-primary:hover { background: #1d4ed8; }
.btn-secondary { background: rgba(255,255,255,0.1); border: none; color: #e5e7eb; }
.btn-secondary:hover { background: rgba(255,255,255,0.15); }
.btn-success { background: #16a34a; border: none; }
.btn-success:hover { background: #15803d; }
.file-box {
background: rgba(255,255,255,0.03);
padding: 14px;
border-radius: 12px;
border: 1px solid rgba(255,255,255,0.06);
margin-bottom: 14px;
}
.preview-box {
max-height: 700px;
overflow: auto;
margin-top: 20px;
border-radius: 12px;
border: 1px solid rgba(255,255,255,0.08);
}
.preview-table { background: #ffffff; color: #111827; border-radius: 10px; overflow: hidden; min-width: 600px; }
.preview-table thead th { position: sticky; top: 0; background: #f3f4f6; color: #111827; font-size: 13px; padding: 10px 12px; }
.preview-table tbody td { font-size: 13px; padding: 9px 12px; }
.h1c { background: #ffe8e8 !important; }
.h2c { background: #f7e8ff !important; }
.alert { border-radius: 10px; margin-top: 16px; }
@media (max-width: 768px) {
body { padding: 20px 14px; }
.card-box { padding: 22px 18px; }
h3 { font-size: 18px; }
.preview-box { max-height: 450px; }
.btn { width: 100%; margin-right: 0; }
}
</style>
</head>
<body>
<div class="card-box">
<h3>📊 Excel / CSV 文件整合工具</h3>
<form method="post" action="{{ url_for('tool', name='excel') }}" enctype="multipart/form-data">
<div class="row">
<div class="col-md-6 file-box">
<label>文件1 {% if file1_name %}<span style="color:#f87171">✔ {{file1_name}}</span>{% endif %}</label>
<input type="file" name="file1" class="form-control" accept=".xlsx,.xls,.csv">
</div>
<div class="col-md-6 file-box">
<label>文件2 {% if file2_name %}<span style="color:#c084fc">✔ {{file2_name}}</span>{% endif %}</label>
<input type="file" name="file2" class="form-control" accept=".xlsx,.xls,.csv">
</div>
</div>
<br>
<div class="row">
<div class="col-md-4"><input name="key1" value="{{key1}}" placeholder="文件1关联字段" class="form-control" required></div>
<div class="col-md-4"><input name="key2" value="{{key2}}" placeholder="文件2关联字段" class="form-control" required></div>
<div class="col-md-4"><select name="join_type" class="form-select"><option value="left" {% if join_type=='left' %}selected{% endif %}>左连接</option><option value="inner" {% if join_type=='inner' %}selected{% endif %}>内连接</option><option value="outer" {% if join_type=='outer' %}selected{% endif %}>外连接</option></select></div>
</div>
<br>
<button class="btn btn-primary">开始整合</button>
<a href="{{ url_for('reset') }}" class="btn btn-secondary">重新开始</a>
</form>
{% if message %}
<div class="alert {% if '错误' in message %}alert-danger{% else %}alert-success{% endif %}">{{message}}</div>
{% endif %}
{% if preview_data %}
<div class="preview-box">{{preview_data|safe}}</div>
<a href="{{ url_for('download', filename=download_file) }}" class="btn btn-success mt-3">下载Excel</a>
{% endif %}
</div>
</div>
<script>
window.onload=function(){
const table=document.getElementById('previewTable');
if(!table)return;
const k1='{{key1}}',k2='{{key2}}';
let i1=-1,i2=-1;
table.querySelectorAll('thead th').forEach((th,i)=>{const t=th.innerText.trim();if(t===k1){i1=i;th.classList.add('h1c')}if(t===k2){i2=i;th.classList.add('h2c')}});
table.querySelectorAll('tbody tr').forEach(r=>{const tds=r.querySelectorAll('td');if(i1>=0) tds[i1]?.classList.add('h1c');if(i2>=0) tds[i2]?.classList.add('h2c')}});
}
</script>
</body>
</html>