(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 };
})();