| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- // 充值与货币管理模块
- class CurrencyManager {
- constructor(options = {}) {
- this.apiBaseUrl = options.apiBaseUrl || 'http://localhost:3000';
-
- this.packages = [
- { points: 100, bonus: 20, price: 5 },
- { points: 1000, bonus: 200, price: 50 },
- { points: 10000, bonus: 800, price: 500 }
- ];
-
- // 保存原始值用于比较
- this.originalPackages = [];
-
- this.init();
- }
- init() {
- this.bindEvents();
- this.loadSettings();
- }
- bindEvents() {
- const addBtn = document.getElementById('addBtn');
- if (addBtn) {
- addBtn.addEventListener('click', () => this.addPackage());
- }
- }
- async loadSettings() {
- try {
- const response = await fetch(`${this.apiBaseUrl}/api/admin/currency/settings`);
- if (response.ok) {
- const result = await response.json();
- if (result.success && result.packages) {
- this.packages = result.packages;
- }
- }
- } catch (error) {
- console.log('[CurrencyManager] 使用默认设置');
- }
-
- // 深拷贝保存原始值
- this.originalPackages = JSON.parse(JSON.stringify(this.packages));
- this.render();
- }
- render() {
- this.renderPackages();
- this.renderPreview();
- }
- renderPackages() {
- const list = document.getElementById('packageList');
- if (!list) return;
- list.innerHTML = this.packages.map((pkg, i) => `
- <div class="package-item" data-index="${i}">
- <div class="package-index">${i + 1}</div>
- <div class="package-fields">
- <div class="package-field">
- <label>价格</label>
- <span class="unit">¥</span>
- <input type="number" value="${pkg.price}" data-field="price" min="0.01" step="0.01">
- </div>
- <div class="package-field">
- <label>基础</label>
- <input type="number" value="${pkg.points}" data-field="points" min="1">
- <span class="unit">Ani币</span>
- </div>
- <div class="package-field">
- <label>赠送</label>
- <input type="number" value="${pkg.bonus}" data-field="bonus" min="0">
- <span class="unit">Ani币</span>
- </div>
- <div class="package-total">= ${pkg.points + pkg.bonus} Ani币</div>
- </div>
- <div class="package-actions">
- <button class="btn-confirm" data-index="${i}" title="确认修改">✓</button>
- <button class="btn-remove" data-index="${i}" title="删除">×</button>
- </div>
- </div>
- `).join('');
- // 绑定输入事件
- list.querySelectorAll('input').forEach(input => {
- input.addEventListener('input', (e) => this.onInputChange(e));
- });
- // 绑定确认按钮
- list.querySelectorAll('.btn-confirm').forEach(btn => {
- btn.addEventListener('click', (e) => {
- const index = parseInt(e.target.dataset.index);
- this.savePackage(index);
- });
- });
- // 绑定删除按钮
- list.querySelectorAll('.btn-remove').forEach(btn => {
- btn.addEventListener('click', (e) => {
- const index = parseInt(e.target.dataset.index);
- this.removePackage(index);
- });
- });
- }
- onInputChange(e) {
- const item = e.target.closest('.package-item');
- const index = parseInt(item.dataset.index);
- const field = e.target.dataset.field;
- const value = parseFloat(e.target.value) || 0;
-
- this.packages[index][field] = value;
-
- // 更新总计显示
- const pkg = this.packages[index];
- const totalEl = item.querySelector('.package-total');
- if (totalEl) {
- totalEl.textContent = `= ${pkg.points + pkg.bonus} Ani币`;
- }
-
- // 检查是否有变化,显示确认按钮
- const confirmBtn = item.querySelector('.btn-confirm');
- const original = this.originalPackages[index];
- const hasChange = !original ||
- pkg.price !== original.price ||
- pkg.points !== original.points ||
- pkg.bonus !== original.bonus;
-
- if (confirmBtn) {
- confirmBtn.classList.toggle('show', hasChange);
- }
-
- this.renderPreview();
- }
- renderPreview() {
- const preview = document.getElementById('preview');
- if (!preview) return;
- preview.innerHTML = this.packages.map(pkg => `
- <div class="preview-card">
- <div class="points">${pkg.points} Ani币</div>
- <div class="card-bottom">
- ${pkg.bonus > 0 ? `<div class="bonus">送 ${pkg.bonus} Ani币</div>` : ''}
- <div class="price">¥${pkg.price}</div>
- </div>
- </div>
- `).join('');
- }
- addPackage() {
- const last = this.packages[this.packages.length - 1] || { points: 100, bonus: 0, price: 10 };
- const newPkg = {
- points: last.points * 2,
- bonus: Math.floor(last.bonus * 1.5),
- price: last.price * 2
- };
- this.packages.push(newPkg);
- this.originalPackages.push(null); // 新增的没有原始值
- this.render();
-
- // 显示新增项的确认按钮
- setTimeout(() => {
- const items = document.querySelectorAll('.package-item');
- const lastItem = items[items.length - 1];
- if (lastItem) {
- const confirmBtn = lastItem.querySelector('.btn-confirm');
- if (confirmBtn) confirmBtn.classList.add('show');
- }
- }, 0);
- }
- async removePackage(index) {
- if (this.packages.length <= 1) {
- this.showMsg('至少保留一个套餐', 'error');
- return;
- }
-
- this.packages.splice(index, 1);
- this.originalPackages.splice(index, 1);
-
- // 保存到服务器
- await this.saveAll();
- this.render();
- }
- async savePackage(index) {
- await this.saveAll();
-
- // 更新原始值
- this.originalPackages[index] = JSON.parse(JSON.stringify(this.packages[index]));
-
- // 隐藏确认按钮
- const items = document.querySelectorAll('.package-item');
- const item = items[index];
- if (item) {
- const confirmBtn = item.querySelector('.btn-confirm');
- if (confirmBtn) confirmBtn.classList.remove('show');
- }
- }
- async saveAll() {
- try {
- const response = await fetch(`${this.apiBaseUrl}/api/admin/currency/settings`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ packages: this.packages })
- });
- const result = await response.json();
-
- if (result.success) {
- this.showMsg('保存成功', 'success');
- // 更新所有原始值
- this.originalPackages = JSON.parse(JSON.stringify(this.packages));
- } else {
- this.showMsg('保存失败: ' + (result.message || ''), 'error');
- }
- } catch (error) {
- this.showMsg('保存失败', 'error');
- }
- }
- showMsg(text, type) {
- const msgBox = document.getElementById('msgBox');
- if (msgBox) {
- msgBox.textContent = text;
- msgBox.className = 'msg ' + type;
- msgBox.style.display = 'block';
- setTimeout(() => {
- msgBox.style.display = 'none';
- }, 2000);
- }
- }
- }
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = CurrencyManager;
- } else {
- window.CurrencyManager = CurrencyManager;
- }
|