1081 lines
38 KiB
HTML
1081 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>积分商城 - 商品管理</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background-color: #f5f5f5;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.container {
|
|
max-width: 100%;
|
|
margin: 0 auto;
|
|
padding: 16px;
|
|
}
|
|
|
|
.header {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
padding: 20px 16px;
|
|
margin: -16px -16px 20px -16px;
|
|
}
|
|
|
|
.header h1 {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
}
|
|
|
|
.search-section {
|
|
background: white;
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.search-grid {
|
|
display: grid;
|
|
gap: 15px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.input-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.input-group label {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: #666;
|
|
}
|
|
|
|
.input-group input {
|
|
padding: 12px 16px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.input-group input:focus {
|
|
outline: none;
|
|
border-color: #667eea;
|
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
}
|
|
|
|
.search-btn {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
width: 100%;
|
|
}
|
|
|
|
.search-btn:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
|
}
|
|
|
|
.search-btn:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.products-section {
|
|
background: white;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.products-header {
|
|
background: #f8f9fa;
|
|
padding: 16px;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.products-header h2 {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.product-list {
|
|
padding: 0;
|
|
}
|
|
|
|
.product-card {
|
|
padding: 16px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.product-card:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.product-card:hover {
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.product-info {
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.product-name {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.product-details {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.product-detail {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.detail-label {
|
|
font-size: 12px;
|
|
color: #666;
|
|
min-width: 40px;
|
|
}
|
|
|
|
.detail-value {
|
|
font-size: 14px;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.product-price {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: #e74c3c;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.add-btn {
|
|
background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 16px;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
width: 100%;
|
|
}
|
|
|
|
.add-btn:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 3px 8px rgba(46, 204, 113, 0.3);
|
|
}
|
|
|
|
.add-btn:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.add-btn:disabled {
|
|
background: #95a5a6;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
.add-btn.discount {
|
|
background: linear-gradient(135deg, #e67e22 0%, #f39c12 100%);
|
|
}
|
|
|
|
.add-btn.discount:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 3px 8px rgba(230, 126, 34, 0.3);
|
|
}
|
|
|
|
.add-btn.discount:disabled {
|
|
background: #95a5a6;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
.add-btn.discount:disabled:hover {
|
|
transform: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
.pagination {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 8px;
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.pagination button {
|
|
padding: 8px 12px;
|
|
border: 1px solid #ddd;
|
|
background: white;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
color: #666;
|
|
transition: all 0.2s ease;
|
|
min-width: 40px;
|
|
}
|
|
|
|
.pagination button:hover {
|
|
background: #f8f9fa;
|
|
border-color: #667eea;
|
|
}
|
|
|
|
.pagination button.active {
|
|
background: #667eea;
|
|
color: white;
|
|
border-color: #667eea;
|
|
}
|
|
|
|
.pagination button:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 40px 20px;
|
|
color: #999;
|
|
}
|
|
|
|
.empty-state i {
|
|
font-size: 48px;
|
|
margin-bottom: 16px;
|
|
display: block;
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
.container {
|
|
max-width: 768px;
|
|
padding: 20px;
|
|
}
|
|
|
|
.search-grid {
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
|
|
.product-details {
|
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
}
|
|
|
|
.add-btn {
|
|
width: auto;
|
|
min-width: 120px;
|
|
}
|
|
}
|
|
|
|
.loading {
|
|
text-align: center;
|
|
padding: 20px;
|
|
color: #666;
|
|
}
|
|
|
|
.toast {
|
|
position: fixed;
|
|
top: 20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
background: #333;
|
|
color: white;
|
|
padding: 12px 20px;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
z-index: 1000;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.toast.show {
|
|
opacity: 1;
|
|
}
|
|
|
|
.toast.success {
|
|
background: #27ae60;
|
|
}
|
|
|
|
.toast.error {
|
|
background: #e74c3c;
|
|
}
|
|
|
|
.points-status {
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
border-radius: 12px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
margin-left: 8px;
|
|
}
|
|
|
|
.points-status.active {
|
|
background: #e8f5e8;
|
|
color: #27ae60;
|
|
border: 1px solid #27ae60;
|
|
}
|
|
|
|
.points-status.discount {
|
|
background: #fff3cd;
|
|
color: #e67e22;
|
|
border: 1px solid #e67e22;
|
|
}
|
|
|
|
.points-status.inactive {
|
|
background: #f8f8f8;
|
|
color: #666;
|
|
border: 1px solid #ddd;
|
|
}
|
|
|
|
.modal-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 1000;
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.modal-overlay.show {
|
|
display: flex;
|
|
}
|
|
|
|
.modal-content {
|
|
background: white;
|
|
border-radius: 16px;
|
|
max-width: 400px;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
animation: modalSlideIn 0.3s ease-out;
|
|
}
|
|
|
|
@keyframes modalSlideIn {
|
|
from {
|
|
transform: scale(0.8) translateY(-20px);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: scale(1) translateY(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.modal-header {
|
|
padding: 20px 24px;
|
|
border-bottom: 1px solid #eee;
|
|
position: relative;
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin: 0;
|
|
}
|
|
|
|
.modal-close {
|
|
position: absolute;
|
|
top: 20px;
|
|
right: 24px;
|
|
background: none;
|
|
border: none;
|
|
font-size: 24px;
|
|
color: #999;
|
|
cursor: pointer;
|
|
line-height: 1;
|
|
transition: color 0.2s ease;
|
|
}
|
|
|
|
.modal-close:hover {
|
|
color: #666;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 24px;
|
|
}
|
|
|
|
.exchange-info {
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.info-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px 0;
|
|
border-bottom: 1px solid #f5f5f5;
|
|
}
|
|
|
|
.info-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.info-label {
|
|
font-size: 14px;
|
|
color: #666;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.info-value {
|
|
font-size: 16px;
|
|
color: #333;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.info-value.highlight {
|
|
color: #e74c3c;
|
|
}
|
|
|
|
.modal-footer {
|
|
padding: 16px 24px;
|
|
border-top: 1px solid #eee;
|
|
display: flex;
|
|
gap: 12px;
|
|
}
|
|
|
|
.modal-btn {
|
|
flex: 1;
|
|
padding: 12px 16px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.modal-btn.cancel {
|
|
background: #f8f9fa;
|
|
color: #666;
|
|
border: 1px solid #ddd;
|
|
}
|
|
|
|
.modal-btn.cancel:hover {
|
|
background: #e9ecef;
|
|
border-color: #adb5bd;
|
|
}
|
|
|
|
.modal-btn.confirm {
|
|
background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
|
|
color: white;
|
|
}
|
|
|
|
.modal-btn.confirm:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgba(39, 174, 96, 0.3);
|
|
}
|
|
|
|
.info-input {
|
|
flex: 1;
|
|
padding: 8px 12px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
transition: all 0.3s ease;
|
|
min-width: 120px;
|
|
text-align: right;
|
|
}
|
|
|
|
.info-input:focus {
|
|
outline: none;
|
|
border-color: #667eea;
|
|
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
|
|
}
|
|
|
|
.info-input.highlight {
|
|
color: #e74c3c;
|
|
border-color: #e74c3c;
|
|
}
|
|
|
|
.info-input.highlight:focus {
|
|
border-color: #e74c3c;
|
|
box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.1);
|
|
}
|
|
|
|
.info-input::placeholder {
|
|
color: #999;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.info-input.error {
|
|
border-color: #e74c3c;
|
|
background-color: #ffeaea;
|
|
}
|
|
|
|
.input-error-message {
|
|
color: #e74c3c;
|
|
font-size: 12px;
|
|
margin-top: 4px;
|
|
display: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>积分商城 - 商品管理</h1>
|
|
</div>
|
|
|
|
<div class="search-section">
|
|
<div class="search-grid">
|
|
<div class="input-group">
|
|
<label for="shopName">店铺</label>
|
|
<input type="text" id="shopName" placeholder="请输入店铺名称">
|
|
</div>
|
|
<div class="input-group">
|
|
<label for="productName">商品名称</label>
|
|
<input type="text" id="productName" placeholder="请输入商品名称">
|
|
</div>
|
|
<div class="input-group">
|
|
<label for="productId">商品ID</label>
|
|
<input type="text" id="productId" placeholder="请输入商品ID">
|
|
</div>
|
|
</div>
|
|
<button class="search-btn" onclick="searchProducts()">查询</button>
|
|
</div>
|
|
|
|
<div class="products-section">
|
|
<div class="products-header">
|
|
<h2>商品列表</h2>
|
|
</div>
|
|
<div class="product-list" id="productList">
|
|
<div class="product-card">
|
|
<div class="product-info">
|
|
<div class="product-name">猪肉</div>
|
|
<div class="product-details">
|
|
<div class="product-detail">
|
|
<span class="detail-label">ID:</span>
|
|
<span class="detail-value">1212</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">店铺:</span>
|
|
<span class="detail-value">猪肉铺</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">规格:</span>
|
|
<span class="detail-value">大份</span>
|
|
</div>
|
|
</div>
|
|
<div class="product-price">¥2</div>
|
|
</div>
|
|
<button class="add-btn" onclick="addToPointsMall('1212', '猪肉', 'exchange')" style="margin-bottom: 8px;">添加为积分换购商品</button>
|
|
<button class="add-btn discount" onclick="addToPointsMall('1212', '猪肉', 'discount')">添加为积分优惠购商品</button>
|
|
</div>
|
|
|
|
<div class="product-card">
|
|
<div class="product-info">
|
|
<div class="product-name">牛肉</div>
|
|
<div class="product-details">
|
|
<div class="product-detail">
|
|
<span class="detail-label">ID:</span>
|
|
<span class="detail-value">1213</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">店铺:</span>
|
|
<span class="detail-value">牛肉铺</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">规格:</span>
|
|
<span class="detail-value">小份</span>
|
|
</div>
|
|
</div>
|
|
<div class="product-price">¥5</div>
|
|
</div>
|
|
<button class="add-btn" onclick="addToPointsMall('1213', '牛肉', 'exchange')" style="margin-bottom: 8px;">添加为积分换购商品</button>
|
|
<button class="add-btn discount" onclick="addToPointsMall('1213', '牛肉', 'discount')">添加为积分优惠购商品</button>
|
|
</div>
|
|
|
|
<div class="product-card">
|
|
<div class="product-info">
|
|
<div class="product-name">鸡肉</div>
|
|
<div class="product-details">
|
|
<div class="product-detail">
|
|
<span class="detail-label">ID:</span>
|
|
<span class="detail-value">1214</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">店铺:</span>
|
|
<span class="detail-value">鸡肉铺</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">规格:</span>
|
|
<span class="detail-value">无</span>
|
|
</div>
|
|
</div>
|
|
<div class="product-price">¥3</div>
|
|
</div>
|
|
<button class="add-btn" onclick="addToPointsMall('1214', '鸡肉', 'exchange')" style="margin-bottom: 8px;">添加为积分换购商品</button>
|
|
<button class="add-btn discount" onclick="addToPointsMall('1214', '鸡肉', 'discount')">添加为积分优惠购商品</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pagination">
|
|
<button onclick="changePage('prev')" id="prevBtn">Previous</button>
|
|
<button class="active" onclick="changePage(1)">1</button>
|
|
<button onclick="changePage(2)">2</button>
|
|
<button onclick="changePage(3)">3</button>
|
|
<button onclick="changePage('next')" id="nextBtn">Next</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="toast" id="toast"></div>
|
|
|
|
<!-- 积分兑换确认弹窗 -->
|
|
<div class="modal-overlay" id="exchangeModal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title" id="modalTitle">添加积分商品确认</h3>
|
|
<button class="modal-close" onclick="closeExchangeModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="exchange-info">
|
|
<div class="info-item">
|
|
<span class="info-label">商品ID</span>
|
|
<span class="info-value" id="modalProductId">-</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">商品名称</span>
|
|
<span class="info-value" id="modalProductName">-</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">归属摊位</span>
|
|
<span class="info-value" id="modalProductShop">-</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">规格名称</span>
|
|
<span class="info-value" id="modalProductSpec">-</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">SKU-ID</span>
|
|
<span class="info-value" id="modalProductSkuId">-</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">商品原价</span>
|
|
<span class="info-value" id="modalProductPrice">-</span>
|
|
</div>
|
|
<div class="info-item" id="pointsRequiredRow">
|
|
<span class="info-label">兑换所需积分</span>
|
|
<input type="number" class="info-input highlight" id="modalPointsRequired" min="1" placeholder="请输入积分">
|
|
</div>
|
|
<div class="info-item" id="discountPointsRow" style="display: none;">
|
|
<span class="info-label">优惠购所需积分</span>
|
|
<input type="number" class="info-input highlight" id="modalDiscountPoints" min="1" placeholder="请输入优惠购所需积分">
|
|
</div>
|
|
<div class="info-item" id="discountPriceRow" style="display: none;">
|
|
<span class="info-label">优惠购商品价格</span>
|
|
<input type="number" class="info-input" id="modalDiscountPrice" min="0" step="0.01" placeholder="请输入优惠购价格">
|
|
</div>
|
|
<div class="info-item">
|
|
<span class="info-label">最大可兑换数量</span>
|
|
<input type="number" class="info-input" id="modalMaxExchange" min="1" placeholder="请输入数量">
|
|
</div>
|
|
<div class="info-item" id="exchangeNoticeRow" style="display: none;">
|
|
<span class="info-label" style="color: #999; font-size: 12px; font-weight: normal;">说明</span>
|
|
<span class="info-value" style="color: #999; font-size: 12px; font-weight: normal;">固定支付0.01,商业支付要求</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="modal-btn cancel" onclick="closeExchangeModal()">取消</button>
|
|
<button class="modal-btn confirm" onclick="confirmAddToPointsMall()" id="confirmBtn">确认添加</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentPage = 1;
|
|
const totalPages = 3;
|
|
|
|
// 模拟商品数据
|
|
const allProducts = [
|
|
{id: '1212', name: '猪肉', shop: '猪肉铺', spec: '大份', price: 2, stock: 150, skuId: 'SKU1212001', exchangeType: 'none', pointsRequired: 200, maxExchangeCount: 50, discountPoints: 50},
|
|
{id: '1213', name: '牛肉', shop: '牛肉铺', spec: '小份', price: 5, stock: 80, skuId: 'SKU1213002', exchangeType: 'exchange', pointsRequired: 500, maxExchangeCount: 30, discountPoints: 100},
|
|
{id: '1214', name: '鸡肉', shop: '鸡肉铺', spec: '无', price: 3, stock: 200, skuId: 'SKU1214003', exchangeType: 'none', pointsRequired: 300, maxExchangeCount: 80, discountPoints: 80},
|
|
{id: '1215', name: '鱼肉', shop: '鱼肉铺', spec: '中份', price: 8, stock: 60, skuId: 'SKU1215004', exchangeType: 'discount', pointsRequired: 800, maxExchangeCount: 25, discountPoints: 200},
|
|
{id: '1216', name: '虾', shop: '海鲜铺', spec: '特大', price: 12, stock: 45, skuId: 'SKU1216005', exchangeType: 'none', pointsRequired: 1200, maxExchangeCount: 20, discountPoints: 300},
|
|
{id: '1217', name: '蟹', shop: '海鲜铺', spec: '精选', price: 25, stock: 30, skuId: 'SKU1217006', exchangeType: 'none', pointsRequired: 2500, maxExchangeCount: 15, discountPoints: 500},
|
|
];
|
|
|
|
let filteredProducts = [...allProducts];
|
|
let currentEditingProduct = null;
|
|
let currentExchangeType = null;
|
|
|
|
function showToast(message, type = 'success') {
|
|
const toast = document.getElementById('toast');
|
|
toast.textContent = message;
|
|
toast.className = `toast ${type} show`;
|
|
|
|
setTimeout(() => {
|
|
toast.classList.remove('show');
|
|
}, 3000);
|
|
}
|
|
|
|
function searchProducts() {
|
|
const shopName = document.getElementById('shopName').value.trim().toLowerCase();
|
|
const productName = document.getElementById('productName').value.trim().toLowerCase();
|
|
const productId = document.getElementById('productId').value.trim();
|
|
|
|
filteredProducts = allProducts.filter(product => {
|
|
const matchShop = !shopName || product.shop.toLowerCase().includes(shopName);
|
|
const matchName = !productName || product.name.toLowerCase().includes(productName);
|
|
const matchId = !productId || product.id.includes(productId);
|
|
|
|
return matchShop && matchName && matchId;
|
|
});
|
|
|
|
currentPage = 1;
|
|
renderProducts();
|
|
updatePagination();
|
|
|
|
if (filteredProducts.length === 0) {
|
|
showToast('未找到匹配的商品', 'error');
|
|
} else {
|
|
showToast(`找到 ${filteredProducts.length} 个商品`);
|
|
}
|
|
}
|
|
|
|
function renderProducts() {
|
|
const productList = document.getElementById('productList');
|
|
const startIndex = (currentPage - 1) * 3;
|
|
const endIndex = startIndex + 3;
|
|
const pageProducts = filteredProducts.slice(startIndex, endIndex);
|
|
|
|
if (pageProducts.length === 0) {
|
|
productList.innerHTML = `
|
|
<div class="empty-state">
|
|
<i>📦</i>
|
|
<div>暂无商品数据</div>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
productList.innerHTML = pageProducts.map(product => {
|
|
return `
|
|
<div class="product-card">
|
|
<div class="product-info">
|
|
<div class="product-name">${product.name}</div>
|
|
<div class="product-details">
|
|
<div class="product-detail">
|
|
<span class="detail-label">ID:</span>
|
|
<span class="detail-value">${product.id}</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">店铺:</span>
|
|
<span class="detail-value">${product.shop}</span>
|
|
</div>
|
|
<div class="product-detail">
|
|
<span class="detail-label">规格:</span>
|
|
<span class="detail-value">${product.spec}</span>
|
|
</div>
|
|
</div>
|
|
<div class="product-price">¥${product.price}</div>
|
|
</div>
|
|
<button class="add-btn" onclick="addToPointsMall('${product.id}', '${product.name}', 'exchange')" style="margin-bottom: 8px;">添加为积分换购商品</button>
|
|
<button class="add-btn discount" onclick="addToPointsMall('${product.id}', '${product.name}', 'discount')">添加为积分优惠购商品</button>
|
|
</div>`;
|
|
}).join('');
|
|
}
|
|
|
|
function addToPointsMall(productId, productName, exchangeType) {
|
|
const product = allProducts.find(p => p.id === productId);
|
|
if (!product) return;
|
|
|
|
currentEditingProduct = product;
|
|
currentExchangeType = exchangeType;
|
|
showExchangeModal(product, exchangeType);
|
|
}
|
|
|
|
function showExchangeModal(product, exchangeType) {
|
|
// 更新弹窗标题
|
|
const modalTitle = document.getElementById('modalTitle');
|
|
const pointsRequiredRow = document.getElementById('pointsRequiredRow');
|
|
const discountPointsRow = document.getElementById('discountPointsRow');
|
|
const discountPriceRow = document.getElementById('discountPriceRow');
|
|
const exchangeNoticeRow = document.getElementById('exchangeNoticeRow');
|
|
|
|
if (exchangeType === 'exchange') {
|
|
modalTitle.textContent = '添加积分换购商品确认';
|
|
pointsRequiredRow.style.display = 'flex';
|
|
discountPointsRow.style.display = 'none';
|
|
discountPriceRow.style.display = 'none';
|
|
exchangeNoticeRow.style.display = 'flex';
|
|
} else if (exchangeType === 'discount') {
|
|
modalTitle.textContent = '添加积分优惠购商品确认';
|
|
pointsRequiredRow.style.display = 'none';
|
|
discountPointsRow.style.display = 'flex';
|
|
discountPriceRow.style.display = 'flex';
|
|
exchangeNoticeRow.style.display = 'none';
|
|
}
|
|
|
|
document.getElementById('modalProductId').textContent = product.id;
|
|
document.getElementById('modalProductName').textContent = product.name;
|
|
document.getElementById('modalProductShop').textContent = product.shop;
|
|
document.getElementById('modalProductSpec').textContent = product.spec;
|
|
document.getElementById('modalProductSkuId').textContent = product.skuId || product.id;
|
|
document.getElementById('modalProductPrice').textContent = `¥${product.price}`;
|
|
|
|
if (exchangeType === 'exchange') {
|
|
document.getElementById('modalPointsRequired').value = product.pointsRequired;
|
|
} else if (exchangeType === 'discount') {
|
|
document.getElementById('modalDiscountPoints').value = product.discountPoints;
|
|
document.getElementById('modalDiscountPrice').value = product.discountPrice || product.price;
|
|
}
|
|
|
|
document.getElementById('modalMaxExchange').value = product.maxExchangeCount;
|
|
|
|
// 清除之前的错误状态
|
|
clearInputErrors();
|
|
|
|
document.getElementById('exchangeModal').classList.add('show');
|
|
document.body.style.overflow = 'hidden'; // 防止背景滚动
|
|
}
|
|
|
|
function closeExchangeModal() {
|
|
document.getElementById('exchangeModal').classList.remove('show');
|
|
document.body.style.overflow = 'auto';
|
|
currentEditingProduct = null;
|
|
currentExchangeType = null;
|
|
}
|
|
|
|
function validateInputs() {
|
|
const pointsInput = document.getElementById('modalPointsRequired');
|
|
const discountPointsInput = document.getElementById('modalDiscountPoints');
|
|
const discountPriceInput = document.getElementById('modalDiscountPrice');
|
|
const maxExchangeInput = document.getElementById('modalMaxExchange');
|
|
|
|
let isValid = true;
|
|
|
|
// 验证积分输入(根据类型)
|
|
if (currentExchangeType === 'exchange') {
|
|
const pointsValue = parseInt(pointsInput.value);
|
|
if (!pointsValue || pointsValue < 1) {
|
|
pointsInput.classList.add('error');
|
|
showToast('兑换所需积分必须大于0', 'error');
|
|
isValid = false;
|
|
} else {
|
|
pointsInput.classList.remove('error');
|
|
}
|
|
} else if (currentExchangeType === 'discount') {
|
|
const discountValue = parseInt(discountPointsInput.value);
|
|
if (!discountValue || discountValue < 1) {
|
|
discountPointsInput.classList.add('error');
|
|
showToast('优惠购所需积分必须大于0', 'error');
|
|
isValid = false;
|
|
} else {
|
|
discountPointsInput.classList.remove('error');
|
|
}
|
|
|
|
const discountPriceValue = parseFloat(discountPriceInput.value);
|
|
if (isNaN(discountPriceValue) || discountPriceValue < 0) {
|
|
discountPriceInput.classList.add('error');
|
|
showToast('优惠购商品价格必须大于等于0', 'error');
|
|
isValid = false;
|
|
} else {
|
|
discountPriceInput.classList.remove('error');
|
|
}
|
|
}
|
|
|
|
// 验证数量输入
|
|
const maxExchangeValue = parseInt(maxExchangeInput.value);
|
|
if (!maxExchangeValue || maxExchangeValue < 1) {
|
|
maxExchangeInput.classList.add('error');
|
|
showToast('最大可兑换数量必须大于0', 'error');
|
|
isValid = false;
|
|
} else if (maxExchangeValue > currentEditingProduct.stock) {
|
|
maxExchangeInput.classList.add('error');
|
|
showToast('最大可兑换数量不能超过库存数量', 'error');
|
|
isValid = false;
|
|
} else {
|
|
maxExchangeInput.classList.remove('error');
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
function clearInputErrors() {
|
|
document.getElementById('modalPointsRequired').classList.remove('error');
|
|
document.getElementById('modalDiscountPoints').classList.remove('error');
|
|
document.getElementById('modalDiscountPrice').classList.remove('error');
|
|
document.getElementById('modalMaxExchange').classList.remove('error');
|
|
}
|
|
|
|
function confirmAddToPointsMall() {
|
|
if (!currentEditingProduct || !currentExchangeType) return;
|
|
|
|
// 验证输入
|
|
if (!validateInputs()) {
|
|
return;
|
|
}
|
|
|
|
const confirmBtn = document.getElementById('confirmBtn');
|
|
const maxExchangeCount = parseInt(document.getElementById('modalMaxExchange').value);
|
|
|
|
let pointsValue = 0;
|
|
let discountPriceValue = 0;
|
|
let successMessage = '';
|
|
|
|
if (currentExchangeType === 'exchange') {
|
|
pointsValue = parseInt(document.getElementById('modalPointsRequired').value);
|
|
successMessage = `${currentEditingProduct.name} 已成功添加到积分换购商城!需要${pointsValue}积分,最多可兑换${maxExchangeCount}件`;
|
|
} else if (currentExchangeType === 'discount') {
|
|
pointsValue = parseInt(document.getElementById('modalDiscountPoints').value);
|
|
discountPriceValue = parseFloat(document.getElementById('modalDiscountPrice').value);
|
|
successMessage = `${currentEditingProduct.name} 已成功添加到积分优惠购商城!需要${pointsValue}积分,优惠购价格¥${discountPriceValue},最多可购买${maxExchangeCount}件`;
|
|
}
|
|
|
|
confirmBtn.disabled = true;
|
|
confirmBtn.textContent = '添加中...';
|
|
|
|
setTimeout(() => {
|
|
// 更新数据状态
|
|
currentEditingProduct.exchangeType = currentExchangeType;
|
|
currentEditingProduct.maxExchangeCount = maxExchangeCount;
|
|
|
|
if (currentExchangeType === 'exchange') {
|
|
currentEditingProduct.pointsRequired = pointsValue;
|
|
} else if (currentExchangeType === 'discount') {
|
|
currentEditingProduct.discountPoints = pointsValue;
|
|
currentEditingProduct.discountPrice = discountPriceValue;
|
|
}
|
|
|
|
// 重新渲染当前页面
|
|
renderProducts();
|
|
|
|
// 关闭弹窗
|
|
closeExchangeModal();
|
|
|
|
// 恢复按钮状态
|
|
confirmBtn.disabled = false;
|
|
confirmBtn.textContent = '确认添加';
|
|
|
|
showToast(successMessage);
|
|
}, 1000);
|
|
}
|
|
|
|
function changePage(page) {
|
|
if (page === 'prev' && currentPage > 1) {
|
|
currentPage--;
|
|
} else if (page === 'next' && currentPage < Math.ceil(filteredProducts.length / 3)) {
|
|
currentPage++;
|
|
} else if (typeof page === 'number') {
|
|
currentPage = page;
|
|
}
|
|
|
|
renderProducts();
|
|
updatePagination();
|
|
}
|
|
|
|
function updatePagination() {
|
|
const maxPages = Math.ceil(filteredProducts.length / 3);
|
|
const prevBtn = document.getElementById('prevBtn');
|
|
const nextBtn = document.getElementById('nextBtn');
|
|
|
|
prevBtn.disabled = currentPage === 1;
|
|
nextBtn.disabled = currentPage === maxPages || maxPages === 0;
|
|
|
|
// 更新页码按钮
|
|
const pageButtons = document.querySelectorAll('.pagination button:not(#prevBtn):not(#nextBtn)');
|
|
pageButtons.forEach((btn, index) => {
|
|
const pageNum = index + 1;
|
|
btn.style.display = pageNum <= maxPages ? 'block' : 'none';
|
|
btn.classList.toggle('active', pageNum === currentPage);
|
|
});
|
|
}
|
|
|
|
// 初始化页面
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
renderProducts();
|
|
updatePagination();
|
|
|
|
// 添加输入框回车搜索功能
|
|
document.addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
searchProducts();
|
|
}
|
|
});
|
|
|
|
// 点击弹窗背景关闭弹窗
|
|
document.getElementById('exchangeModal').addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
closeExchangeModal();
|
|
}
|
|
});
|
|
|
|
// ESC键关闭弹窗
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') {
|
|
closeExchangeModal();
|
|
}
|
|
});
|
|
|
|
// 输入框实时验证
|
|
document.getElementById('modalPointsRequired').addEventListener('input', function() {
|
|
if (this.classList.contains('error')) {
|
|
this.classList.remove('error');
|
|
}
|
|
});
|
|
|
|
document.getElementById('modalDiscountPoints').addEventListener('input', function() {
|
|
if (this.classList.contains('error')) {
|
|
this.classList.remove('error');
|
|
}
|
|
});
|
|
|
|
document.getElementById('modalDiscountPrice').addEventListener('input', function() {
|
|
if (this.classList.contains('error')) {
|
|
this.classList.remove('error');
|
|
}
|
|
});
|
|
|
|
document.getElementById('modalMaxExchange').addEventListener('input', function() {
|
|
if (this.classList.contains('error')) {
|
|
this.classList.remove('error');
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |