feat(积分商城): 商家端支持积分换购和积分优惠购
- 商家端后台积分商城功能更新,增加“积分换购”和“积分优惠购”两种模式。 - “添加积分商品”页面支持两种模式的独立设置。 - “积分商城”管理页面重构,统一了编辑弹窗,并为不同模式提供差异化配置。 - 删除了旧的弹窗文件,将逻辑整合。 - 更新了相关的原型文件。
This commit is contained in:
		
							parent
							
								
									8ee3ab19b6
								
							
						
					
					
						commit
						281db90590
					
				|  | @ -208,7 +208,22 @@ | ||||||
|             transform: none; |             transform: none; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         .add-btn:disabled:hover { |         .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; |             transform: none; | ||||||
|             box-shadow: none; |             box-shadow: none; | ||||||
|         } |         } | ||||||
|  | @ -275,7 +290,7 @@ | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             .product-details { |             .product-details { | ||||||
|                 grid-template-columns: 1fr 1fr 1fr; |                 grid-template-columns: 1fr 1fr 1fr 1fr; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             .add-btn { |             .add-btn { | ||||||
|  | @ -332,6 +347,12 @@ | ||||||
|             border: 1px solid #27ae60; |             border: 1px solid #27ae60; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         .points-status.discount { | ||||||
|  |             background: #fff3cd; | ||||||
|  |             color: #e67e22; | ||||||
|  |             border: 1px solid #e67e22; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         .points-status.inactive { |         .points-status.inactive { | ||||||
|             background: #f8f8f8; |             background: #f8f8f8; | ||||||
|             color: #666; |             color: #666; | ||||||
|  | @ -561,68 +582,71 @@ | ||||||
|             <div class="product-list" id="productList"> |             <div class="product-list" id="productList"> | ||||||
|                 <div class="product-card"> |                 <div class="product-card"> | ||||||
|                     <div class="product-info"> |                     <div class="product-info"> | ||||||
|                         <div class="product-name">猪肉<span class="points-status inactive">普通商品</span></div> |                         <div class="product-name">猪肉</div> | ||||||
|                         <div class="product-details"> |                         <div class="product-details"> | ||||||
|                             <div class="product-detail"> |  | ||||||
|                                 <span class="detail-label">店铺:</span> |  | ||||||
|                                 <span class="detail-value">猪肉铺</span> |  | ||||||
|                             </div> |  | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">ID:</span> |                                 <span class="detail-label">ID:</span> | ||||||
|                                 <span class="detail-value">1212</span> |                                 <span class="detail-value">1212</span> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">库存:</span> |                                 <span class="detail-label">店铺:</span> | ||||||
|                                 <span class="detail-value">150件</span> |                                 <span class="detail-value">猪肉铺</span> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="product-detail"> | ||||||
|  |                                 <span class="detail-label">规格:</span> | ||||||
|  |                                 <span class="detail-value">大份</span> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="product-price">¥2</div> |                         <div class="product-price">¥2</div> | ||||||
|                     </div> |                     </div> | ||||||
|                     <button class="add-btn" onclick="addToPointsMall('1212', '猪肉')">添加为积分商品</button> |                     <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> | ||||||
| 
 | 
 | ||||||
|                 <div class="product-card"> |                 <div class="product-card"> | ||||||
|                     <div class="product-info"> |                     <div class="product-info"> | ||||||
|                         <div class="product-name">牛肉<span class="points-status active">积分商品</span></div> |                         <div class="product-name">牛肉</div> | ||||||
|                         <div class="product-details"> |                         <div class="product-details"> | ||||||
|                             <div class="product-detail"> |  | ||||||
|                                 <span class="detail-label">店铺:</span> |  | ||||||
|                                 <span class="detail-value">牛肉铺</span> |  | ||||||
|                             </div> |  | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">ID:</span> |                                 <span class="detail-label">ID:</span> | ||||||
|                                 <span class="detail-value">1213</span> |                                 <span class="detail-value">1213</span> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">库存:</span> |                                 <span class="detail-label">店铺:</span> | ||||||
|                                 <span class="detail-value">80件</span> |                                 <span class="detail-value">牛肉铺</span> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="product-detail"> | ||||||
|  |                                 <span class="detail-label">规格:</span> | ||||||
|  |                                 <span class="detail-value">小份</span> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="product-price">¥5</div> |                         <div class="product-price">¥5</div> | ||||||
|                     </div> |                     </div> | ||||||
|                     <button class="add-btn" onclick="addToPointsMall('1213', '牛肉')" disabled>已是积分商品</button> |                     <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> | ||||||
| 
 | 
 | ||||||
|                 <div class="product-card"> |                 <div class="product-card"> | ||||||
|                     <div class="product-info"> |                     <div class="product-info"> | ||||||
|                         <div class="product-name">鸡肉<span class="points-status inactive">普通商品</span></div> |                         <div class="product-name">鸡肉</div> | ||||||
|                         <div class="product-details"> |                         <div class="product-details"> | ||||||
|                             <div class="product-detail"> |  | ||||||
|                                 <span class="detail-label">店铺:</span> |  | ||||||
|                                 <span class="detail-value">鸡肉铺</span> |  | ||||||
|                             </div> |  | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">ID:</span> |                                 <span class="detail-label">ID:</span> | ||||||
|                                 <span class="detail-value">1214</span> |                                 <span class="detail-value">1214</span> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">库存:</span> |                                 <span class="detail-label">店铺:</span> | ||||||
|                                 <span class="detail-value">200件</span> |                                 <span class="detail-value">鸡肉铺</span> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="product-detail"> | ||||||
|  |                                 <span class="detail-label">规格:</span> | ||||||
|  |                                 <span class="detail-value">无</span> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="product-price">¥3</div> |                         <div class="product-price">¥3</div> | ||||||
|                     </div> |                     </div> | ||||||
|                     <button class="add-btn" onclick="addToPointsMall('1214', '鸡肉')">添加为积分商品</button> |                     <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> | ||||||
|         </div> |         </div> | ||||||
|  | @ -642,27 +666,55 @@ | ||||||
|     <div class="modal-overlay" id="exchangeModal"> |     <div class="modal-overlay" id="exchangeModal"> | ||||||
|         <div class="modal-content"> |         <div class="modal-content"> | ||||||
|             <div class="modal-header"> |             <div class="modal-header"> | ||||||
|                 <h3 class="modal-title">添加积分商品确认</h3> |                 <h3 class="modal-title" id="modalTitle">添加积分商品确认</h3> | ||||||
|                 <button class="modal-close" onclick="closeExchangeModal()">×</button> |                 <button class="modal-close" onclick="closeExchangeModal()">×</button> | ||||||
|             </div> |             </div> | ||||||
|             <div class="modal-body"> |             <div class="modal-body"> | ||||||
|                 <div class="exchange-info"> |                 <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"> |                     <div class="info-item"> | ||||||
|                         <span class="info-label">商品名称</span> |                         <span class="info-label">商品名称</span> | ||||||
|                         <span class="info-value" id="modalProductName">-</span> |                         <span class="info-value" id="modalProductName">-</span> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="info-item"> |                     <div class="info-item"> | ||||||
|                         <span class="info-label">当前库存</span> |                         <span class="info-label">归属摊位</span> | ||||||
|                         <span class="info-value" id="modalProductStock">-</span> |                         <span class="info-value" id="modalProductShop">-</span> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="info-item"> |                     <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> |                         <span class="info-label">兑换所需积分</span> | ||||||
|                         <input type="number" class="info-input highlight" id="modalPointsRequired" min="1" placeholder="请输入积分"> |                         <input type="number" class="info-input highlight" id="modalPointsRequired" min="1" placeholder="请输入积分"> | ||||||
|                     </div> |                     </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"> |                     <div class="info-item"> | ||||||
|                         <span class="info-label">最大可兑换数量</span> |                         <span class="info-label">最大可兑换数量</span> | ||||||
|                         <input type="number" class="info-input" id="modalMaxExchange" min="1" placeholder="请输入数量"> |                         <input type="number" class="info-input" id="modalMaxExchange" min="1" placeholder="请输入数量"> | ||||||
|                     </div> |                     </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> |             </div> | ||||||
|             <div class="modal-footer"> |             <div class="modal-footer"> | ||||||
|  | @ -678,16 +730,17 @@ | ||||||
| 
 | 
 | ||||||
|         // 模拟商品数据 |         // 模拟商品数据 | ||||||
|         const allProducts = [ |         const allProducts = [ | ||||||
|             {id: '1212', name: '猪肉', shop: '猪肉铺', price: 2, stock: 150, isPointsProduct: false, pointsRequired: 200, maxExchangeCount: 50}, |             {id: '1212', name: '猪肉', shop: '猪肉铺', spec: '大份', price: 2, stock: 150, skuId: 'SKU1212001', exchangeType: 'none', pointsRequired: 200, maxExchangeCount: 50, discountPoints: 50}, | ||||||
|             {id: '1213', name: '牛肉', shop: '牛肉铺', price: 5, stock: 80, isPointsProduct: true, pointsRequired: 500, maxExchangeCount: 30}, |             {id: '1213', name: '牛肉', shop: '牛肉铺', spec: '小份', price: 5, stock: 80, skuId: 'SKU1213002', exchangeType: 'exchange', pointsRequired: 500, maxExchangeCount: 30, discountPoints: 100}, | ||||||
|             {id: '1214', name: '鸡肉', shop: '鸡肉铺', price: 3, stock: 200, isPointsProduct: false, pointsRequired: 300, maxExchangeCount: 80}, |             {id: '1214', name: '鸡肉', shop: '鸡肉铺', spec: '无', price: 3, stock: 200, skuId: 'SKU1214003', exchangeType: 'none', pointsRequired: 300, maxExchangeCount: 80, discountPoints: 80}, | ||||||
|             {id: '1215', name: '鱼肉', shop: '鱼肉铺', price: 8, stock: 60, isPointsProduct: true, pointsRequired: 800, maxExchangeCount: 25}, |             {id: '1215', name: '鱼肉', shop: '鱼肉铺', spec: '中份', price: 8, stock: 60, skuId: 'SKU1215004', exchangeType: 'discount', pointsRequired: 800, maxExchangeCount: 25, discountPoints: 200}, | ||||||
|             {id: '1216', name: '虾', shop: '海鲜铺', price: 12, stock: 45, isPointsProduct: false, pointsRequired: 1200, maxExchangeCount: 20}, |             {id: '1216', name: '虾', shop: '海鲜铺', spec: '特大', price: 12, stock: 45, skuId: 'SKU1216005', exchangeType: 'none', pointsRequired: 1200, maxExchangeCount: 20, discountPoints: 300}, | ||||||
|             {id: '1217', name: '蟹', shop: '海鲜铺', price: 25, stock: 30, isPointsProduct: false, pointsRequired: 2500, maxExchangeCount: 15}, |             {id: '1217', name: '蟹', shop: '海鲜铺', spec: '精选', price: 25, stock: 30, skuId: 'SKU1217006', exchangeType: 'none', pointsRequired: 2500, maxExchangeCount: 15, discountPoints: 500}, | ||||||
|         ]; |         ]; | ||||||
| 
 | 
 | ||||||
|         let filteredProducts = [...allProducts]; |         let filteredProducts = [...allProducts]; | ||||||
|         let currentEditingProduct = null; |         let currentEditingProduct = null; | ||||||
|  |         let currentExchangeType = null; | ||||||
| 
 | 
 | ||||||
|         function showToast(message, type = 'success') { |         function showToast(message, type = 'success') { | ||||||
|             const toast = document.getElementById('toast'); |             const toast = document.getElementById('toast'); | ||||||
|  | @ -740,54 +793,77 @@ | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             productList.innerHTML = pageProducts.map(product => { |             productList.innerHTML = pageProducts.map(product => { | ||||||
|                 const statusClass = product.isPointsProduct ? 'active' : 'inactive'; |  | ||||||
|                 const statusText = product.isPointsProduct ? '积分商品' : '普通商品'; |  | ||||||
|                 const buttonText = product.isPointsProduct ? '已是积分商品' : '添加为积分商品'; |  | ||||||
|                 const buttonDisabled = product.isPointsProduct ? 'disabled' : ''; |  | ||||||
|                  |  | ||||||
|                 return ` |                 return ` | ||||||
|                 <div class="product-card"> |                 <div class="product-card"> | ||||||
|                     <div class="product-info"> |                     <div class="product-info"> | ||||||
|                         <div class="product-name">${product.name}<span class="points-status ${statusClass}">${statusText}</span></div> |                         <div class="product-name">${product.name}</div> | ||||||
|                         <div class="product-details"> |                         <div class="product-details"> | ||||||
|                             <div class="product-detail"> |  | ||||||
|                                 <span class="detail-label">店铺:</span> |  | ||||||
|                                 <span class="detail-value">${product.shop}</span> |  | ||||||
|                             </div> |  | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">ID:</span> |                                 <span class="detail-label">ID:</span> | ||||||
|                                 <span class="detail-value">${product.id}</span> |                                 <span class="detail-value">${product.id}</span> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div class="product-detail"> |                             <div class="product-detail"> | ||||||
|                                 <span class="detail-label">库存:</span> |                                 <span class="detail-label">店铺:</span> | ||||||
|                                 <span class="detail-value">${product.stock}件</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> |                         </div> | ||||||
|                         <div class="product-price">¥${product.price}</div> |                         <div class="product-price">¥${product.price}</div> | ||||||
|                     </div> |                     </div> | ||||||
|                     <button class="add-btn" onclick="addToPointsMall('${product.id}', '${product.name}')" ${buttonDisabled}>${buttonText}</button> |                     <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>`; |                 </div>`; | ||||||
|             }).join(''); |             }).join(''); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function addToPointsMall(productId, productName) { |         function addToPointsMall(productId, productName, exchangeType) { | ||||||
|             // 检查是否已经是积分商品 |  | ||||||
|             const product = allProducts.find(p => p.id === productId); |             const product = allProducts.find(p => p.id === productId); | ||||||
|             if (product && product.isPointsProduct) { |             if (!product) return; | ||||||
|                 showToast(`${productName} 已经是积分商品了!`, 'error'); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             if (product) { |  | ||||||
|             currentEditingProduct = product; |             currentEditingProduct = product; | ||||||
|                 showExchangeModal(product); |             currentExchangeType = exchangeType; | ||||||
|             } |             showExchangeModal(product, exchangeType); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function showExchangeModal(product) { |         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('modalProductName').textContent = product.name; | ||||||
|             document.getElementById('modalProductStock').textContent = `${product.stock}件`; |             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; |                 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; |             document.getElementById('modalMaxExchange').value = product.maxExchangeCount; | ||||||
|              |              | ||||||
|             // 清除之前的错误状态 |             // 清除之前的错误状态 | ||||||
|  | @ -801,15 +877,19 @@ | ||||||
|             document.getElementById('exchangeModal').classList.remove('show'); |             document.getElementById('exchangeModal').classList.remove('show'); | ||||||
|             document.body.style.overflow = 'auto'; |             document.body.style.overflow = 'auto'; | ||||||
|             currentEditingProduct = null; |             currentEditingProduct = null; | ||||||
|  |             currentExchangeType = null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function validateInputs() { |         function validateInputs() { | ||||||
|             const pointsInput = document.getElementById('modalPointsRequired'); |             const pointsInput = document.getElementById('modalPointsRequired'); | ||||||
|  |             const discountPointsInput = document.getElementById('modalDiscountPoints'); | ||||||
|  |             const discountPriceInput = document.getElementById('modalDiscountPrice'); | ||||||
|             const maxExchangeInput = document.getElementById('modalMaxExchange'); |             const maxExchangeInput = document.getElementById('modalMaxExchange'); | ||||||
|              |              | ||||||
|             let isValid = true; |             let isValid = true; | ||||||
|              |              | ||||||
|             // 验证积分输入 |             // 验证积分输入(根据类型) | ||||||
|  |             if (currentExchangeType === 'exchange') { | ||||||
|                 const pointsValue = parseInt(pointsInput.value); |                 const pointsValue = parseInt(pointsInput.value); | ||||||
|                 if (!pointsValue || pointsValue < 1) { |                 if (!pointsValue || pointsValue < 1) { | ||||||
|                     pointsInput.classList.add('error'); |                     pointsInput.classList.add('error'); | ||||||
|  | @ -818,6 +898,25 @@ | ||||||
|                 } else { |                 } else { | ||||||
|                     pointsInput.classList.remove('error'); |                     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); |             const maxExchangeValue = parseInt(maxExchangeInput.value); | ||||||
|  | @ -838,11 +937,13 @@ | ||||||
|          |          | ||||||
|         function clearInputErrors() { |         function clearInputErrors() { | ||||||
|             document.getElementById('modalPointsRequired').classList.remove('error'); |             document.getElementById('modalPointsRequired').classList.remove('error'); | ||||||
|  |             document.getElementById('modalDiscountPoints').classList.remove('error'); | ||||||
|  |             document.getElementById('modalDiscountPrice').classList.remove('error'); | ||||||
|             document.getElementById('modalMaxExchange').classList.remove('error'); |             document.getElementById('modalMaxExchange').classList.remove('error'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function confirmAddToPointsMall() { |         function confirmAddToPointsMall() { | ||||||
|             if (!currentEditingProduct) return; |             if (!currentEditingProduct || !currentExchangeType) return; | ||||||
|              |              | ||||||
|             // 验证输入 |             // 验证输入 | ||||||
|             if (!validateInputs()) { |             if (!validateInputs()) { | ||||||
|  | @ -850,18 +951,36 @@ | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const confirmBtn = document.getElementById('confirmBtn'); |             const confirmBtn = document.getElementById('confirmBtn'); | ||||||
|             const pointsRequired = parseInt(document.getElementById('modalPointsRequired').value); |  | ||||||
|             const maxExchangeCount = parseInt(document.getElementById('modalMaxExchange').value); |             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.disabled = true; | ||||||
|             confirmBtn.textContent = '添加中...'; |             confirmBtn.textContent = '添加中...'; | ||||||
| 
 | 
 | ||||||
|             setTimeout(() => { |             setTimeout(() => { | ||||||
|                 // 更新数据状态,使用用户输入的值 |                 // 更新数据状态 | ||||||
|                 currentEditingProduct.isPointsProduct = true; |                 currentEditingProduct.exchangeType = currentExchangeType; | ||||||
|                 currentEditingProduct.pointsRequired = pointsRequired; |  | ||||||
|                 currentEditingProduct.maxExchangeCount = maxExchangeCount; |                 currentEditingProduct.maxExchangeCount = maxExchangeCount; | ||||||
|                  |                  | ||||||
|  |                 if (currentExchangeType === 'exchange') { | ||||||
|  |                     currentEditingProduct.pointsRequired = pointsValue; | ||||||
|  |                 } else if (currentExchangeType === 'discount') { | ||||||
|  |                     currentEditingProduct.discountPoints = pointsValue; | ||||||
|  |                     currentEditingProduct.discountPrice = discountPriceValue; | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|                 // 重新渲染当前页面 |                 // 重新渲染当前页面 | ||||||
|                 renderProducts(); |                 renderProducts(); | ||||||
|                  |                  | ||||||
|  | @ -872,7 +991,7 @@ | ||||||
|                 confirmBtn.disabled = false; |                 confirmBtn.disabled = false; | ||||||
|                 confirmBtn.textContent = '确认添加'; |                 confirmBtn.textContent = '确认添加'; | ||||||
|                  |                  | ||||||
|                 showToast(`${currentEditingProduct.name} 已成功添加到积分商城!需要${pointsRequired}积分,最多可兑换${maxExchangeCount}件`); |                 showToast(successMessage); | ||||||
|             }, 1000); |             }, 1000); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -939,6 +1058,18 @@ | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|              |              | ||||||
|  |             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() { |             document.getElementById('modalMaxExchange').addEventListener('input', function() { | ||||||
|                 if (this.classList.contains('error')) { |                 if (this.classList.contains('error')) { | ||||||
|                     this.classList.remove('error'); |                     this.classList.remove('error'); | ||||||
|  |  | ||||||
|  | @ -376,6 +376,118 @@ | ||||||
|             color: #666; |             color: #666; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         .product-info-section { | ||||||
|  |             background: #f8f9fa; | ||||||
|  |             padding: 16px; | ||||||
|  |             border-radius: 8px; | ||||||
|  |             margin-bottom: 20px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-row { | ||||||
|  |             display: flex; | ||||||
|  |             justify-content: space-between; | ||||||
|  |             align-items: center; | ||||||
|  |             padding: 8px 0; | ||||||
|  |             border-bottom: 1px solid #e9ecef; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-row:last-child { | ||||||
|  |             border-bottom: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-label { | ||||||
|  |             font-size: 14px; | ||||||
|  |             color: #666; | ||||||
|  |             font-weight: 500; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-value { | ||||||
|  |             font-size: 14px; | ||||||
|  |             color: #333; | ||||||
|  |             font-weight: 600; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .required { | ||||||
|  |             color: #ff4757; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-control { | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             gap: 0; | ||||||
|  |             border: 1px solid #ddd; | ||||||
|  |             border-radius: 6px; | ||||||
|  |             overflow: hidden; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-btn { | ||||||
|  |             width: 40px; | ||||||
|  |             height: 48px; | ||||||
|  |             border: none; | ||||||
|  |             background: #f8f9fa; | ||||||
|  |             color: #333; | ||||||
|  |             font-size: 18px; | ||||||
|  |             cursor: pointer; | ||||||
|  |             transition: all 0.2s ease; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-btn:hover { | ||||||
|  |             background: #e9ecef; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-btn:active { | ||||||
|  |             background: #dee2e6; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-input { | ||||||
|  |             border: none; | ||||||
|  |             text-align: center; | ||||||
|  |             flex: 1; | ||||||
|  |             min-width: 60px; | ||||||
|  |             font-weight: 600; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-input:focus { | ||||||
|  |             outline: none; | ||||||
|  |             border: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .radio-group { | ||||||
|  |             display: flex; | ||||||
|  |             gap: 24px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .radio-option { | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             cursor: pointer; | ||||||
|  |             font-size: 14px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .radio-option input[type="radio"] { | ||||||
|  |             width: 18px; | ||||||
|  |             height: 18px; | ||||||
|  |             margin-right: 8px; | ||||||
|  |             accent-color: #007AFF; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .radio-text { | ||||||
|  |             color: #333; | ||||||
|  |             user-select: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-display { | ||||||
|  |             padding: 12px; | ||||||
|  |             background: #f8f9fa; | ||||||
|  |             border: 1px solid #e9ecef; | ||||||
|  |             border-radius: 6px; | ||||||
|  |             color: #333; | ||||||
|  |             font-weight: 500; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         @media (min-width: 768px) { |         @media (min-width: 768px) { | ||||||
|             .container { |             .container { | ||||||
|                 max-width: 800px; |                 max-width: 800px; | ||||||
|  | @ -486,6 +598,8 @@ | ||||||
|         <div class="modal-content"> |         <div class="modal-content"> | ||||||
|             <div class="modal-header" id="modalTitle">添加商品</div> |             <div class="modal-header" id="modalTitle">添加商品</div> | ||||||
|             <div class="modal-body"> |             <div class="modal-body"> | ||||||
|  |                 <!-- 添加模式 --> | ||||||
|  |                 <div id="addMode" style="display: none;"> | ||||||
|                     <div class="filter-row"> |                     <div class="filter-row"> | ||||||
|                         <label class="filter-label">商品名称</label> |                         <label class="filter-label">商品名称</label> | ||||||
|                         <input type="text" class="filter-input" id="modalProductName" placeholder="请输入商品名称"> |                         <input type="text" class="filter-input" id="modalProductName" placeholder="请输入商品名称"> | ||||||
|  | @ -503,7 +617,7 @@ | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="filter-row"> |                     <div class="filter-row"> | ||||||
|                         <label class="filter-label">积分使用模式</label> |                         <label class="filter-label">积分使用模式</label> | ||||||
|                     <select class="filter-select" id="modalPoints"> |                         <select class="filter-select" id="modalPoints" onchange="updatePointsMode()"> | ||||||
|                             <option value="">请选择积分使用模式</option> |                             <option value="">请选择积分使用模式</option> | ||||||
|                             <option value="积分换购">积分换购</option> |                             <option value="积分换购">积分换购</option> | ||||||
|                             <option value="积分优惠购">积分优惠购</option> |                             <option value="积分优惠购">积分优惠购</option> | ||||||
|  | @ -514,9 +628,122 @@ | ||||||
|                         <input type="number" class="filter-input" id="modalStock" placeholder="请输入库存数量"> |                         <input type="number" class="filter-input" id="modalStock" placeholder="请输入库存数量"> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|  |                  | ||||||
|  |                 <!-- 编辑模式 - 积分换购 --> | ||||||
|  |                 <div id="editModeExchange" style="display: none;"> | ||||||
|  |                     <div class="product-info-section"> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品ID:</span> | ||||||
|  |                             <span class="info-value" id="displayProductId"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品名称:</span> | ||||||
|  |                             <span class="info-value" id="displayProductName"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">归属摊位:</span> | ||||||
|  |                             <span class="info-value" id="displayStore"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">规格名称:</span> | ||||||
|  |                             <span class="info-value" id="displaySpec"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">SKU-ID:</span> | ||||||
|  |                             <span class="info-value" id="displaySkuId"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品原价:</span> | ||||||
|  |                             <span class="info-value" id="displayPrice"></span> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">添加库存(负数代表减少库存) <span class="required">*</span></label> | ||||||
|  |                         <div class="quantity-control"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalStockEdit', -1)">-</button> | ||||||
|  |                             <input type="number" class="filter-input quantity-input" id="modalStockEdit" value="10"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalStockEdit', 1)">+</button> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">积分类型</label> | ||||||
|  |                         <div class="info-display">积分换购</div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">兑换所需积分设置 <span class="required">*</span></label> | ||||||
|  |                         <div class="quantity-control"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalPoints', -1)">-</button> | ||||||
|  |                             <input type="number" class="filter-input quantity-input" id="modalPointsRequired" value="1" min="1"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalPointsRequired', 1)">+</button> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">最低兑换金额(商业支付最少0.01元)</label> | ||||||
|  |                         <input type="text" class="filter-input" id="modalMinAmount" value="0.01元" readonly> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                  | ||||||
|  |                 <!-- 编辑模式 - 积分优惠购 --> | ||||||
|  |                 <div id="editModeDiscount" style="display: none;"> | ||||||
|  |                     <div class="product-info-section"> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品ID:</span> | ||||||
|  |                             <span class="info-value" id="displayProductIdDiscount"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品名称:</span> | ||||||
|  |                             <span class="info-value" id="displayProductNameDiscount"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">归属摊位:</span> | ||||||
|  |                             <span class="info-value" id="displayStoreDiscount"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">规格名称:</span> | ||||||
|  |                             <span class="info-value" id="displaySpecDiscount"></span> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="info-row"> | ||||||
|  |                             <span class="info-label">商品原价:</span> | ||||||
|  |                             <span class="info-value" id="displayPriceDiscount"></span> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">添加库存(负数代表减少库存) <span class="required">*</span></label> | ||||||
|  |                         <div class="quantity-control"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalStockEditDiscount', -1)">-</button> | ||||||
|  |                             <input type="number" class="filter-input quantity-input" id="modalStockEditDiscount" value="10"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalStockEditDiscount', 1)">+</button> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">积分类型</label> | ||||||
|  |                         <div class="info-display">积分优惠购</div> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">积分抵扣金额设置 <span class="required">*</span></label> | ||||||
|  |                         <input type="number" step="0.01" class="filter-input" id="modalDiscountAmount" placeholder="请输入积分抵扣金额" min="0.01"> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <div class="filter-row"> | ||||||
|  |                         <label class="filter-label">所需积分数量 <span class="required">*</span></label> | ||||||
|  |                         <div class="quantity-control"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalDiscountPoints', -1)">-</button> | ||||||
|  |                             <input type="number" class="filter-input quantity-input" id="modalDiscountPoints" value="100" min="1"> | ||||||
|  |                             <button type="button" class="quantity-btn" onclick="changeQuantity('modalDiscountPoints', 1)">+</button> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|             <div class="modal-buttons"> |             <div class="modal-buttons"> | ||||||
|                 <button class="btn btn-secondary" onclick="hideModal()">取消</button> |                 <button class="btn btn-secondary" onclick="hideModal()">取消</button> | ||||||
|                 <button class="btn btn-primary" onclick="saveProduct()">保存</button> |                 <button class="btn btn-primary" onclick="saveProduct()">确认</button> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | @ -533,7 +760,11 @@ | ||||||
|                 originalStatus: '上架', |                 originalStatus: '上架', | ||||||
|                 pointsMode: '积分换购', |                 pointsMode: '积分换购', | ||||||
|                 stock: 10, |                 stock: 10, | ||||||
|                 enabled: true |                 enabled: true, | ||||||
|  |                 skuId: '19410514277450383601', | ||||||
|  |                 pointsRequired: 50, | ||||||
|  |                 discountAmount: null, | ||||||
|  |                 discountPoints: null | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 id: '002', |                 id: '002', | ||||||
|  | @ -544,7 +775,11 @@ | ||||||
|                 originalStatus: '上架', |                 originalStatus: '上架', | ||||||
|                 pointsMode: '积分优惠购', |                 pointsMode: '积分优惠购', | ||||||
|                 stock: 10, |                 stock: 10, | ||||||
|                 enabled: true |                 enabled: true, | ||||||
|  |                 skuId: '19410514277450383602', | ||||||
|  |                 pointsRequired: null, | ||||||
|  |                 discountAmount: 2.00, | ||||||
|  |                 discountPoints: 100 | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 id: '003', |                 id: '003', | ||||||
|  | @ -555,7 +790,11 @@ | ||||||
|                 originalStatus: '下架', |                 originalStatus: '下架', | ||||||
|                 pointsMode: '积分换购', |                 pointsMode: '积分换购', | ||||||
|                 stock: 2, |                 stock: 2, | ||||||
|                 enabled: false |                 enabled: false, | ||||||
|  |                 skuId: '19410514277450383603', | ||||||
|  |                 pointsRequired: 35, | ||||||
|  |                 discountAmount: null, | ||||||
|  |                 discountPoints: null | ||||||
|             } |             } | ||||||
|         ]; |         ]; | ||||||
| 
 | 
 | ||||||
|  | @ -812,12 +1051,45 @@ | ||||||
|                 const product = pointsDiscountProducts[index]; |                 const product = pointsDiscountProducts[index]; | ||||||
|                 if (!product) return; |                 if (!product) return; | ||||||
| 
 | 
 | ||||||
|                 document.getElementById('modalTitle').textContent = '编辑商品'; |                 document.getElementById('modalTitle').textContent = '已选择商品'; | ||||||
|                 document.getElementById('modalProductName').value = product.name; |                  | ||||||
|                 document.getElementById('modalStore').value = product.store; |                 // 隐藏所有模式 | ||||||
|                 document.getElementById('modalPrice').value = product.price; |                 document.getElementById('addMode').style.display = 'none'; | ||||||
|                 document.getElementById('modalPoints').value = product.pointsMode; |                 document.getElementById('editModeExchange').style.display = 'none'; | ||||||
|                 document.getElementById('modalStock').value = product.stock; |                 document.getElementById('editModeDiscount').style.display = 'none'; | ||||||
|  |                  | ||||||
|  |                 if (product.pointsMode === '积分换购') { | ||||||
|  |                     // 显示积分换购编辑模式 | ||||||
|  |                     document.getElementById('editModeExchange').style.display = 'block'; | ||||||
|  |                      | ||||||
|  |                     // 填充商品信息 | ||||||
|  |                     document.getElementById('displayProductId').textContent = product.id; | ||||||
|  |                     document.getElementById('displayProductName').textContent = product.name; | ||||||
|  |                     document.getElementById('displayStore').textContent = product.store; | ||||||
|  |                     document.getElementById('displaySpec').textContent = product.spec; | ||||||
|  |                     document.getElementById('displaySkuId').textContent = product.skuId; | ||||||
|  |                     document.getElementById('displayPrice').textContent = `¥${product.price.toFixed(2)}`; | ||||||
|  |                      | ||||||
|  |                     // 设置可编辑字段 | ||||||
|  |                     document.getElementById('modalStockEdit').value = product.stock; | ||||||
|  |                     document.getElementById('modalPointsRequired').value = product.pointsRequired || 1; | ||||||
|  |                 } else { | ||||||
|  |                     // 显示积分优惠购编辑模式 | ||||||
|  |                     document.getElementById('editModeDiscount').style.display = 'block'; | ||||||
|  |                      | ||||||
|  |                     // 填充商品信息 | ||||||
|  |                     document.getElementById('displayProductIdDiscount').textContent = product.id; | ||||||
|  |                     document.getElementById('displayProductNameDiscount').textContent = product.name; | ||||||
|  |                     document.getElementById('displayStoreDiscount').textContent = product.store; | ||||||
|  |                     document.getElementById('displaySpecDiscount').textContent = product.spec; | ||||||
|  |                     document.getElementById('displayPriceDiscount').textContent = `¥${product.price.toFixed(2)}`; | ||||||
|  |                      | ||||||
|  |                     // 设置可编辑字段 | ||||||
|  |                     document.getElementById('modalStockEditDiscount').value = product.stock; | ||||||
|  |                     document.getElementById('modalDiscountAmount').value = product.discountAmount || ''; | ||||||
|  |                     document.getElementById('modalDiscountPoints').value = product.discountPoints || 100; | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|                 currentEditId = index; |                 currentEditId = index; | ||||||
|                 document.getElementById('productModal').style.display = 'block'; |                 document.getElementById('productModal').style.display = 'block'; | ||||||
|             } else { |             } else { | ||||||
|  | @ -827,6 +1099,13 @@ | ||||||
| 
 | 
 | ||||||
|         function showAddModal() { |         function showAddModal() { | ||||||
|             document.getElementById('modalTitle').textContent = '添加商品'; |             document.getElementById('modalTitle').textContent = '添加商品'; | ||||||
|  |              | ||||||
|  |             // 显示添加模式,隐藏编辑模式 | ||||||
|  |             document.getElementById('addMode').style.display = 'block'; | ||||||
|  |             document.getElementById('editModeExchange').style.display = 'none'; | ||||||
|  |             document.getElementById('editModeDiscount').style.display = 'none'; | ||||||
|  |              | ||||||
|  |             // 清空表单 | ||||||
|             document.getElementById('modalProductName').value = ''; |             document.getElementById('modalProductName').value = ''; | ||||||
|             document.getElementById('modalStore').value = ''; |             document.getElementById('modalStore').value = ''; | ||||||
|             document.getElementById('modalPrice').value = ''; |             document.getElementById('modalPrice').value = ''; | ||||||
|  | @ -842,6 +1121,45 @@ | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function saveProduct() { |         function saveProduct() { | ||||||
|  |             if (currentEditId !== null) { | ||||||
|  |                 // 编辑模式 | ||||||
|  |                 const product = pointsDiscountProducts[currentEditId]; | ||||||
|  |                  | ||||||
|  |                 if (product.pointsMode === '积分换购') { | ||||||
|  |                     // 积分换购模式 | ||||||
|  |                     const stock = parseInt(document.getElementById('modalStockEdit').value); | ||||||
|  |                     const pointsRequired = parseInt(document.getElementById('modalPointsRequired').value); | ||||||
|  |                      | ||||||
|  |                     if (stock === null || stock === undefined || !pointsRequired) { | ||||||
|  |                         alert('请填写所有必填字段'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|  |                     pointsDiscountProducts[currentEditId] = { | ||||||
|  |                         ...product, | ||||||
|  |                         stock, | ||||||
|  |                         pointsRequired | ||||||
|  |                     }; | ||||||
|  |                 } else { | ||||||
|  |                     // 积分优惠购模式 | ||||||
|  |                     const stock = parseInt(document.getElementById('modalStockEditDiscount').value); | ||||||
|  |                     const discountAmount = parseFloat(document.getElementById('modalDiscountAmount').value); | ||||||
|  |                     const discountPoints = parseInt(document.getElementById('modalDiscountPoints').value); | ||||||
|  |                      | ||||||
|  |                     if (stock === null || stock === undefined || !discountAmount || !discountPoints) { | ||||||
|  |                         alert('请填写所有必填字段'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|  |                     pointsDiscountProducts[currentEditId] = { | ||||||
|  |                         ...product, | ||||||
|  |                         stock, | ||||||
|  |                         discountAmount, | ||||||
|  |                         discountPoints | ||||||
|  |                     }; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 // 添加模式 | ||||||
|                 const name = document.getElementById('modalProductName').value; |                 const name = document.getElementById('modalProductName').value; | ||||||
|                 const store = document.getElementById('modalStore').value; |                 const store = document.getElementById('modalStore').value; | ||||||
|                 const price = parseFloat(document.getElementById('modalPrice').value); |                 const price = parseFloat(document.getElementById('modalPrice').value); | ||||||
|  | @ -853,13 +1171,9 @@ | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|             if (currentEditId !== null) { |  | ||||||
|                 pointsDiscountProducts[currentEditId] = { |  | ||||||
|                     ...pointsDiscountProducts[currentEditId], |  | ||||||
|                     name, store, price, pointsMode, stock |  | ||||||
|                 }; |  | ||||||
|             } else { |  | ||||||
|                 const newId = String(Math.max(...pointsDiscountProducts.map(p => parseInt(p.id))) + 1).padStart(3, '0'); |                 const newId = String(Math.max(...pointsDiscountProducts.map(p => parseInt(p.id))) + 1).padStart(3, '0'); | ||||||
|  |                 const newSkuId = `1941051427745038360${newId}`; | ||||||
|  |                  | ||||||
|                 pointsDiscountProducts.push({ |                 pointsDiscountProducts.push({ | ||||||
|                     id: newId, |                     id: newId, | ||||||
|                     name,  |                     name,  | ||||||
|  | @ -869,7 +1183,11 @@ | ||||||
|                     originalStatus: '上架', |                     originalStatus: '上架', | ||||||
|                     pointsMode,  |                     pointsMode,  | ||||||
|                     stock, |                     stock, | ||||||
|                     enabled: true |                     enabled: true, | ||||||
|  |                     skuId: newSkuId, | ||||||
|  |                     pointsRequired: pointsMode === '积分换购' ? Math.floor(price * 10) : null, | ||||||
|  |                     discountAmount: pointsMode === '积分优惠购' ? Math.floor(price * 0.2 * 100) / 100 : null, | ||||||
|  |                     discountPoints: pointsMode === '积分优惠购' ? 100 : null | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -877,6 +1195,24 @@ | ||||||
|             renderPointsDiscountProducts(); |             renderPointsDiscountProducts(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // 数量控制函数 | ||||||
|  |         function changeQuantity(inputId, change) { | ||||||
|  |             const input = document.getElementById(inputId); | ||||||
|  |             const currentValue = parseInt(input.value) || 0; | ||||||
|  |             // 对于库存设置允许负数,其他字段保持最小值限制 | ||||||
|  |             if (inputId.includes('Stock')) { | ||||||
|  |                 input.value = currentValue + change; | ||||||
|  |             } else { | ||||||
|  |                 const newValue = Math.max(0, currentValue + change); | ||||||
|  |                 input.value = newValue; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // 更新积分模式函数(用于添加模式) | ||||||
|  |         function updatePointsMode() { | ||||||
|  |             // 预留函数,可以在选择积分模式时进行相关处理 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         document.addEventListener('click', function(e) { |         document.addEventListener('click', function(e) { | ||||||
|             const modal = document.getElementById('productModal'); |             const modal = document.getElementById('productModal'); | ||||||
|             if (e.target === modal) { |             if (e.target === modal) { | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <title>已选择商品</title> |     <title>积分优惠购 - 已选择商品</title> | ||||||
|     <style> |     <style> | ||||||
|         * { |         * { | ||||||
|             margin: 0; |             margin: 0; | ||||||
|  | @ -46,6 +46,15 @@ | ||||||
|             color: #333; |             color: #333; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         .points-type-badge { | ||||||
|  |             background: #52c41a; | ||||||
|  |             color: white; | ||||||
|  |             padding: 4px 8px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             font-size: 12px; | ||||||
|  |             margin-left: 8px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         .close-btn { |         .close-btn { | ||||||
|             width: 24px; |             width: 24px; | ||||||
|             height: 24px; |             height: 24px; | ||||||
|  | @ -179,83 +188,14 @@ | ||||||
|             outline: none; |             outline: none; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         .select-wrapper { |         .price-info { | ||||||
|             position: relative; |             background: #fff7e6; | ||||||
|         } |             border: 1px solid #ffd591; | ||||||
| 
 |  | ||||||
|         .form-select { |  | ||||||
|             width: 100%; |  | ||||||
|             padding: 10px 32px 10px 12px; |  | ||||||
|             border: 1px solid #d9d9d9; |  | ||||||
|             border-radius: 4px; |             border-radius: 4px; | ||||||
|             font-size: 14px; |             padding: 12px; | ||||||
|             background: white; |  | ||||||
|             cursor: pointer; |  | ||||||
|             appearance: none; |  | ||||||
|             -webkit-appearance: none; |  | ||||||
|             -moz-appearance: none; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .form-select:focus { |  | ||||||
|             outline: none; |  | ||||||
|             border-color: #1890ff; |  | ||||||
|             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .select-arrow { |  | ||||||
|             position: absolute; |  | ||||||
|             right: 12px; |  | ||||||
|             top: 50%; |  | ||||||
|             transform: translateY(-50%); |  | ||||||
|             pointer-events: none; |  | ||||||
|             color: #666; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .limit-setting { |  | ||||||
|             display: flex; |  | ||||||
|             gap: 12px; |  | ||||||
|             align-items: flex-end; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .limit-input { |  | ||||||
|             flex: 1; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .limit-select { |  | ||||||
|             flex: 0 0 100px; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .radio-group { |  | ||||||
|             display: flex; |  | ||||||
|             gap: 20px; |  | ||||||
|             margin-top: 8px; |             margin-top: 8px; | ||||||
|         } |             font-size: 13px; | ||||||
| 
 |             color: #d46b08; | ||||||
|         .radio-option { |  | ||||||
|             display: flex; |  | ||||||
|             align-items: center; |  | ||||||
|             cursor: pointer; |  | ||||||
|             position: relative; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .radio-option input[type="radio"] { |  | ||||||
|             margin: 0; |  | ||||||
|             margin-right: 8px; |  | ||||||
|             width: 16px; |  | ||||||
|             height: 16px; |  | ||||||
|             cursor: pointer; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .radio-option label { |  | ||||||
|             font-size: 14px; |  | ||||||
|             color: #333; |  | ||||||
|             cursor: pointer; |  | ||||||
|             margin: 0; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         .exchange-only, |  | ||||||
|         .discount-only { |  | ||||||
|             transition: opacity 0.3s ease; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         .modal-footer { |         .modal-footer { | ||||||
|  | @ -323,7 +263,10 @@ | ||||||
| <body> | <body> | ||||||
|     <div class="modal"> |     <div class="modal"> | ||||||
|         <div class="modal-header"> |         <div class="modal-header"> | ||||||
|             <h2 class="modal-title">已选择商品</h2> |             <h2 class="modal-title"> | ||||||
|  |                 已选择商品 | ||||||
|  |                 <span class="points-type-badge">积分优惠购</span> | ||||||
|  |             </h2> | ||||||
|             <button class="close-btn" onclick="closeModal()">×</button> |             <button class="close-btn" onclick="closeModal()">×</button> | ||||||
|         </div> |         </div> | ||||||
|          |          | ||||||
|  | @ -369,52 +312,21 @@ | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <div class="form-group"> |             <div class="form-group"> | ||||||
|                 <label class="form-label">积分类型 <span class="required">*</span></label> |  | ||||||
|                 <div class="radio-group"> |  | ||||||
|                     <div class="radio-option"> |  | ||||||
|                         <input type="radio" id="pointsDiscount" name="pointsType" value="discount" checked onchange="toggleFieldsByType()"> |  | ||||||
|                         <label for="pointsDiscount">积分优惠购</label> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="radio-option"> |  | ||||||
|                         <input type="radio" id="pointsExchange" name="pointsType" value="exchange" onchange="toggleFieldsByType()"> |  | ||||||
|                         <label for="pointsExchange">积分换购</label> |  | ||||||
|                     </div> |  | ||||||
|                 </div> |  | ||||||
|             </div> |  | ||||||
| 
 |  | ||||||
|             <!-- 积分换购专用字段 --> |  | ||||||
|             <div class="form-group exchange-only"> |  | ||||||
|                 <label class="form-label">兑换所需积分设置 <span class="required">*</span></label> |  | ||||||
|                 <div class="number-input-group"> |  | ||||||
|                     <button class="number-btn" onclick="decreasePoints()">-</button> |  | ||||||
|                     <input type="number" class="number-input" id="pointsInput" value="1" min="1"> |  | ||||||
|                     <button class="number-btn" onclick="increasePoints()">+</button> |  | ||||||
|                 </div> |  | ||||||
|             </div> |  | ||||||
|              |  | ||||||
|             <!-- 最低兑换金额 --> |  | ||||||
|             <div class="form-group exchange-only"> |  | ||||||
|                 <label class="form-label">最低兑换金额(商业支付最少0.01元)</label> |  | ||||||
|                 <div class="input-wrapper"> |  | ||||||
|                     <input type="text" class="form-input" value="0.01元" readonly> |  | ||||||
|                 </div> |  | ||||||
|             </div> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             <!-- 积分优惠购专用字段 --> |  | ||||||
|             <div class="form-group discount-only" style="display: none;"> |  | ||||||
|                 <label class="form-label">优惠购所需积分 <span class="required">*</span></label> |                 <label class="form-label">优惠购所需积分 <span class="required">*</span></label> | ||||||
|                 <div class="number-input-group"> |                 <div class="number-input-group"> | ||||||
|                     <button class="number-btn" onclick="decreaseDiscountPoints()">-</button> |                     <button class="number-btn" onclick="decreaseDiscountPoints()">-</button> | ||||||
|                     <input type="number" class="number-input" id="discountPointsInput" value="1" min="1"> |                     <input type="number" class="number-input" id="discountPointsInput" value="100" min="1"> | ||||||
|                     <button class="number-btn" onclick="increaseDiscountPoints()">+</button> |                     <button class="number-btn" onclick="increaseDiscountPoints()">+</button> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <div class="form-group discount-only" style="display: none;"> |             <div class="form-group"> | ||||||
|                 <label class="form-label">优惠购商品价格 <span class="required">*</span></label> |                 <label class="form-label">优惠购商品价格 <span class="required">*</span></label> | ||||||
|                 <div class="input-wrapper"> |                 <div class="input-wrapper"> | ||||||
|                     <input type="number" class="form-input" id="discountPriceInput" placeholder="请输入优惠购价格" step="0.01" min="0"> |                     <input type="number" class="form-input" id="discountPriceInput" placeholder="请输入优惠购价格" step="0.01" min="0" value="8.80"> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="price-info"> | ||||||
|  |                     提示:用户需要支付 <span id="discountPointsDisplay">100</span> 积分 + ¥<span id="discountPriceDisplay">8.80</span> 即可购买此商品 | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  | @ -426,24 +338,11 @@ | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <script> |     <script> | ||||||
|         // 积分设置(兑换专用) |  | ||||||
|         function increasePoints() { |  | ||||||
|             const input = document.getElementById('pointsInput'); |  | ||||||
|             input.value = parseInt(input.value) + 1; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         function decreasePoints() { |  | ||||||
|             const input = document.getElementById('pointsInput'); |  | ||||||
|             const currentValue = parseInt(input.value); |  | ||||||
|             if (currentValue > 1) { |  | ||||||
|                 input.value = currentValue - 1; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // 优惠购积分设置 |         // 优惠购积分设置 | ||||||
|         function increaseDiscountPoints() { |         function increaseDiscountPoints() { | ||||||
|             const input = document.getElementById('discountPointsInput'); |             const input = document.getElementById('discountPointsInput'); | ||||||
|             input.value = parseInt(input.value) + 1; |             input.value = parseInt(input.value) + 1; | ||||||
|  |             updatePriceInfo(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         function decreaseDiscountPoints() { |         function decreaseDiscountPoints() { | ||||||
|  | @ -451,6 +350,7 @@ | ||||||
|             const currentValue = parseInt(input.value); |             const currentValue = parseInt(input.value); | ||||||
|             if (currentValue > 1) { |             if (currentValue > 1) { | ||||||
|                 input.value = currentValue - 1; |                 input.value = currentValue - 1; | ||||||
|  |                 updatePriceInfo(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -468,59 +368,23 @@ | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // 更新价格提示信息 | ||||||
|  |         function updatePriceInfo() { | ||||||
|  |             const points = document.getElementById('discountPointsInput').value; | ||||||
|  |             const price = document.getElementById('discountPriceInput').value; | ||||||
|  |              | ||||||
|  |             document.getElementById('discountPointsDisplay').textContent = points; | ||||||
|  |             document.getElementById('discountPriceDisplay').textContent = price || '0.00'; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // 关闭弹窗 |         // 关闭弹窗 | ||||||
|         function closeModal() { |         function closeModal() { | ||||||
|             // 这里可以添加关闭弹窗的逻辑 |  | ||||||
|             console.log('关闭弹窗'); |             console.log('关闭弹窗'); | ||||||
|             // 实际应用中可能会隐藏弹窗或者跳转页面 |  | ||||||
|             // window.close(); // 如果是新窗口 |  | ||||||
|             // 或者隐藏弹窗元素 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // 切换字段显示 |  | ||||||
|         function toggleFieldsByType() { |  | ||||||
|             const pointsType = document.querySelector('input[name="pointsType"]:checked').value; |  | ||||||
|             const exchangeFields = document.querySelectorAll('.exchange-only'); |  | ||||||
|             const discountFields = document.querySelectorAll('.discount-only'); |  | ||||||
| 
 |  | ||||||
|             if (pointsType === 'exchange') { |  | ||||||
|                 // 积分换购:显示兑换字段,隐藏优惠购字段 |  | ||||||
|                 exchangeFields.forEach(field => field.style.display = 'block'); |  | ||||||
|                 discountFields.forEach(field => field.style.display = 'none'); |  | ||||||
|             } else if (pointsType === 'discount') { |  | ||||||
|                 // 积分优惠购:隐藏兑换字段,显示优惠购字段 |  | ||||||
|                 exchangeFields.forEach(field => field.style.display = 'none'); |  | ||||||
|                 discountFields.forEach(field => field.style.display = 'block'); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // 确认选择 |         // 确认选择 | ||||||
|         function confirmSelection() { |         function confirmSelection() { | ||||||
|             const pointsType = document.querySelector('input[name="pointsType"]:checked').value; |  | ||||||
|             const stock = document.getElementById('stockInput').value; |             const stock = document.getElementById('stockInput').value; | ||||||
|              |  | ||||||
|             let data = { |  | ||||||
|                 productId: '192401649879976960', |  | ||||||
|                 productName: '黑木耳100g', |  | ||||||
|                 shopName: '牛生蔬菜店', |  | ||||||
|                 skuId: '194105142774503836', |  | ||||||
|                 pointsType: pointsType, |  | ||||||
|                 stock: stock |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             if (pointsType === 'exchange') { |  | ||||||
|                 // 积分换购验证 |  | ||||||
|                 const points = document.getElementById('pointsInput').value; |  | ||||||
|                  |  | ||||||
|                 if (!points || !stock) { |  | ||||||
|                     alert('请填写所有必填项'); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                  |  | ||||||
|                 data.points = points; |  | ||||||
|             } else if (pointsType === 'discount') { |  | ||||||
|                 // 积分优惠购验证 |  | ||||||
|             const discountPoints = document.getElementById('discountPointsInput').value; |             const discountPoints = document.getElementById('discountPointsInput').value; | ||||||
|             const discountPrice = document.getElementById('discountPriceInput').value; |             const discountPrice = document.getElementById('discountPriceInput').value; | ||||||
|              |              | ||||||
|  | @ -529,14 +393,30 @@ | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|                 data.discountPoints = discountPoints; |             if (parseFloat(discountPrice) < 0) { | ||||||
|                 data.discountPrice = discountPrice; |                 alert('优惠购价格不能为负数'); | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|              |              | ||||||
|  |             const data = { | ||||||
|  |                 productId: '192401649879976960', | ||||||
|  |                 productName: '黑木耳', | ||||||
|  |                 shopName: '牛生蔬菜店', | ||||||
|  |                 skuId: '194105142774503836', | ||||||
|  |                 pointsType: 'discount', | ||||||
|  |                 stock: stock, | ||||||
|  |                 discountPoints: discountPoints, | ||||||
|  |                 discountPrice: discountPrice | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|             console.log('提交数据:', data); |             console.log('提交数据:', data); | ||||||
|             alert('设置成功!'); |             alert('积分优惠购设置成功!'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // 监听价格输入变化 | ||||||
|  |         document.getElementById('discountPriceInput').addEventListener('input', updatePriceInfo); | ||||||
|  |         document.getElementById('discountPointsInput').addEventListener('input', updatePriceInfo); | ||||||
|  | 
 | ||||||
|         // 键盘事件处理 |         // 键盘事件处理 | ||||||
|         document.addEventListener('keydown', function(e) { |         document.addEventListener('keydown', function(e) { | ||||||
|             if (e.key === 'Escape') { |             if (e.key === 'Escape') { | ||||||
|  | @ -551,9 +431,9 @@ | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // 页面加载时初始化字段显示 |         // 页面加载时初始化 | ||||||
|         document.addEventListener('DOMContentLoaded', function() { |         document.addEventListener('DOMContentLoaded', function() { | ||||||
|             toggleFieldsByType(); |             updatePriceInfo(); | ||||||
|         }); |         }); | ||||||
|     </script> |     </script> | ||||||
| </body> | </body> | ||||||
|  | @ -0,0 +1,449 @@ | ||||||
|  | <!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, 'Helvetica Neue', Arial, sans-serif; | ||||||
|  |             background-color: rgba(0, 0, 0, 0.5); | ||||||
|  |             display: flex; | ||||||
|  |             justify-content: center; | ||||||
|  |             align-items: center; | ||||||
|  |             min-height: 100vh; | ||||||
|  |             padding: 20px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .modal { | ||||||
|  |             background: white; | ||||||
|  |             border-radius: 8px; | ||||||
|  |             box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); | ||||||
|  |             width: 100%; | ||||||
|  |             max-width: 500px; | ||||||
|  |             position: relative; | ||||||
|  |             overflow: hidden; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .modal-header { | ||||||
|  |             display: flex; | ||||||
|  |             justify-content: space-between; | ||||||
|  |             align-items: center; | ||||||
|  |             padding: 20px 24px; | ||||||
|  |             border-bottom: 1px solid #f0f0f0; | ||||||
|  |             background-color: #fafafa; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .modal-title { | ||||||
|  |             font-size: 18px; | ||||||
|  |             font-weight: 600; | ||||||
|  |             color: #333; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .points-type-badge { | ||||||
|  |             background: #fa8c16; | ||||||
|  |             color: white; | ||||||
|  |             padding: 4px 8px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             font-size: 12px; | ||||||
|  |             margin-left: 8px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .close-btn { | ||||||
|  |             width: 24px; | ||||||
|  |             height: 24px; | ||||||
|  |             border: none; | ||||||
|  |             background: none; | ||||||
|  |             cursor: pointer; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             color: #666; | ||||||
|  |             font-size: 18px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             transition: background-color 0.2s; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .close-btn:hover { | ||||||
|  |             background-color: #f5f5f5; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .modal-content { | ||||||
|  |             padding: 24px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .product-info { | ||||||
|  |             margin-bottom: 24px; | ||||||
|  |             padding: 16px; | ||||||
|  |             background-color: #f8f9fa; | ||||||
|  |             border-radius: 6px; | ||||||
|  |             border: 1px solid #e9ecef; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-row { | ||||||
|  |             display: flex; | ||||||
|  |             margin-bottom: 8px; | ||||||
|  |             font-size: 14px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-row:last-child { | ||||||
|  |             margin-bottom: 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-label { | ||||||
|  |             color: #666; | ||||||
|  |             width: 80px; | ||||||
|  |             flex-shrink: 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .info-value { | ||||||
|  |             color: #333; | ||||||
|  |             flex: 1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .form-group { | ||||||
|  |             margin-bottom: 20px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .form-label { | ||||||
|  |             display: block; | ||||||
|  |             margin-bottom: 8px; | ||||||
|  |             font-size: 14px; | ||||||
|  |             color: #333; | ||||||
|  |             font-weight: 500; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .required { | ||||||
|  |             color: #ff4757; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .input-wrapper { | ||||||
|  |             position: relative; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .form-input { | ||||||
|  |             width: 100%; | ||||||
|  |             padding: 10px 12px; | ||||||
|  |             border: 1px solid #d9d9d9; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             font-size: 14px; | ||||||
|  |             transition: border-color 0.2s; | ||||||
|  |             background-color: #f5f5f5; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .form-input:focus { | ||||||
|  |             outline: none; | ||||||
|  |             border-color: #1890ff; | ||||||
|  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-input-group { | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             border: 1px solid #d9d9d9; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             overflow: hidden; | ||||||
|  |             background: white; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-input-group:focus-within { | ||||||
|  |             border-color: #1890ff; | ||||||
|  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-btn { | ||||||
|  |             width: 32px; | ||||||
|  |             height: 40px; | ||||||
|  |             border: none; | ||||||
|  |             background: #fafafa; | ||||||
|  |             cursor: pointer; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             font-size: 16px; | ||||||
|  |             color: #666; | ||||||
|  |             transition: background-color 0.2s; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-btn:hover { | ||||||
|  |             background-color: #f0f0f0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-btn:disabled { | ||||||
|  |             cursor: not-allowed; | ||||||
|  |             color: #ccc; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .number-input { | ||||||
|  |             flex: 1; | ||||||
|  |             border: none; | ||||||
|  |             padding: 10px 12px; | ||||||
|  |             font-size: 14px; | ||||||
|  |             text-align: center; | ||||||
|  |             outline: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .exchange-info { | ||||||
|  |             background: #fff2e8; | ||||||
|  |             border: 1px solid #ffbb96; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             padding: 12px; | ||||||
|  |             margin-top: 8px; | ||||||
|  |             font-size: 13px; | ||||||
|  |             color: #d4380d; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .exchange-note { | ||||||
|  |             background: #e6f7ff; | ||||||
|  |             border: 1px solid #91d5ff; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             padding: 12px; | ||||||
|  |             margin-top: 8px; | ||||||
|  |             font-size: 13px; | ||||||
|  |             color: #0050b3; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .modal-footer { | ||||||
|  |             padding: 16px 24px; | ||||||
|  |             border-top: 1px solid #f0f0f0; | ||||||
|  |             display: flex; | ||||||
|  |             gap: 12px; | ||||||
|  |             justify-content: flex-end; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .btn { | ||||||
|  |             padding: 8px 24px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             font-size: 14px; | ||||||
|  |             cursor: pointer; | ||||||
|  |             transition: all 0.2s; | ||||||
|  |             border: 1px solid; | ||||||
|  |             min-width: 80px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .btn-cancel { | ||||||
|  |             background: white; | ||||||
|  |             color: #666; | ||||||
|  |             border-color: #d9d9d9; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .btn-cancel:hover { | ||||||
|  |             background: #f5f5f5; | ||||||
|  |             border-color: #bfbfbf; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .btn-primary { | ||||||
|  |             background: #1890ff; | ||||||
|  |             color: white; | ||||||
|  |             border-color: #1890ff; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .btn-primary:hover { | ||||||
|  |             background: #40a9ff; | ||||||
|  |             border-color: #40a9ff; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @media (max-width: 480px) { | ||||||
|  |             .modal { | ||||||
|  |                 margin: 0; | ||||||
|  |                 border-radius: 0; | ||||||
|  |                 height: 100vh; | ||||||
|  |                 max-width: none; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             .modal-content { | ||||||
|  |                 padding: 20px; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             .modal-footer { | ||||||
|  |                 padding: 16px 20px; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             .btn { | ||||||
|  |                 flex: 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     </style> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div class="modal"> | ||||||
|  |         <div class="modal-header"> | ||||||
|  |             <h2 class="modal-title"> | ||||||
|  |                 已选择商品 | ||||||
|  |                 <span class="points-type-badge">积分换购</span> | ||||||
|  |             </h2> | ||||||
|  |             <button class="close-btn" onclick="closeModal()">×</button> | ||||||
|  |         </div> | ||||||
|  |          | ||||||
|  |         <div class="modal-content"> | ||||||
|  |             <div class="product-info"> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">商品ID:</span> | ||||||
|  |                     <span class="info-value">192401649879976960</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">商品名称:</span> | ||||||
|  |                     <span class="info-value">黑木耳</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">归属摊位:</span> | ||||||
|  |                     <span class="info-value">牛生蔬菜店</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">规格名称:</span> | ||||||
|  |                     <span class="info-value">小份</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">SKU-ID:</span> | ||||||
|  |                     <span class="info-value">194105142774503836</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">商品原价:</span> | ||||||
|  |                     <span class="info-value">¥12.80</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="info-row"> | ||||||
|  |                     <span class="info-label">当前剩余库存:</span> | ||||||
|  |                     <span class="info-value">50</span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <div class="form-group"> | ||||||
|  |                 <label class="form-label">添加库存(负数代表减少库存) <span class="required">*</span></label> | ||||||
|  |                 <div class="number-input-group"> | ||||||
|  |                     <button class="number-btn" onclick="decreaseStock()">-</button> | ||||||
|  |                     <input type="number" class="number-input" id="stockInput" value="10" min="0"> | ||||||
|  |                     <button class="number-btn" onclick="increaseStock()">+</button> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <div class="form-group"> | ||||||
|  |                 <label class="form-label">兑换所需积分设置 <span class="required">*</span></label> | ||||||
|  |                 <div class="number-input-group"> | ||||||
|  |                     <button class="number-btn" onclick="decreasePoints()">-</button> | ||||||
|  |                     <input type="number" class="number-input" id="pointsInput" value="1280" min="1"> | ||||||
|  |                     <button class="number-btn" onclick="increasePoints()">+</button> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="exchange-info"> | ||||||
|  |                     用户需要支付 <span id="pointsDisplay">1280</span> 积分 + ¥0.01 即可兑换此商品 | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |              | ||||||
|  |             <div class="form-group"> | ||||||
|  |                 <label class="form-label">最低兑换金额(商业支付最少0.01元)</label> | ||||||
|  |                 <div class="input-wrapper"> | ||||||
|  |                     <input type="text" class="form-input" value="¥0.01" readonly> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="exchange-note"> | ||||||
|  |                     提示:为符合商业支付规范,用户在使用积分兑换时仍需支付最少0.01元的金额 | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  | 
 | ||||||
|  |         <div class="modal-footer"> | ||||||
|  |             <button class="btn btn-cancel" onclick="closeModal()">取消</button> | ||||||
|  |             <button class="btn btn-primary" onclick="confirmSelection()">确认</button> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |         // 积分设置(兑换专用) | ||||||
|  |         function increasePoints() { | ||||||
|  |             const input = document.getElementById('pointsInput'); | ||||||
|  |             input.value = parseInt(input.value) + 10; | ||||||
|  |             updateExchangeInfo(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         function decreasePoints() { | ||||||
|  |             const input = document.getElementById('pointsInput'); | ||||||
|  |             const currentValue = parseInt(input.value); | ||||||
|  |             if (currentValue > 1) { | ||||||
|  |                 input.value = Math.max(1, currentValue - 10); | ||||||
|  |                 updateExchangeInfo(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 库存设置 | ||||||
|  |         function increaseStock() { | ||||||
|  |             const input = document.getElementById('stockInput'); | ||||||
|  |             input.value = parseInt(input.value) + 1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         function decreaseStock() { | ||||||
|  |             const input = document.getElementById('stockInput'); | ||||||
|  |             const currentValue = parseInt(input.value); | ||||||
|  |             if (currentValue > 0) { | ||||||
|  |                 input.value = currentValue - 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 更新兑换信息提示 | ||||||
|  |         function updateExchangeInfo() { | ||||||
|  |             const points = document.getElementById('pointsInput').value; | ||||||
|  |             document.getElementById('pointsDisplay').textContent = points; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 关闭弹窗 | ||||||
|  |         function closeModal() { | ||||||
|  |             console.log('关闭弹窗'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 确认选择 | ||||||
|  |         function confirmSelection() { | ||||||
|  |             const stock = document.getElementById('stockInput').value; | ||||||
|  |             const points = document.getElementById('pointsInput').value; | ||||||
|  |              | ||||||
|  |             if (!points || !stock) { | ||||||
|  |                 alert('请填写所有必填项'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (parseInt(points) < 1) { | ||||||
|  |                 alert('兑换积分不能小于1'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             const data = { | ||||||
|  |                 productId: '192401649879976960', | ||||||
|  |                 productName: '黑木耳', | ||||||
|  |                 shopName: '牛生蔬菜店', | ||||||
|  |                 skuId: '194105142774503836', | ||||||
|  |                 pointsType: 'exchange', | ||||||
|  |                 stock: stock, | ||||||
|  |                 points: points, | ||||||
|  |                 minPayment: 0.01 | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             console.log('提交数据:', data); | ||||||
|  |             alert('积分换购设置成功!'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 监听积分输入变化 | ||||||
|  |         document.getElementById('pointsInput').addEventListener('input', updateExchangeInfo); | ||||||
|  | 
 | ||||||
|  |         // 键盘事件处理 | ||||||
|  |         document.addEventListener('keydown', function(e) { | ||||||
|  |             if (e.key === 'Escape') { | ||||||
|  |                 closeModal(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // 点击背景关闭弹窗 | ||||||
|  |         document.addEventListener('click', function(e) { | ||||||
|  |             if (e.target === document.body) { | ||||||
|  |                 closeModal(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // 页面加载时初始化 | ||||||
|  |         document.addEventListener('DOMContentLoaded', function() { | ||||||
|  |             updateExchangeInfo(); | ||||||
|  |         }); | ||||||
|  |     </script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
		Loading…
	
		Reference in New Issue