| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // 商品定价管理模块
- class ProductPricingManager {
- constructor(options = {}) {
- this.apiBaseUrl = options.apiBaseUrl || 'http://localhost:3000';
-
- // 默认商品配置
- this.products = [
- { id: 'vip-matting', name: 'VIP抠图', desc: '使用VIP服务进行图片抠图', price: 0 },
- { id: 'ai-generate', name: 'AI生图', desc: '使用AI生成图片', price: 0 }
- ];
-
- this.init();
- }
- init() {
- this.bindEvents();
- this.loadSettings();
- }
- bindEvents() {
- const productList = document.getElementById('productList');
- if (productList) {
- productList.addEventListener('input', (e) => {
- if (e.target.classList.contains('price-input')) {
- const productId = e.target.dataset.productId;
- const confirmBtn = e.target.closest('.product-item').querySelector('.btn-confirm');
- if (confirmBtn) {
- confirmBtn.classList.add('show');
- }
- }
- });
- productList.addEventListener('click', (e) => {
- if (e.target.closest('.btn-confirm')) {
- const button = e.target.closest('.btn-confirm');
- const productId = button.dataset.productId;
- this.saveProduct(productId);
- }
- });
- }
- }
- async loadSettings() {
- try {
- const response = await fetch(`${this.apiBaseUrl}/api/admin/product-pricing/settings`);
- if (response.ok) {
- const result = await response.json();
- if (result.success && result.products) {
- // 更新产品价格,保持默认产品结构
- result.products.forEach(serverProduct => {
- const localProduct = this.products.find(p => p.id === serverProduct.id);
- if (localProduct) {
- localProduct.price = serverProduct.price || 0;
- }
- });
- }
- }
- } catch (error) {
- console.log('[ProductPricingManager] 使用默认设置');
- }
-
- this.render();
- }
- render() {
- const list = document.getElementById('productList');
- if (!list) return;
- list.innerHTML = this.products.map(product => `
- <div class="product-item" data-product-id="${product.id}">
- <div class="product-info">
- <div class="product-name">${product.name}</div>
- <div class="product-desc">${product.desc}</div>
- </div>
- <div class="product-price">
- <span class="price-label">价格</span>
- <div class="price-input-wrapper">
- <input type="text" class="price-input" value="${product.price}"
- data-product-id="${product.id}"
- data-original="${product.price}">
- <span class="price-unit">Ani币</span>
- </div>
- <button class="btn-confirm" data-product-id="${product.id}" title="确认修改">✓</button>
- </div>
- </div>
- `).join('');
- }
- async saveProduct(productId) {
- const product = this.products.find(p => p.id === productId);
- if (!product) return;
- const input = document.querySelector(`.price-input[data-product-id="${productId}"]`);
- if (!input) return;
- const newPrice = parseFloat(input.value);
- if (isNaN(newPrice) || newPrice < 0) {
- this.showMessage('价格必须是大于等于0的数字', 'error');
- return;
- }
- const originalPrice = parseFloat(input.dataset.original);
- if (newPrice === originalPrice) {
- const confirmBtn = input.closest('.product-item').querySelector('.btn-confirm');
- if (confirmBtn) {
- confirmBtn.classList.remove('show');
- }
- return;
- }
- try {
- const response = await fetch(`${this.apiBaseUrl}/api/admin/product-pricing/settings`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- productId: productId,
- price: newPrice
- })
- });
- const result = await response.json();
- if (result.success) {
- product.price = newPrice;
- input.dataset.original = newPrice.toString();
- const confirmBtn = input.closest('.product-item').querySelector('.btn-confirm');
- if (confirmBtn) {
- confirmBtn.classList.remove('show');
- }
- this.showMessage('价格更新成功', 'success');
- } else {
- this.showMessage(result.message || '保存失败', 'error');
- }
- } catch (error) {
- console.error('[ProductPricingManager] 保存失败:', error);
- this.showMessage('保存失败,请稍后重试', 'error');
- }
- }
- showMessage(message, type) {
- const msgBox = document.getElementById('msgBox');
- if (msgBox) {
- msgBox.textContent = message;
- msgBox.className = `msg ${type}`;
- setTimeout(() => {
- msgBox.className = 'msg';
- }, 3000);
- }
- }
- }
|