Spaces:
Sleeping
Sleeping
Upload 10 files
Browse files- public/index.html +180 -19
public/index.html
CHANGED
|
@@ -416,7 +416,7 @@
|
|
| 416 |
visibility: visible;
|
| 417 |
}
|
| 418 |
|
| 419 |
-
/* Mobile Generate Button */
|
| 420 |
.mobile-generate-btn {
|
| 421 |
position: fixed;
|
| 422 |
left: 20px;
|
|
@@ -430,22 +430,29 @@
|
|
| 430 |
width: 60px;
|
| 431 |
height: 60px;
|
| 432 |
font-size: 24px;
|
| 433 |
-
cursor:
|
| 434 |
box-shadow: var(--shadow-lg);
|
| 435 |
transition: all 0.3s ease;
|
| 436 |
display: none;
|
|
|
|
|
|
|
| 437 |
}
|
| 438 |
|
| 439 |
.mobile-generate-btn:hover {
|
| 440 |
-
transform: translateY(-50%) scale(1.1);
|
| 441 |
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2), 0 10px 10px -5px rgba(0, 0, 0, 0.1);
|
| 442 |
}
|
| 443 |
|
| 444 |
.mobile-generate-btn:active {
|
| 445 |
-
transform:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
}
|
| 447 |
|
| 448 |
-
/* Card Meta Expandable */
|
| 449 |
.card .meta {
|
| 450 |
padding: 16px;
|
| 451 |
border-top: 1px solid var(--border);
|
|
@@ -462,19 +469,24 @@
|
|
| 462 |
}
|
| 463 |
|
| 464 |
.card .meta-toggle {
|
| 465 |
-
background:
|
| 466 |
-
border:
|
| 467 |
color: var(--accent);
|
| 468 |
cursor: pointer;
|
| 469 |
font-size: 12px;
|
| 470 |
-
padding:
|
| 471 |
-
border-radius:
|
| 472 |
transition: all 0.2s ease;
|
| 473 |
-
min-height:
|
|
|
|
|
|
|
| 474 |
}
|
| 475 |
|
| 476 |
-
.card .meta-toggle:hover
|
| 477 |
-
|
|
|
|
|
|
|
|
|
|
| 478 |
transform: none;
|
| 479 |
box-shadow: none;
|
| 480 |
}
|
|
@@ -486,7 +498,7 @@
|
|
| 486 |
}
|
| 487 |
|
| 488 |
.card .meta-content.expanded {
|
| 489 |
-
max-height:
|
| 490 |
}
|
| 491 |
|
| 492 |
/* Mobile Responsive Styles */
|
|
@@ -573,6 +585,23 @@
|
|
| 573 |
padding: 14px 16px;
|
| 574 |
font-size: 16px;
|
| 575 |
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
}
|
| 577 |
}
|
| 578 |
|
|
@@ -878,9 +907,24 @@
|
|
| 878 |
metaHeader.className = 'meta-header';
|
| 879 |
metaHeader.innerHTML = `
|
| 880 |
<div style="font-weight: 600;">${params.model}</div>
|
| 881 |
-
<button class="meta-toggle" onclick="toggleCardMeta(this)">详情</button>
|
| 882 |
`;
|
| 883 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 884 |
const metaContent = document.createElement('div');
|
| 885 |
metaContent.className = 'meta-content';
|
| 886 |
metaContent.innerHTML = `
|
|
@@ -898,7 +942,7 @@
|
|
| 898 |
wrap.appendChild(meta);
|
| 899 |
}
|
| 900 |
|
| 901 |
-
// 切换卡片详情显示
|
| 902 |
function toggleCardMeta(button) {
|
| 903 |
const metaContent = button.parentElement.nextElementSibling;
|
| 904 |
const isExpanded = metaContent.classList.contains('expanded');
|
|
@@ -912,6 +956,124 @@
|
|
| 912 |
}
|
| 913 |
}
|
| 914 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 915 |
// 移动端优化的下载函数
|
| 916 |
function downloadImageMobile(filename, dataUrl) {
|
| 917 |
// 检测是否为移动端
|
|
@@ -1185,10 +1347,9 @@
|
|
| 1185 |
closeSidebar();
|
| 1186 |
});
|
| 1187 |
|
| 1188 |
-
//
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
});
|
| 1192 |
|
| 1193 |
// 通用事件绑定
|
| 1194 |
qs('#downloadAll').addEventListener('click', () => {
|
|
|
|
| 416 |
visibility: visible;
|
| 417 |
}
|
| 418 |
|
| 419 |
+
/* Mobile Generate Button - Draggable */
|
| 420 |
.mobile-generate-btn {
|
| 421 |
position: fixed;
|
| 422 |
left: 20px;
|
|
|
|
| 430 |
width: 60px;
|
| 431 |
height: 60px;
|
| 432 |
font-size: 24px;
|
| 433 |
+
cursor: move;
|
| 434 |
box-shadow: var(--shadow-lg);
|
| 435 |
transition: all 0.3s ease;
|
| 436 |
display: none;
|
| 437 |
+
touch-action: none;
|
| 438 |
+
user-select: none;
|
| 439 |
}
|
| 440 |
|
| 441 |
.mobile-generate-btn:hover {
|
|
|
|
| 442 |
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2), 0 10px 10px -5px rgba(0, 0, 0, 0.1);
|
| 443 |
}
|
| 444 |
|
| 445 |
.mobile-generate-btn:active {
|
| 446 |
+
transform: scale(0.95);
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.mobile-generate-btn.dragging {
|
| 450 |
+
transition: none;
|
| 451 |
+
z-index: 1000;
|
| 452 |
+
transform: scale(1.1);
|
| 453 |
}
|
| 454 |
|
| 455 |
+
/* Card Meta Expandable - Fixed for mobile */
|
| 456 |
.card .meta {
|
| 457 |
padding: 16px;
|
| 458 |
border-top: 1px solid var(--border);
|
|
|
|
| 469 |
}
|
| 470 |
|
| 471 |
.card .meta-toggle {
|
| 472 |
+
background: var(--bg);
|
| 473 |
+
border: 1px solid var(--border);
|
| 474 |
color: var(--accent);
|
| 475 |
cursor: pointer;
|
| 476 |
font-size: 12px;
|
| 477 |
+
padding: 6px 12px;
|
| 478 |
+
border-radius: 6px;
|
| 479 |
transition: all 0.2s ease;
|
| 480 |
+
min-height: 32px;
|
| 481 |
+
font-weight: 500;
|
| 482 |
+
touch-action: manipulation;
|
| 483 |
}
|
| 484 |
|
| 485 |
+
.card .meta-toggle:hover,
|
| 486 |
+
.card .meta-toggle:active {
|
| 487 |
+
background: var(--accent);
|
| 488 |
+
color: white;
|
| 489 |
+
border-color: var(--accent);
|
| 490 |
transform: none;
|
| 491 |
box-shadow: none;
|
| 492 |
}
|
|
|
|
| 498 |
}
|
| 499 |
|
| 500 |
.card .meta-content.expanded {
|
| 501 |
+
max-height: 300px;
|
| 502 |
}
|
| 503 |
|
| 504 |
/* Mobile Responsive Styles */
|
|
|
|
| 585 |
padding: 14px 16px;
|
| 586 |
font-size: 16px;
|
| 587 |
border-radius: 8px;
|
| 588 |
+
-webkit-appearance: none;
|
| 589 |
+
-moz-appearance: none;
|
| 590 |
+
appearance: none;
|
| 591 |
+
touch-action: manipulation;
|
| 592 |
+
}
|
| 593 |
+
|
| 594 |
+
/* 修复iOS输入框问题 */
|
| 595 |
+
.group input:focus, .group select:focus, .group textarea:focus {
|
| 596 |
+
transform: none;
|
| 597 |
+
-webkit-user-select: text;
|
| 598 |
+
user-select: text;
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
.group textarea {
|
| 602 |
+
-webkit-user-select: text;
|
| 603 |
+
user-select: text;
|
| 604 |
+
resize: vertical;
|
| 605 |
}
|
| 606 |
}
|
| 607 |
|
|
|
|
| 907 |
metaHeader.className = 'meta-header';
|
| 908 |
metaHeader.innerHTML = `
|
| 909 |
<div style="font-weight: 600;">${params.model}</div>
|
|
|
|
| 910 |
`;
|
| 911 |
|
| 912 |
+
const toggleBtn = document.createElement('button');
|
| 913 |
+
toggleBtn.className = 'meta-toggle';
|
| 914 |
+
toggleBtn.textContent = '详情';
|
| 915 |
+
toggleBtn.addEventListener('click', function(e) {
|
| 916 |
+
e.preventDefault();
|
| 917 |
+
e.stopPropagation();
|
| 918 |
+
toggleCardMeta(this);
|
| 919 |
+
});
|
| 920 |
+
toggleBtn.addEventListener('touchend', function(e) {
|
| 921 |
+
e.preventDefault();
|
| 922 |
+
e.stopPropagation();
|
| 923 |
+
toggleCardMeta(this);
|
| 924 |
+
});
|
| 925 |
+
|
| 926 |
+
metaHeader.appendChild(toggleBtn);
|
| 927 |
+
|
| 928 |
const metaContent = document.createElement('div');
|
| 929 |
metaContent.className = 'meta-content';
|
| 930 |
metaContent.innerHTML = `
|
|
|
|
| 942 |
wrap.appendChild(meta);
|
| 943 |
}
|
| 944 |
|
| 945 |
+
// 切换卡片详情显示 - 修复移动端点击问题
|
| 946 |
function toggleCardMeta(button) {
|
| 947 |
const metaContent = button.parentElement.nextElementSibling;
|
| 948 |
const isExpanded = metaContent.classList.contains('expanded');
|
|
|
|
| 956 |
}
|
| 957 |
}
|
| 958 |
|
| 959 |
+
// 拖拽功能
|
| 960 |
+
let dragState = {
|
| 961 |
+
isDragging: false,
|
| 962 |
+
startX: 0,
|
| 963 |
+
startY: 0,
|
| 964 |
+
currentX: 0,
|
| 965 |
+
currentY: 0,
|
| 966 |
+
initialX: 20,
|
| 967 |
+
initialY: 0
|
| 968 |
+
};
|
| 969 |
+
|
| 970 |
+
function initDragButton() {
|
| 971 |
+
const btn = qs('#mobileGenerateBtn');
|
| 972 |
+
if (!btn) return;
|
| 973 |
+
|
| 974 |
+
// 鼠标事件
|
| 975 |
+
btn.addEventListener('mousedown', startDrag);
|
| 976 |
+
document.addEventListener('mousemove', drag);
|
| 977 |
+
document.addEventListener('mouseup', endDrag);
|
| 978 |
+
|
| 979 |
+
// 触摸事件
|
| 980 |
+
btn.addEventListener('touchstart', startDrag, { passive: false });
|
| 981 |
+
document.addEventListener('touchmove', drag, { passive: false });
|
| 982 |
+
document.addEventListener('touchend', endDrag);
|
| 983 |
+
}
|
| 984 |
+
|
| 985 |
+
function startDrag(e) {
|
| 986 |
+
const btn = qs('#mobileGenerateBtn');
|
| 987 |
+
if (!btn) return;
|
| 988 |
+
|
| 989 |
+
dragState.isDragging = true;
|
| 990 |
+
btn.classList.add('dragging');
|
| 991 |
+
|
| 992 |
+
if (e.type === 'touchstart') {
|
| 993 |
+
dragState.startX = e.touches[0].clientX;
|
| 994 |
+
dragState.startY = e.touches[0].clientY;
|
| 995 |
+
} else {
|
| 996 |
+
dragState.startX = e.clientX;
|
| 997 |
+
dragState.startY = e.clientY;
|
| 998 |
+
}
|
| 999 |
+
|
| 1000 |
+
const rect = btn.getBoundingClientRect();
|
| 1001 |
+
dragState.initialX = rect.left;
|
| 1002 |
+
dragState.initialY = rect.top;
|
| 1003 |
+
|
| 1004 |
+
e.preventDefault();
|
| 1005 |
+
}
|
| 1006 |
+
|
| 1007 |
+
function drag(e) {
|
| 1008 |
+
if (!dragState.isDragging) return;
|
| 1009 |
+
|
| 1010 |
+
e.preventDefault();
|
| 1011 |
+
|
| 1012 |
+
let clientX, clientY;
|
| 1013 |
+
if (e.type === 'touchmove') {
|
| 1014 |
+
clientX = e.touches[0].clientX;
|
| 1015 |
+
clientY = e.touches[0].clientY;
|
| 1016 |
+
} else {
|
| 1017 |
+
clientX = e.clientX;
|
| 1018 |
+
clientY = e.clientY;
|
| 1019 |
+
}
|
| 1020 |
+
|
| 1021 |
+
dragState.currentX = dragState.initialX + (clientX - dragState.startX);
|
| 1022 |
+
dragState.currentY = dragState.initialY + (clientY - dragState.startY);
|
| 1023 |
+
|
| 1024 |
+
// 限制在屏幕范围内
|
| 1025 |
+
const btn = qs('#mobileGenerateBtn');
|
| 1026 |
+
const maxX = window.innerWidth - 60;
|
| 1027 |
+
const maxY = window.innerHeight - 60;
|
| 1028 |
+
|
| 1029 |
+
dragState.currentX = Math.max(0, Math.min(maxX, dragState.currentX));
|
| 1030 |
+
dragState.currentY = Math.max(0, Math.min(maxY, dragState.currentY));
|
| 1031 |
+
|
| 1032 |
+
btn.style.left = dragState.currentX + 'px';
|
| 1033 |
+
btn.style.top = dragState.currentY + 'px';
|
| 1034 |
+
btn.style.transform = 'none';
|
| 1035 |
+
}
|
| 1036 |
+
|
| 1037 |
+
function endDrag(e) {
|
| 1038 |
+
if (!dragState.isDragging) return;
|
| 1039 |
+
|
| 1040 |
+
const btn = qs('#mobileGenerateBtn');
|
| 1041 |
+
if (!btn) return;
|
| 1042 |
+
|
| 1043 |
+
dragState.isDragging = false;
|
| 1044 |
+
btn.classList.remove('dragging');
|
| 1045 |
+
|
| 1046 |
+
// 如果移动距离很小,视为点击
|
| 1047 |
+
const moveDistance = Math.sqrt(
|
| 1048 |
+
Math.pow(dragState.currentX - dragState.initialX, 2) +
|
| 1049 |
+
Math.pow(dragState.currentY - dragState.initialY, 2)
|
| 1050 |
+
);
|
| 1051 |
+
|
| 1052 |
+
if (moveDistance < 10) {
|
| 1053 |
+
// 触发生成
|
| 1054 |
+
generate();
|
| 1055 |
+
}
|
| 1056 |
+
|
| 1057 |
+
// 保存位置
|
| 1058 |
+
ls.set('generateBtnPosition', {
|
| 1059 |
+
x: dragState.currentX,
|
| 1060 |
+
y: dragState.currentY
|
| 1061 |
+
});
|
| 1062 |
+
}
|
| 1063 |
+
|
| 1064 |
+
// 恢复按钮位置
|
| 1065 |
+
function restoreButtonPosition() {
|
| 1066 |
+
const btn = qs('#mobileGenerateBtn');
|
| 1067 |
+
if (!btn) return;
|
| 1068 |
+
|
| 1069 |
+
const savedPos = ls.get('generateBtnPosition', null);
|
| 1070 |
+
if (savedPos) {
|
| 1071 |
+
btn.style.left = savedPos.x + 'px';
|
| 1072 |
+
btn.style.top = savedPos.y + 'px';
|
| 1073 |
+
btn.style.transform = 'none';
|
| 1074 |
+
}
|
| 1075 |
+
}
|
| 1076 |
+
|
| 1077 |
// 移动端优化的下载函数
|
| 1078 |
function downloadImageMobile(filename, dataUrl) {
|
| 1079 |
// 检测是否为移动端
|
|
|
|
| 1347 |
closeSidebar();
|
| 1348 |
});
|
| 1349 |
|
| 1350 |
+
// 初始化拖拽功能
|
| 1351 |
+
initDragButton();
|
| 1352 |
+
restoreButtonPosition();
|
|
|
|
| 1353 |
|
| 1354 |
// 通用事件绑定
|
| 1355 |
qs('#downloadAll').addEventListener('click', () => {
|