(function () { 'use strict'; var Api = function () { return window.AdminApi; }; var Ui = function () { return window.AdminUi; }; var I = function () { return window.AdminI18n; }; var Form = function () { return window.AdminForm; }; function activeBadge(v) { var on = v === true || parseInt(v, 10) === 1; return I().badgeStatus(on ? 'active' : 'disabled'); } function recBadge(v) { if (!v) return '—'; return '推荐'; } function isFreePlan(plan) { return plan && plan.code === 'free'; } function isPaidMemberPlan(plan) { return plan && plan.code !== 'free' && plan.price_cents > 0; } function editableFeatures(plan) { if (plan.features_editable && plan.features_editable.length) { return plan.features_editable.slice(); } var lines = plan.features || []; return lines.filter(function (l) { return l.indexOf('订阅有效期') < 0 && l.indexOf('订阅周期') < 0 && l.indexOf('到期') < 0; }); } function featureRowsHtml(lines) { var items = lines && lines.length ? lines : ['']; return items.map(function (text) { return '
' + '' + '
'; }).join(''); } function bindFeatureEditor() { var list = document.getElementById('peFeatures'); var addBtn = document.getElementById('peFeatureAdd'); if (!list) return; function bindDel(btn) { if (!btn || btn.dataset.bound) return; btn.dataset.bound = '1'; btn.onclick = function () { var rows = list.querySelectorAll('.soon-admin-feature-row'); if (rows.length <= 1) { var inp = list.querySelector('.soon-admin-feature-input'); if (inp) inp.value = ''; return; } var row = btn.closest('.soon-admin-feature-row'); if (row) row.remove(); }; } list.querySelectorAll('.soon-admin-feature-del').forEach(bindDel); if (addBtn && !addBtn.dataset.bound) { addBtn.dataset.bound = '1'; addBtn.onclick = function () { var row = document.createElement('div'); row.className = 'soon-admin-feature-row'; row.innerHTML = '' + ''; list.appendChild(row); bindDel(row.querySelector('.soon-admin-feature-del')); row.querySelector('.soon-admin-feature-input').focus(); }; } } function collectFeatures() { var lines = []; document.querySelectorAll('#peFeatures .soon-admin-feature-input').forEach(function (inp) { var t = inp.value.trim(); if (t) lines.push(t); }); return lines; } function periodHint(plan) { if (isFreePlan(plan)) return ''; var days = parseInt(Ui().el('peDays') && Ui().el('peDays').value, 10); if (!days || days <= 0) days = plan.duration_days || 0; if (days <= 0) return '付费方案保存后将自动追加订阅周期说明。'; var label = days >= 365 ? '1 年' : (days === 90 ? '1 季' : (days >= 30 && days % 30 === 0 ? (days / 30) + ' 个月' : days + ' 天')); return '保存后将自动追加订阅周期说明(' + label + '),用户端卡片中不展示该行'; } function openEditModal(plan) { var free = isFreePlan(plan); var paid = isPaidMemberPlan(plan); var features = editableFeatures(plan); var basicPanel = Form().panel('基本信息', Form().field('代码', '') + Form().field('名称', Form().input('peName', { value: plan.name })) + Form().field('简介', Form().input('peDesc', { value: plan.description || '' })) ); var pricePanel = Form().panel('价格与周期', '
' + Form().field('价格(元)', Form().input('pePriceYuan', { type: 'number', value: (plan.price_cents / 100).toFixed(2), disabled: free, })) + Form().field('有效天数', Form().input('peDays', { type: 'number', value: plan.duration_days }), free ? '免费版填 0' : '月付 30 / 季付 90 / 年付 365') + Form().field('排序', Form().input('peSort', { type: 'number', value: plan.sort_order })) + '
' + '
' + '' + '' + (paid ? '' : '') + '
' ); var quotaPanel = Form().panel('云端配额', '
' + Form().field('存储(MB)', Form().input('peQuota', { type: 'number', value: plan.quota_mb })) + Form().field('文件数上限', Form().input('peMaxFiles', { type: 'number', value: plan.max_files })) + '
', '云端存储与文件数量上限;预览/保存/导出仍受订阅状态约束。' ); var benefitTitle = free ? '免费版展示' : '订阅包含'; var benefitHint = free ? '展示在会员中心免费版区域;补充说明写在简介中。' : periodHint(plan); var benefitPanel = Form().panel(benefitTitle, '
' + featureRowsHtml(features) + '
' + '' + (benefitHint ? '

' + I().esc(benefitHint) + '

' : '') ); var form = '
' + basicPanel + pricePanel + quotaPanel + benefitPanel + Form().actions('保存', 'adminModalSave') + '
'; Ui().openFormModal((free ? '免费版' : '订阅方案') + ' · ' + plan.name, form, function () { var name = Ui().el('peName').value.trim(); if (!name) { soonToast('名称不能为空', 'warn'); return false; } var featureLines = collectFeatures(); if (!featureLines.length) { soonToast('请至少填写一条权益', 'warn'); return false; } var yuan = free ? 0 : (parseFloat(Ui().el('pePriceYuan').value) || 0); var body = { code: plan.code, name: name, description: Ui().el('peDesc').value.trim(), price_cents: Math.round(yuan * 100), quota_mb: parseInt(Ui().el('peQuota').value, 10) || 0, max_files: parseInt(Ui().el('peMaxFiles').value, 10) || 0, duration_days: parseInt(Ui().el('peDays').value, 10) || 0, sort_order: parseInt(Ui().el('peSort').value, 10) || 0, is_recommended: free ? 0 : (Ui().el('peRec').checked ? 1 : 0), is_active: Ui().el('peActive').checked ? 1 : 0, features: featureLines, sync_member_benefits: paid && Ui().el('peSync') && Ui().el('peSync').checked ? 1 : 0, }; return Api().postJson('plans', body).then(function (r) { if (r) { layer.closeAll(); soonToast('已保存', 'success'); render(); } }); }, { area: ['640px', '72vh'], success: function () { bindFeatureEditor(); var daysEl = Ui().el('peDays'); var hintEl = document.querySelector('.soon-admin-form-hint--tight'); if (daysEl && hintEl && paid) { daysEl.oninput = function () { hintEl.textContent = periodHint(plan); }; } }, }); } function featureSummary(plan) { var n = editableFeatures(plan).length; return n > 0 ? n + ' 条' : '—'; } function render() { var panel = Ui().el('panel-plans'); if (!panel) return; panel.innerHTML = '
' + Ui().pageHeader('订阅方案', '配置价格、周期、配额与用户端展示文案') + Ui().skeletonTable() + '
'; Api().get('plans').then(function (j) { if (!j) return; var items = j.data.items || []; var rows = items.map(function (p) { return '' + I().esc(p.code) + '' + I().esc(p.name) + '' + I().formatCents(p.price_cents) + '' + featureSummary(p) + '' + p.quota_mb + ' MB' + (p.duration_days > 0 ? p.duration_days + ' 天' : '永久') + '' + recBadge(p.is_recommended) + '' + activeBadge(p.is_active) + ''; }).join(''); panel.innerHTML = '
' + Ui().pageHeader('订阅方案', '配置价格、周期、配额与用户端展示文案') + Ui().dataTable( ['代码', '名称', '价格', '权益', '存储', '有效期', '推荐', '状态', '操作'], rows ) + '
'; var planMap = {}; items.forEach(function (p) { planMap[p.code] = p; }); panel.querySelectorAll('.plan-edit').forEach(function (btn) { btn.onclick = function () { var code = btn.closest('tr').dataset.code; if (planMap[code]) openEditModal(planMap[code]); }; }); }); } window.AdminViews = window.AdminViews || {}; window.AdminViews.plans = { render: render }; })();