优化展示效果
This commit is contained in:
parent
0f448ec33e
commit
9c274b5b41
@ -21,10 +21,12 @@ import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@ -153,6 +155,15 @@ public class GalleryController {
|
||||
File currentFolder = new File(rootPath, path);
|
||||
String rootAbsolutePath = new File(rootPath).getAbsolutePath();
|
||||
|
||||
Set<String> cartItemIds = Collections.emptySet();
|
||||
if (StpUtil.isLogin() && ((String) StpUtil.getLoginId()).startsWith("user-")) {
|
||||
String loginId = (String) StpUtil.getLoginId();
|
||||
String authCode = loginId.substring(5);
|
||||
cartItemIds = jdbcTemplate.queryForList("SELECT item_id FROM cart_items WHERE auth_code = ?", String.class, authCode)
|
||||
.stream()
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
List<Map<String, String>> folders = new ArrayList<>();
|
||||
Map<String, Map<String, File>> groupedFiles = new HashMap<>();
|
||||
|
||||
@ -176,6 +187,7 @@ public class GalleryController {
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> finalCartItemIds = cartItemIds;
|
||||
List<ImageGroup> imageGroups = groupedFiles.entrySet().stream()
|
||||
.map(entry -> {
|
||||
String uniqueId = entry.getKey();
|
||||
@ -183,6 +195,7 @@ public class GalleryController {
|
||||
Map<String, File> typeMap = entry.getValue();
|
||||
|
||||
ImageGroup group = new ImageGroup(uniqueId, displayName);
|
||||
group.setInCart(finalCartItemIds.contains(uniqueId));
|
||||
|
||||
java.util.function.Function<File, String> getUrl = (file) -> {
|
||||
if (file == null) return null;
|
||||
|
||||
@ -8,6 +8,7 @@ public class ImageGroup {
|
||||
private String effectImageUrl;
|
||||
private String templateThumbnailUrl;
|
||||
private String templateImageUrl;
|
||||
private boolean inCart;
|
||||
|
||||
public ImageGroup(String id, String name) {
|
||||
this.id = id;
|
||||
@ -63,4 +64,12 @@ public class ImageGroup {
|
||||
public void setTemplateImageUrl(String templateImageUrl) {
|
||||
this.templateImageUrl = templateImageUrl;
|
||||
}
|
||||
|
||||
public boolean isInCart() {
|
||||
return inCart;
|
||||
}
|
||||
|
||||
public void setInCart(boolean inCart) {
|
||||
this.inCart = inCart;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,24 +4,66 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>管理后台</title>
|
||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
||||
<style>
|
||||
body { font-family: sans-serif; background-color: #f4f6f8; margin: 0; display: flex; height: 100vh; }
|
||||
.sidebar { width: 280px; background: #fff; box-shadow: 2px 0 5px rgba(0,0,0,0.1); padding: 20px; overflow-y: auto; }
|
||||
.main-content { flex-grow: 1; padding: 20px; overflow-y: auto; }
|
||||
:root {
|
||||
--primary-color: #007bff; /* Blue shade */
|
||||
--bg-color: #e9f5ff; /* Light blue background */
|
||||
--glass-bg: rgba(255, 255, 255, 0.6);
|
||||
--card-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#particles-js {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 280px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex-grow: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.code-list-item { padding: 12px; border-bottom: 1px solid #eee; cursor: pointer; border-radius: 6px; }
|
||||
.code-list-item:hover, .code-list-item.active { background-color: #e9f5ff; }
|
||||
.code-list-item:hover, .code-list-item.active { background-color: #d1e7fd; }
|
||||
.code-list-item strong { font-size: 14px; color: #333; }
|
||||
.code-list-item span { font-size: 12px; color: #777; display: block; margin-top: 4px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; margin-top: 20px; }
|
||||
.grid-item { background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 16px rgba(0,0,0,0.05); }
|
||||
.grid-item { background: #fff; border-radius: 10px; overflow: hidden; box-shadow: var(--card-shadow); }
|
||||
.grid-item img { width: 100%; height: auto; display: block; }
|
||||
.grid-item-info { padding: 10px; font-size: 12px; text-align: center; }
|
||||
#download-btn { background: #28a745; color: white; border: none; padding: 12px 20px; border-radius: 8px; cursor: pointer; font-size: 16px; display: none; margin-bottom: 20px; }
|
||||
#download-btn { background: var(--primary-color); color: white; border: none; padding: 12px 20px; border-radius: 8px; cursor: pointer; font-size: 16px; display: none; margin-bottom: 20px; }
|
||||
#download-btn:hover { background: #0056b3; }
|
||||
#download-btn:disabled { background: #999; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="particles-js"></div>
|
||||
|
||||
<div class="sidebar" id="sidebar">
|
||||
<h3>授权码列表</h3>
|
||||
<div id="code-list"></div>
|
||||
@ -126,7 +168,27 @@
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', fetchAuthCodes);
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchAuthCodes();
|
||||
|
||||
particlesJS('particles-js', {
|
||||
"particles": {
|
||||
"number": { "value": 80, "density": { "enable": true, "value_area": 800 } },
|
||||
"color": { "value": "#007bff" },
|
||||
"shape": { "type": "circle", "stroke": { "width": 0, "color": "#000000" }, "polygon": { "nb_sides": 5 } },
|
||||
"opacity": { "value": 0.5, "random": false, "anim": { "enable": false, "speed": 1, "opacity_min": 0.1, "sync": false } },
|
||||
"size": { "value": 3, "random": true, "anim": { "enable": false, "speed": 40, "size_min": 0.1, "sync": false } },
|
||||
"line_linked": { "enable": true, "distance": 150, "color": "#007bff", "opacity": 0.4, "width": 1 },
|
||||
"move": { "enable": true, "speed": 6, "direction": "none", "random": false, "straight": false, "out_mode": "out", "bounce": false, "attract": { "enable": false, "rotateX": 600, "rotateY": 1200 } }
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "canvas",
|
||||
"events": { "onhover": { "enable": true, "mode": "repulse" }, "onclick": { "enable": true, "mode": "push" }, "resize": true },
|
||||
"modes": { "grab": { "distance": 400, "line_linked": { "opacity": 1 } }, "bubble": { "distance": 400, "size": 40, "duration": 2, "opacity": 8, "speed": 3 }, "repulse": { "distance": 200, "duration": 0.4 }, "push": { "particles_nb": 4 }, "remove": { "particles_nb": 2 } }
|
||||
},
|
||||
"retina_detect": true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@ -6,13 +6,42 @@
|
||||
<title>我的购物车</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.6/viewer.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.6/viewer.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
||||
<style>
|
||||
body { font-family: sans-serif; background-color: #f0f2f5; margin: 0; }
|
||||
.navbar { background: #fff; padding: 10px 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); display: flex; align-items: center; }
|
||||
.navbar a { text-decoration: none; color: #007bff; font-weight: bold; margin-right: 20px; }
|
||||
.main-content { padding: 20px; max-width: 1600px; margin: auto; }
|
||||
:root {
|
||||
--primary-color: #28a745; /* Green shade */
|
||||
--bg-color: #e8f5e9; /* Light green background */
|
||||
--glass-bg: rgba(255, 255, 255, 0.6);
|
||||
--card-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#particles-js {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 10px 20px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.navbar a { text-decoration: none; color: var(--primary-color); font-weight: bold; margin-right: 20px; }
|
||||
.main-content { position: relative; z-index: 1; padding: 20px; max-width: 1600px; margin: auto; }
|
||||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }
|
||||
.grid-item { position: relative; background: #fff; border-radius: 15px; overflow: hidden; box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07); }
|
||||
.grid-item { position: relative; background: #fff; border-radius: 15px; overflow: hidden; box-shadow: var(--card-shadow); }
|
||||
.grid-item img { width: 100%; height: auto; display: block; cursor: zoom-in; }
|
||||
.image-info { padding: 12px; font-size: 12px; text-align: center; }
|
||||
.loading-status { text-align: center; padding: 40px; color: #999; }
|
||||
@ -41,9 +70,11 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="particles-js"></div>
|
||||
|
||||
<div class="navbar">
|
||||
<a href="/">返回主页</a>
|
||||
<a id="admin-link" href="/admin" style="display: none;">管理后台</a>
|
||||
<a id="admin-link" href="/api/admin" style="display: none;">管理后台</a>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
@ -74,7 +105,6 @@
|
||||
items.forEach(item => {
|
||||
const gridItem = document.createElement('div');
|
||||
gridItem.className = 'grid-item';
|
||||
// **[FIX]** Use a data attribute to reliably store the original ID.
|
||||
gridItem.dataset.itemId = item.id;
|
||||
gridItem.innerHTML = `
|
||||
<button class="delete-btn" data-id="${item.id}" title="从购物车移除">×</button>
|
||||
@ -105,7 +135,6 @@
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// **[FIX]** Use a robust attribute selector to find the correct element.
|
||||
const itemElement = document.querySelector(`.grid-item[data-item-id="${itemId}"]`);
|
||||
if (itemElement) {
|
||||
itemElement.style.transition = 'opacity 0.5s, transform 0.5s';
|
||||
@ -138,7 +167,29 @@
|
||||
});
|
||||
|
||||
async function checkUserRole() { try { const res = await fetch('/api/auth/info'); if (res.ok) { const data = await res.json(); if (data.role === 'admin') { document.getElementById('admin-link').style.display = 'block'; } } } catch (e) { /* Ignore */ } }
|
||||
document.addEventListener('DOMContentLoaded', () => { checkUserRole(); fetchCartItems(); });
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
checkUserRole();
|
||||
fetchCartItems();
|
||||
|
||||
particlesJS('particles-js', {
|
||||
"particles": {
|
||||
"number": { "value": 80, "density": { "enable": true, "value_area": 800 } },
|
||||
"color": { "value": "#28a745" },
|
||||
"shape": { "type": "circle", "stroke": { "width": 0, "color": "#000000" }, "polygon": { "nb_sides": 5 } },
|
||||
"opacity": { "value": 0.5, "random": false, "anim": { "enable": false, "speed": 1, "opacity_min": 0.1, "sync": false } },
|
||||
"size": { "value": 3, "random": true, "anim": { "enable": false, "speed": 40, "size_min": 0.1, "sync": false } },
|
||||
"line_linked": { "enable": true, "distance": 150, "color": "#28a745", "opacity": 0.4, "width": 1 },
|
||||
"move": { "enable": true, "speed": 6, "direction": "none", "random": false, "straight": false, "out_mode": "out", "bounce": false, "attract": { "enable": false, "rotateX": 600, "rotateY": 1200 } }
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "canvas",
|
||||
"events": { "onhover": { "enable": true, "mode": "repulse" }, "onclick": { "enable": true, "mode": "push" }, "resize": true },
|
||||
"modes": { "grab": { "distance": 400, "line_linked": { "opacity": 1 } }, "bubble": { "distance": 400, "size": 40, "duration": 2, "opacity": 8, "speed": 3 }, "repulse": { "distance": 200, "duration": 0.4 }, "push": { "particles_nb": 4 }, "remove": { "particles_nb": 2 } }
|
||||
},
|
||||
"retina_detect": true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@ -7,12 +7,13 @@
|
||||
<title>云端私密相册 - 模板图片挑选</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.6/viewer.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.6/viewer.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #007bff;
|
||||
--bg-color: #f0f2f5;
|
||||
--glass-bg: rgba(255, 255, 255, 0.7);
|
||||
--primary-color: #28a745; /* Green shade */
|
||||
--bg-color: #e8f5e9; /* Light green background */
|
||||
--glass-bg: rgba(255, 255, 255, 0.6);
|
||||
--card-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
|
||||
}
|
||||
|
||||
@ -25,11 +26,20 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#particles-js {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.main-content { position: relative; z-index: 1; padding: 30px 5%; max-width: 1600px; margin: 0 auto; }
|
||||
.breadcrumb { padding: 15px 25px; background: var(--glass-bg); backdrop-filter: blur(10px); margin-bottom: 30px; border-radius: 15px; box-shadow: var(--card-shadow); font-size: 14px; }
|
||||
.breadcrumb { display: flex; justify-content: space-between; align-items: center; padding: 15px 25px; background: var(--glass-bg); backdrop-filter: blur(10px); margin-bottom: 30px; border-radius: 15px; box-shadow: var(--card-shadow); font-size: 14px; }
|
||||
.breadcrumb a { color: var(--primary-color); text-decoration: none; font-weight: 500; }
|
||||
.breadcrumb a:hover { color: #0056b3; }
|
||||
.breadcrumb a:hover { color: #1e7e34; }
|
||||
.breadcrumb span { margin: 0 10px; color: #abb2bf; }
|
||||
.admin-link { background-color: var(--primary-color); color: white !important; padding: 8px 15px; border-radius: 8px; text-decoration: none; font-weight: 500; }
|
||||
.admin-link:hover { background-color: #1e7e34; }
|
||||
.folder-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 20px; margin-bottom: 40px; }
|
||||
.folder-card { background: var(--glass-bg); backdrop-filter: blur(8px); padding: 20px; border-radius: 18px; text-align: center; cursor: pointer; box-shadow: var(--card-shadow); border: 1px solid rgba(255, 255, 255, 0.4); transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); }
|
||||
.folder-card:hover { transform: translateY(-5px); box-shadow: 0 12px 40px rgba(0,0,0,0.1); }
|
||||
@ -40,13 +50,15 @@
|
||||
.grid-item:hover { transform: scale(1.02); z-index: 10; }
|
||||
.grid-item img { width: 100%; height: auto; display: block; cursor: zoom-in; }
|
||||
.image-info { padding: 12px; font-size: 12px; color: #666; text-align: center; background: #fff; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.add-to-cart-btn { position: absolute; bottom: 10px; right: 10px; background: rgba(0, 123, 255, 0.8); color: white; border: none; border-radius: 50px; width: 40px; height: 40px; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); opacity: 0; transform: scale(0.8); transition: opacity 0.2s ease, transform 0.2s ease; z-index: 5; display: flex; align-items: center; justify-content: center; }
|
||||
.add-to-cart-btn { position: absolute; bottom: 10px; right: 10px; background: rgba(40, 167, 69, 0.8); color: white; border: none; border-radius: 50px; width: 40px; height: 40px; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); opacity: 0; transform: scale(0.8); transition: opacity 0.2s ease, transform 0.2s ease; z-index: 5; display: flex; align-items: center; justify-content: center; }
|
||||
.grid-item:hover .add-to-cart-btn { opacity: 1; transform: scale(1); }
|
||||
.add-to-cart-btn:hover { background: #0056b3; transform: scale(1.1); }
|
||||
.add-to-cart-btn:hover { background: #1e7e34; transform: scale(1.1); }
|
||||
.add-to-cart-btn.in-cart { background: #218838; cursor: not-allowed; }
|
||||
.in-cart-badge { position: absolute; top: 10px; left: 10px; background: #28a745; color: white; padding: 5px 8px; border-radius: 5px; font-size: 12px; z-index: 5; }
|
||||
.loading-status { text-align: center; padding: 40px; color: #999; font-size: 14px; }
|
||||
|
||||
.fab-cart { position: fixed; bottom: 40px; right: 40px; width: 60px; height: 60px; background-color: var(--primary-color); color: white; border-radius: 50%; border: none; box-shadow: 0 6px 20px rgba(0, 123, 255, 0.4); display: none; align-items: center; justify-content: center; cursor: pointer; z-index: 1000; transition: all 0.3s; }
|
||||
.fab-cart:hover { transform: scale(1.1); background-color: #0056b3; }
|
||||
.fab-cart { position: fixed; bottom: 40px; right: 40px; width: 60px; height: 60px; background-color: var(--primary-color); color: white; border-radius: 50%; border: none; box-shadow: 0 6px 20px rgba(40, 167, 69, 0.4); display: none; align-items: center; justify-content: center; cursor: pointer; z-index: 1000; transition: all 0.3s; }
|
||||
.fab-cart:hover { transform: scale(1.1); background-color: #1e7e34; }
|
||||
.fab-cart.show { display: flex; }
|
||||
|
||||
#toast-container { position: fixed; top: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; align-items: flex-end; }
|
||||
@ -59,10 +71,14 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="particles-js"></div>
|
||||
<div id="toast-container"></div>
|
||||
|
||||
<div class="main-content">
|
||||
<div class="breadcrumb" id="breadcrumb"></div>
|
||||
<div class="breadcrumb" id="breadcrumb">
|
||||
<div id="breadcrumb-links"></div>
|
||||
<a id="admin-link" class="admin-link" href="/api/admin" style="display: none;">后台管理</a>
|
||||
</div>
|
||||
<div class="folder-container" id="folder-list"></div>
|
||||
<div class="grid" id="image-grid"></div>
|
||||
<div id="loader" class="loading-status">正在探索云端内容...</div>
|
||||
@ -106,6 +122,8 @@
|
||||
currentUserRole = data.role;
|
||||
if (currentUserRole === 'user') {
|
||||
document.getElementById('fab-cart').classList.add('show');
|
||||
} else if (currentUserRole === 'admin') {
|
||||
document.getElementById('admin-link').style.display = 'block';
|
||||
}
|
||||
} else {
|
||||
handleAuthError();
|
||||
@ -167,7 +185,7 @@
|
||||
}
|
||||
|
||||
function renderBreadcrumb(path) {
|
||||
const bc = document.getElementById('breadcrumb');
|
||||
const bc = document.getElementById('breadcrumb-links');
|
||||
bc.innerHTML = `<a onclick="loadLevel('')">🏠 根目录</a>`;
|
||||
let parts = path.split('/').filter(p => p);
|
||||
let fullPath = "";
|
||||
@ -204,8 +222,20 @@
|
||||
const effectImageUrl = group.effectImageUrl ? `/raw${group.effectImageUrl}` : '';
|
||||
const displayName = cleanString(group.name);
|
||||
const itemId = cleanString(group.id);
|
||||
const cartButtonHtml = currentUserRole === 'user' ? `<button class="add-to-cart-btn" data-id="${itemId}" title="加入购物车"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"><path d="M.5 1a.5.5 0 0 0 0 1h1.11l.401 1.607 1.498 7.985A.5.5 0 0 0 4 12h1a2 2 0 1 0 0 4 2 2 0 0 0 0-4h7a2 2 0 1 0 0 4 2 2 0 0 0 0-4h1a.5.5 0 0 0 .491-.408l1.5-8A.5.5 0 0 0 14.5 3H2.89l-.405-1.621A.5.5 0 0 0 2 1zM6 14a1 1 0 1 1-2 0 1 1 0 0 1 2 0m7 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0M9 5.5V7h1.5a.5.5 0 0 1 0 1H9v1.5a.5.5 0 0 1-1 0V8H6.5a.5.5 0 0 1 0-1H8V5.5a.5.5 0 0 1 1 0"/></svg></button>` : '';
|
||||
item.innerHTML = `<img src="${effectThumbUrl}" data-original="${effectImageUrl}" alt="${displayName}" />${cartButtonHtml}<div class="image-info">${displayName}</div>`;
|
||||
|
||||
let cartButtonHtml = '';
|
||||
let inCartBadgeHtml = '';
|
||||
|
||||
if (currentUserRole === 'user') {
|
||||
if (group.inCart) {
|
||||
inCartBadgeHtml = '<div class="in-cart-badge">✔️</div>';
|
||||
cartButtonHtml = `<button class="add-to-cart-btn in-cart" data-id="${itemId}" title="已在购物车" disabled><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg></button>`;
|
||||
} else {
|
||||
cartButtonHtml = `<button class="add-to-cart-btn" data-id="${itemId}" title="加入购物车"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"><path d="M.5 1a.5.5 0 0 0 0 1h1.11l.401 1.607 1.498 7.985A.5.5 0 0 0 4 12h1a2 2 0 1 0 0 4 2 2 0 0 0 0-4h7a2 2 0 1 0 0 4 2 2 0 0 0 0-4h1a.5.5 0 0 0 .491-.408l1.5-8A.5.5 0 0 0 14.5 3H2.89l-.405-1.621A.5.5 0 0 0 2 1zM6 14a1 1 0 1 1-2 0 1 1 0 0 1 2 0m7 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0M9 5.5V7h1.5a.5.5 0 0 1 0 1H9v1.5a.5.5 0 0 1-1 0V8H6.5a.5.5 0 0 1 0-1H8V5.5a.5.5 0 0 1 1 0"/></svg></button>`;
|
||||
}
|
||||
}
|
||||
|
||||
item.innerHTML = `${inCartBadgeHtml}<img src="${effectThumbUrl}" data-original="${effectImageUrl}" alt="${displayName}" />${cartButtonHtml}<div class="image-info">${displayName}</div>`;
|
||||
grid.appendChild(item);
|
||||
});
|
||||
if (viewer) {
|
||||
@ -223,7 +253,7 @@
|
||||
async function handleAddToCart(itemId) {
|
||||
console.log(`Adding item ${itemId} to cart.`);
|
||||
try {
|
||||
const response = await fetch('/api/cart/add', { // **[PATH-FIX]** Reverted to /api/cart/add
|
||||
const response = await fetch('/api/cart/add', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ itemId: itemId })
|
||||
@ -234,6 +264,20 @@
|
||||
showToast(result, 'info');
|
||||
} else {
|
||||
showToast(result, 'success');
|
||||
const button = document.querySelector(`.add-to-cart-btn[data-id="${itemId}"]`);
|
||||
if(button){
|
||||
button.classList.add('in-cart');
|
||||
button.disabled = true;
|
||||
button.title = "已在购物车";
|
||||
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg>';
|
||||
const item = button.closest('.grid-item');
|
||||
if(item && !item.querySelector('.in-cart-badge')){
|
||||
const badge = document.createElement('div');
|
||||
badge.className = 'in-cart-badge';
|
||||
badge.textContent = '✔️';
|
||||
item.prepend(badge);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (response.status === 401) {
|
||||
handleAuthError();
|
||||
@ -249,12 +293,30 @@
|
||||
await fetchUserInfo();
|
||||
document.getElementById('image-grid').addEventListener('click', function(event) {
|
||||
const cartButton = event.target.closest('.add-to-cart-btn');
|
||||
if (cartButton) {
|
||||
if (cartButton && !cartButton.disabled) {
|
||||
event.stopPropagation();
|
||||
handleAddToCart(cartButton.dataset.id);
|
||||
}
|
||||
});
|
||||
loadLevel("");
|
||||
|
||||
particlesJS('particles-js', {
|
||||
"particles": {
|
||||
"number": { "value": 80, "density": { "enable": true, "value_area": 800 } },
|
||||
"color": { "value": "#28a745" },
|
||||
"shape": { "type": "circle", "stroke": { "width": 0, "color": "#000000" }, "polygon": { "nb_sides": 5 } },
|
||||
"opacity": { "value": 0.5, "random": false, "anim": { "enable": false, "speed": 1, "opacity_min": 0.1, "sync": false } },
|
||||
"size": { "value": 3, "random": true, "anim": { "enable": false, "speed": 40, "size_min": 0.1, "sync": false } },
|
||||
"line_linked": { "enable": true, "distance": 150, "color": "#28a745", "opacity": 0.4, "width": 1 },
|
||||
"move": { "enable": true, "speed": 6, "direction": "none", "random": false, "straight": false, "out_mode": "out", "bounce": false, "attract": { "enable": false, "rotateX": 600, "rotateY": 1200 } }
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "canvas",
|
||||
"events": { "onhover": { "enable": true, "mode": "repulse" }, "onclick": { "enable": true, "mode": "push" }, "resize": true },
|
||||
"modes": { "grab": { "distance": 400, "line_linked": { "opacity": 1 } }, "bubble": { "distance": 400, "size": 40, "duration": 2, "opacity": 8, "speed": 3 }, "repulse": { "distance": 200, "duration": 0.4 }, "push": { "particles_nb": 4 }, "remove": { "particles_nb": 2 } }
|
||||
},
|
||||
"retina_detect": true
|
||||
});
|
||||
}
|
||||
|
||||
initializeApp();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user