XH_Digital_Management/excel_parser/templates/excel_preview_table.html

263 lines
9.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<title>Excel解析工具</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- Favicon icon -->
<link rel="icon" href="{% static 'images/favicon.svg' %}" type="image/x-icon">
<!-- fontawesome icon -->
<link rel="stylesheet" href="{% static 'fonts/fontawesome/css/fontawesome-all.min.css' %}">
<!-- animation css -->
<link rel="stylesheet" href="{% static 'plugins/animation/css/animate.min.css' %}">
<!-- vendor css -->
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<style>
body {
background-color: #f8f9fa;
}
.page-wrapper {
padding: 20px;
}
.table-container {
position: relative;
max-height: 70vh;
overflow-y: auto;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
border-radius: 10px;
background-color: #fff;
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
}
thead th {
position: sticky;
top: 0;
background: #007bff;
color: #fff;
z-index: 1;
padding: 15px;
text-align: center;
}
th, td {
border: none;
padding: 12px;
}
tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
.form-control {
border: 1px solid #ced4da;
border-radius: 5px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.form-control:focus {
border-color: #80bdff;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
.error-cell {
background-color: #f8d7da;
border-color: #f5c2c7;
}
.btn-primary {
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #0056b3;
}
#alertContainer {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
width: 400px;
}
.dynamic-width {
transition: width 0.3s ease;
min-width: 50px;
max-width: 300px;
}
#width-test {
position: absolute;
visibility: hidden;
height: auto;
width: auto;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="alertContainer"></div>
<div class="page-wrapper">
<form id="preview-form" method="post">
{% csrf_token %}
<div class="container">
<div class="row mb-4">
<div class="col">
<h2 class="text-primary"><i class="fas fa-file-excel me-2"></i>上传文件预览</h2>
</div>
<div class="col text-end">
<button type="button" class="btn btn-outline-secondary" onclick="history.back();">
<i class="fas fa-arrow-left me-2"></i>返回
</button>
</div>
</div>
<div class="table-container animate__animated animate__fadeIn">
<table id="form-input-table" class="table table-hover">
<thead>
<tr>
<th>序号</th>
{% for column in columns %}
<th>{{ column }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in table_data %}
<tr>
<td>
<input type="text" class="form-control text-center" style="width: 50px" value="{{ forloop.counter }}" disabled>
</td>
{% for cell in row %}
<td>
<input type="text" class="form-control dynamic-width" name="cell_{{ forloop.parentloop.counter0 }}_{{ forloop.counter0 }}" value="{{ cell|default_if_none:'-' }}">
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row mt-4">
<div class="col">
<span id="totalData" class="text-muted">数据总数: {{ table_data|length }}</span>
</div>
<div class="col text-end" id="actions">
<button id="saveButton" type="button" class="btn btn-primary">
<i class="fas fa-save me-2"></i>保存
</button>
</div>
</div>
</div>
</form>
</div>
<div id="width-test"></div>
<script src="{% static 'js/vendor-all.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/custom.js' %}"></script>
<script>
function adjustInputWidth(input) {
const widthTest = document.getElementById('width-test');
const minWidth = 100; // 最小宽度(像素)
const maxWidth = 300; // 最大宽度(像素)
const padding = 20; // 输入框的内边距左右各10px
// 设置与输入框相同的字体样式
const inputStyle = window.getComputedStyle(input);
widthTest.style.font = inputStyle.font;
widthTest.style.fontSize = inputStyle.fontSize;
widthTest.style.fontWeight = inputStyle.fontWeight;
widthTest.style.fontFamily = inputStyle.fontFamily;
widthTest.style.letterSpacing = inputStyle.letterSpacing;
// 测量文本宽度
widthTest.textContent = input.value || input.placeholder;
let textWidth = widthTest.offsetWidth;
// 设置输入框宽度
let width = Math.max(minWidth, Math.min(textWidth + padding, maxWidth));
input.style.width = `${width}px`;
}
function adjustAllInputWidths() {
const inputs = document.querySelectorAll('.dynamic-width');
inputs.forEach(adjustInputWidth);
}
// 页面加载时调用函数
document.addEventListener('DOMContentLoaded', function () {
adjustAllInputWidths();
// 为所有输入框添加输入事件监听器
document.querySelectorAll('.dynamic-width').forEach(input => {
input.addEventListener('input', function () {
adjustInputWidth(this);
});
});
});
document.getElementById('saveButton').addEventListener('click', function () {
const table = document.getElementById('form-input-table');
const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent.trim()).slice(1); // 跳过"序号"列
const data = [];
// 清除之前的错误标记
const inputs = table.querySelectorAll('input');
inputs.forEach(input => {
input.classList.remove('is-invalid');
});
for (let i = 0; i < table.tBodies[0].rows.length; i++) {
const row = table.tBodies[0].rows[i];
const rowData = {};
for (let j = 1; j < row.cells.length; j++) { // 跳过序号列
rowData[headers[j - 1]] = row.cells[j].querySelector('input').value;
}
data.push(rowData);
}
fetch("{% url 'ep_common_save' %}", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({data: data})
})
.then(response => response.json())
.then(result => {
if (result.status === 'success') {
showAlert('success', result.message);
setTimeout(() => {
window.location.href = result.redirect_url;
}, 2000);
} else {
const errorMessage = result.message + '<br>' + result.errors.join('<br>');
showAlert('error', errorMessage);
result.errors.forEach(error => {
const regex = /第【(\d+)】行【(.+?)】字段输入错误/;
const matches = error.match(regex);
if (matches) {
const row = parseInt(matches[1], 10);
const field = matches[2];
const column = headers.findIndex(header => header.trim() === field.trim()) + 1; // +1 因为我们跳过了序号列
if (column !== -1 && table.tBodies[0].rows[row - 1] && table.tBodies[0].rows[row - 1].cells[column]) {
table.tBodies[0].rows[row - 1].cells[column].querySelector('input').classList.add('is-invalid');
}
}
});
}
});
});
</script>
</body>
</html>