feat: 增加网页comment字段
This commit is contained in:
@@ -1,11 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Saved Images List</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.min.js "></script>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
.controls { margin-bottom: 20px; }
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 8px 16px;
|
||||
margin-right: 10px;
|
||||
@@ -14,23 +22,59 @@
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover { background-color: #0056b3; }
|
||||
button:disabled { background-color: #cccccc; cursor: not-allowed; }
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
||||
th { background-color: #f2f2f2; }
|
||||
.image-preview { width: 100px; height: auto; }
|
||||
input[type="checkbox"] { transform: scale(1.2); }
|
||||
#status { padding: 10px; margin: 10px 0; background-color: #f0f0f0; }
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background-color: #cccccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.image-preview {
|
||||
width: 100px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
#status {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Saved Images</h1>
|
||||
<!-- 添加导航链接 -->
|
||||
@@ -41,18 +85,20 @@
|
||||
<button id="exportBtn" disabled>Export Selected</button>
|
||||
<button id="deleteSelectedBtn" disabled>Delete Selected</button>
|
||||
</div>
|
||||
<!-- 修改表格头部 -->
|
||||
<table id="imagesTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<input type="checkbox" id="selectAllCheckbox">
|
||||
<label for="selectAllCheckbox" style="display: inline-block; margin-left: 5px; cursor: pointer;">Select All</label>
|
||||
<label for="selectAllCheckbox"
|
||||
style="display: inline-block; margin-left: 5px; cursor: pointer;">Select All</label>
|
||||
</th>
|
||||
<th>ID</th>
|
||||
<th>Left Image</th>
|
||||
<th>Right Image</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Created At</th>
|
||||
<th>Comment</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -82,6 +128,7 @@
|
||||
}
|
||||
|
||||
// 渲染表格
|
||||
// 修改渲染表格的函数
|
||||
function renderTable(images) {
|
||||
const tbody = document.getElementById('imagesTableBody');
|
||||
tbody.innerHTML = ''; // 清空现有内容
|
||||
@@ -90,14 +137,14 @@
|
||||
const row = tbody.insertRow();
|
||||
row.insertCell(0).innerHTML = `<input type="checkbox" class="selectCheckbox" data-id="${image.id}">`;
|
||||
row.insertCell(1).textContent = image.id;
|
||||
|
||||
|
||||
const leftCell = row.insertCell(2);
|
||||
const leftImg = document.createElement('img');
|
||||
// 修改这里:使用 Flask 静态文件路径
|
||||
leftImg.src = `/static/received/left/${image.left_filename}`;
|
||||
leftImg.alt = "Left Image";
|
||||
leftImg.className = 'image-preview';
|
||||
leftImg.onerror = function() { this.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="75" viewBox="0 0 100 75"><rect width="100" height="75" fill="%23eee"/><text x="50" y="40" font-family="Arial" font-size="12" fill="%23999" text-anchor="middle">No Image</text></svg>'; };
|
||||
leftImg.onerror = function () { this.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="75" viewBox="0 0 100 75"><rect width="100" height="75" fill="%23eee"/><text x="50" y="40" font-family="Arial" font-size="12" fill="%23999" text-anchor="middle">No Image</text></svg>'; };
|
||||
leftCell.appendChild(leftImg);
|
||||
|
||||
const rightCell = row.insertCell(3);
|
||||
@@ -106,15 +153,47 @@
|
||||
rightImg.src = `/static/received/right/${image.right_filename}`;
|
||||
rightImg.alt = "Right Image";
|
||||
rightImg.className = 'image-preview';
|
||||
rightImg.onerror = function() { this.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="75" viewBox="0 0 100 75"><rect width="100" height="75" fill="%23eee"/><text x="50" y="40" font-family="Arial" font-size="12" fill="%23999" text-anchor="middle">No Image</text></svg>'; };
|
||||
rightImg.onerror = function () { this.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="75" viewBox="0 0 100 75"><rect width="100" height="75" fill="%23eee"/><text x="50" y="40" font-family="Arial" font-size="12" fill="%23999" text-anchor="middle">No Image</text></svg>'; };
|
||||
rightCell.appendChild(rightImg);
|
||||
|
||||
row.insertCell(4).textContent = new Date(image.timestamp * 1000).toISOString();
|
||||
row.insertCell(5).textContent = image.created_at;
|
||||
|
||||
// 添加可编辑的comment单元格
|
||||
const commentCell = row.insertCell(5);
|
||||
const commentInput = document.createElement('input');
|
||||
commentInput.type = 'text';
|
||||
commentInput.value = image.comment || '';
|
||||
commentInput.dataset.id = image.id;
|
||||
commentInput.className = 'comment-input';
|
||||
commentInput.style.width = '100%';
|
||||
commentInput.addEventListener('change', function () {
|
||||
updateComment(image.id, this.value);
|
||||
});
|
||||
commentCell.appendChild(commentInput);
|
||||
|
||||
row.insertCell(6).innerHTML = `<button onclick="deleteImage(${image.id})">Delete</button>`;
|
||||
});
|
||||
}
|
||||
|
||||
// 添加更新comment的函数
|
||||
async function updateComment(id, comment) {
|
||||
try {
|
||||
const response = await fetch('/api/images/comment', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ id: id, comment: comment })
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ error: response.statusText }));
|
||||
throw new Error(errorData.error || `HTTP error! status: ${response.status}`);
|
||||
}
|
||||
document.getElementById('status').textContent = `Comment for image ID ${id} updated.`;
|
||||
} catch (error) {
|
||||
console.error('Error updating comment:', error);
|
||||
document.getElementById('status').textContent = 'Error updating comment: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 删除图片
|
||||
async function deleteImage(id) {
|
||||
if (!confirm(`Are you sure you want to delete image ID ${id}?`)) return;
|
||||
@@ -165,7 +244,7 @@
|
||||
document.getElementById('refreshBtn').addEventListener('click', loadImages);
|
||||
|
||||
// --- 修改:使用 fetch API 发起导出请求 ---
|
||||
document.getElementById('exportBtn').addEventListener('click', async function() {
|
||||
document.getElementById('exportBtn').addEventListener('click', async function () {
|
||||
const selectedIds = getSelectedIds();
|
||||
if (selectedIds.length === 0) {
|
||||
alert('Please select at least one image to export.');
|
||||
@@ -205,7 +284,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('deleteSelectedBtn').addEventListener('click', async function() {
|
||||
document.getElementById('deleteSelectedBtn').addEventListener('click', async function () {
|
||||
const selectedIds = getSelectedIds();
|
||||
if (selectedIds.length === 0) {
|
||||
alert('Please select at least one image to delete.');
|
||||
@@ -236,7 +315,7 @@
|
||||
});
|
||||
|
||||
// 全选复选框事件监听
|
||||
document.getElementById('selectAllCheckbox').addEventListener('change', function() {
|
||||
document.getElementById('selectAllCheckbox').addEventListener('change', function () {
|
||||
const isChecked = this.checked;
|
||||
const checkboxes = document.querySelectorAll('.selectCheckbox');
|
||||
checkboxes.forEach(checkbox => {
|
||||
@@ -246,7 +325,7 @@
|
||||
});
|
||||
|
||||
// 监听单个复选框变化以更新全选框和按钮状态
|
||||
document.getElementById('imagesTable').addEventListener('change', function(e) {
|
||||
document.getElementById('imagesTable').addEventListener('change', function (e) {
|
||||
if (e.target.classList.contains('selectCheckbox')) {
|
||||
updateSelectAllCheckbox();
|
||||
}
|
||||
@@ -257,4 +336,5 @@
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user