在查看图片时可以进行缩放

This commit is contained in:
DSQ
2025-11-22 11:59:41 +08:00
parent d755f4710f
commit faae7032f1

View File

@@ -3,226 +3,47 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>数据管理</title> <title>数据管理</title>
<style> <style>
body {margin: 0;font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;background: #fafafa;} body{margin:0;font-family:sans-serif;background:#fafafa}
/* 导航栏样式 */ .sidebar{position:fixed;top:0;left:0;width:180px;height:100vh;background:#1e1e2e;color:white;padding:20px;box-shadow:2px 0 5px rgba(0,0,0,.1);z-index:1000;display:flex;flex-direction:column;align-items:center}
.sidebar {position: fixed;top: 0;left: 0;width: 180px;height: 100vh;background: #1e1e2e;color: white;padding: 20px;box-shadow: 2px 0 5px rgba(0,0,0,0.1);z-index: 1000;display: flex; .user-id{text-align:center;margin-bottom:0}
flex-direction: column;align-items: center;} .sidebar h3{margin:0;font-size:18px;color:#add8e6;text-align:center;margin-bottom:20px}
.user-id {text-align: center;margin-bottom: 0px;} .navigation-links{width:100%;margin-top:60px}
.sidebar h3 {margin-top: 0;font-size: 18px;color: #add8e6;text-align: center; margin-bottom: 20px;} .sidebar a,.sidebar button{display:block;color:#8be9fd;text-decoration:none;margin:10px 0;font-size:16px;padding:15px;border-radius:4px;background:transparent;border:none;cursor:pointer;width:calc(100% - 40px);text-align:left;transition:.2s}
.navigation-links {width: 100%;margin-top: 60px;} .sidebar a:hover,.sidebar button:hover{color:#ff79c6;background-color:rgba(139,233,253,.2)}
.sidebar a, .main-content{margin-left:200px;padding:20px;color:#333}
.sidebar button {display: block;color: #8be9fd;text-decoration: none;margin: 10px 0;font-size: 16px;padding: 15px;border-radius: 4px;background: transparent; .container{max-width:1200px;margin:0 auto;background:#fff;border-radius:10px;box-shadow:0 6px 18px rgba(0,0,0,.06);padding:20px}
border: none;cursor: pointer; width: calc(100% - 40px);text-align: left;transition: all 0.2s ease;} table{width:100%;border-collapse:collapse;margin-top:20px}
.sidebar a:hover, th,td{border-bottom:1px solid #eee;padding:12px 8px;text-align:left;vertical-align:top}
.sidebar button:hover {color: #ff79c6;background-color: rgba(139, 233, 253, 0.2);} th{background:#f8f9fa;font-weight:600}
/* 主内容区 */ img{max-width:120px;border:1px solid #eee;border-radius:6px;cursor:pointer}
.main-content { .btn{padding:6px 10px;border:none;border-radius:6px;cursor:pointer;font-size:14px;margin:2px}
margin-left: 200px; .btn-primary{background:#1677ff;color:#fff}
padding: 20px; .btn-danger{background:#ff4d4f;color:#fff}
color: #333; .btn-secondary{background:#f0f0f0;color:#333}
} .muted{color:#666;font-size:12px}
.modal{position:fixed;inset:0;display:none;background:rgba(0,0,0,.4);align-items:center;justify-content:center;z-index:1000}
/* 原有样式保持不变 */ .modal .dialog{width:720px;max-width:92vw;background:#fff;border-radius:10px;padding:20px;max-height:80vh;overflow-y:auto}
.container { textarea{width:100%;min-height:240px;font-family:monospace;font-size:14px;padding:10px;border:1px solid #ddd;border-radius:4px;resize:vertical}
max-width: 1200px; #kvForm{border:1px solid #eee;border-radius:6px;padding:8px;max-height:300px;overflow:auto}
margin: 0 auto; .search-container{background:#f8f9fa;padding:15px;border-radius:8px;margin-bottom:20px}
background: #fff; .search-controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:10px}
border-radius: 10px; .search-input{flex:1;min-width:200px;padding:8px 12px;border:1px solid #ddd;border-radius:4px;font-size:14px}
box-shadow: 0 6px 18px rgba(0,0,0,0.06); .search-result{margin-top:10px;padding:10px;background:#e8f4ff;border-radius:4px;font-size:14px}
padding: 20px; .search-result.empty{background:#fff8e8}
} .search-result.error{background:#ffe8e8}
table { .loading{display:inline-block;width:20px;height:20px;border:3px solid #f3f3f3;border-top:3px solid #1677ff;border-radius:50%;animation:spin 1s linear infinite}
width: 100%; @keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
border-collapse: collapse; @media(max-width:768px){.search-controls{flex-direction:column;align-items:stretch}.search-input{min-width:auto}.btn{width:100%;margin:2px 0}}
margin-top: 20px; .image-modal{display:none;position:fixed;z-index:2000;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.9);overflow:hidden}
} .image-modal-content{margin:auto;display:block;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-width:80%;max-height:80%;object-fit:contain;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.5);cursor:grab;transition:transform .3s ease}
th, td { .image-modal-content.dragging{cursor:grabbing}
border-bottom: 1px solid #eee; .image-modal-close{position:absolute;top:15px;right:35px;color:#f1f1f1;font-size:40px;font-weight:bold;transition:.3s;cursor:pointer;z-index:2001}
padding: 12px 8px; .image-modal-close:hover{color:#bbb}
text-align: left; .zoom-controls{position:absolute;bottom:30px;left:50%;transform:translateX(-50%);display:flex;gap:10px;z-index:2001}
vertical-align: top; .zoom-btn{background:rgba(255,255,255,.7);border:none;border-radius:50%;width:40px;height:40px;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px rgba(0,0,0,.3);transition:background .3s}
} .zoom-btn:hover{background:rgba(255,255,255,.9)}
th { .zoom-info{position:absolute;top:15px;left:15px;color:#f1f1f1;font-size:14px;z-index:2001;background:rgba(0,0,0,.5);padding:5px 10px;border-radius:4px}
background-color: #f8f9fa;
font-weight: 600;
}
img {
max-width: 120px;
border: 1px solid #eee;
border-radius: 6px;
cursor: pointer; /* 添加指针样式 */
}
.btn {
padding: 6px 10px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
margin: 2px;
}
.btn-primary {
background: #1677ff;
color: #fff;
}
.btn-danger {
background: #ff4d4f;
color: #fff;
}
.btn-secondary {
background: #f0f0f0;
color: #333;
}
.muted {
color: #666;
font-size: 12px;
}
.modal {
position: fixed;
inset: 0;
display: none;
background: rgba(0,0,0,0.4);
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal .dialog {
width: 720px;
max-width: 92vw;
background: #fff;
border-radius: 10px;
padding: 20px;
max-height: 80vh;
overflow-y: auto;
}
textarea {
width: 100%;
min-height: 240px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 14px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
resize: vertical;
}
#kvForm {
border: 1px solid #eee;
border-radius: 6px;
padding: 8px;
max-height: 300px;
overflow: auto;
}
/* 搜索区域样式 */
.search-container {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}
.search-controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
margin-bottom: 10px;
}
.search-input {
flex: 1;
min-width: 200px;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.search-result {
margin-top: 10px;
padding: 10px;
background: #e8f4ff;
border-radius: 4px;
font-size: 14px;
}
.search-result.empty {
background: #fff8e8;
}
.search-result.error {
background: #ffe8e8;
}
/* 加载动画 */
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #1677ff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 响应式调整 */
@media (max-width: 768px) {
.search-controls {
flex-direction: column;
align-items: stretch;
}
.search-input {
min-width: auto;
}
.btn {
width: 100%;
margin: 2px 0;
}
}
/* 图片放大模态框 */
.image-modal {
display: none;
position: fixed;
z-index: 2000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.9);
overflow: auto;
}
.image-modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 800px;
max-height: 80%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: contain; /* 保持图片比例,完整显示 */
border-radius: 8px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.image-modal-close {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
cursor: pointer;
z-index: 2001;
}
.image-modal-close:hover {
color: #bbb;
}
</style> </style>
</head> </head>
<body> <body>
@@ -302,7 +123,13 @@
<!-- 图片放大模态框 --> <!-- 图片放大模态框 -->
<div id="imageModal" class="image-modal"> <div id="imageModal" class="image-modal">
<span class="image-modal-close">&times;</span> <span class="image-modal-close">&times;</span>
<div class="zoom-info">缩放: <span id="zoomValue">100%</span></div>
<img class="image-modal-content" id="expandedImage"> <img class="image-modal-content" id="expandedImage">
<div class="zoom-controls">
<button class="zoom-btn" id="zoomOutBtn">-</button>
<button class="zoom-btn" id="resetZoomBtn">1:1</button>
<button class="zoom-btn" id="zoomInBtn">+</button>
</div>
</div> </div>
<script> <script>
@@ -330,6 +157,10 @@ const syncFromTextBtn = document.getElementById('syncFromTextBtn');
const imageModal = document.getElementById('imageModal'); const imageModal = document.getElementById('imageModal');
const expandedImage = document.getElementById('expandedImage'); const expandedImage = document.getElementById('expandedImage');
const imageModalClose = document.querySelector('.image-modal-close'); const imageModalClose = document.querySelector('.image-modal-close');
const zoomInBtn = document.getElementById('zoomInBtn');
const zoomOutBtn = document.getElementById('zoomOutBtn');
const resetZoomBtn = document.getElementById('resetZoomBtn');
const zoomValue = document.getElementById('zoomValue');
// 全局变量 // 全局变量
let currentId = ''; let currentId = '';
@@ -337,6 +168,16 @@ let currentWriter = '';
let currentImage = ''; let currentImage = '';
let allDataCache = []; // 缓存所有数据,避免重复请求 let allDataCache = []; // 缓存所有数据,避免重复请求
// 图片缩放相关变量
let currentScale = 1;
let currentX = 0;
let currentY = 0;
let isDragging = false;
let dragStartX = 0;
let dragStartY = 0;
let imgStartX = 0;
let imgStartY = 0;
// 搜索功能 // 搜索功能
async function performSearch(type) { async function performSearch(type) {
const query = searchQueryInput.value.trim(); const query = searchQueryInput.value.trim();
@@ -727,6 +568,30 @@ document.getElementById('logoutBtn').addEventListener('click', async () => {
} }
}); });
// 图片缩放功能
function updateZoom() {
expandedImage.style.transform = `translate(-50%, -50%) scale(${currentScale}) translate(${currentX}px, ${currentY}px)`;
zoomValue.textContent = `${Math.round(currentScale * 100)}%`;
}
function resetZoom() {
currentScale = 1;
currentX = 0;
currentY = 0;
updateZoom();
}
function zoomIn() {
currentScale *= 1.2;
updateZoom();
}
function zoomOut() {
currentScale /= 1.2;
if (currentScale < 0.1) currentScale = 0.1; // 最小缩放限制
updateZoom();
}
// 图片放大功能 // 图片放大功能
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// 为所有图片添加点击事件监听器 // 为所有图片添加点击事件监听器
@@ -735,6 +600,9 @@ document.addEventListener('DOMContentLoaded', function() {
const imgSrc = e.target.src; const imgSrc = e.target.src;
expandedImage.src = imgSrc; expandedImage.src = imgSrc;
imageModal.style.display = 'block'; imageModal.style.display = 'block';
// 重置缩放状态
resetZoom();
} }
}); });
@@ -749,6 +617,91 @@ document.addEventListener('DOMContentLoaded', function() {
imageModal.style.display = 'none'; imageModal.style.display = 'none';
} }
} }
// 缩放按钮事件
zoomInBtn.addEventListener('click', zoomIn);
zoomOutBtn.addEventListener('click', zoomOut);
resetZoomBtn.addEventListener('click', resetZoom);
// 鼠标滚轮缩放
expandedImage.addEventListener('wheel', function(e) {
e.preventDefault();
if (e.deltaY < 0) {
zoomIn();
} else {
zoomOut();
}
});
// 拖拽功能
expandedImage.addEventListener('mousedown', function(e) {
isDragging = true;
dragStartX = e.clientX;
dragStartY = e.clientY;
imgStartX = currentX;
imgStartY = currentY;
expandedImage.classList.add('dragging');
});
document.addEventListener('mousemove', function(e) {
if (isDragging) {
const deltaX = e.clientX - dragStartX;
const deltaY = e.clientY - dragStartY;
currentX = imgStartX + deltaX / currentScale;
currentY = imgStartY + deltaY / currentScale;
updateZoom();
}
});
document.addEventListener('mouseup', function() {
isDragging = false;
expandedImage.classList.remove('dragging');
});
// 触摸事件支持(移动端)
expandedImage.addEventListener('touchstart', function(e) {
if (e.touches.length === 1) {
isDragging = true;
dragStartX = e.touches[0].clientX;
dragStartY = e.touches[0].clientY;
imgStartX = currentX;
imgStartY = currentY;
} else if (e.touches.length === 2) {
// 双指缩放
initialDistance = getDistance(e.touches[0], e.touches[1]);
initialScale = currentScale;
}
});
document.addEventListener('touchmove', function(e) {
e.preventDefault();
if (isDragging && e.touches.length === 1) {
const deltaX = e.touches[0].clientX - dragStartX;
const deltaY = e.touches[0].clientY - dragStartY;
currentX = imgStartX + deltaX / currentScale;
currentY = imgStartY + deltaY / currentScale;
updateZoom();
} else if (e.touches.length === 2) {
// 双指缩放
const currentDistance = getDistance(e.touches[0], e.touches[1]);
const scale = (currentDistance / initialDistance) * initialScale;
currentScale = Math.max(0.1, Math.min(scale, 10)); // 限制缩放范围
updateZoom();
}
});
document.addEventListener('touchend', function() {
isDragging = false;
});
// 计算两点间距离
function getDistance(touch1, touch2) {
return Math.sqrt(
Math.pow(touch2.clientX - touch1.clientX, 2) +
Math.pow(touch2.clientY - touch1.clientY, 2)
);
}
}); });
</script> </script>
</body> </body>