170 lines
5.7 KiB
JavaScript
170 lines
5.7 KiB
JavaScript
// SaaSShop Admin JS
|
||
// 说明:用于增强总台管理的运营交互体验(尽量保持小而可治理)。
|
||
// 原则:不引入复杂构建链;以渐进增强为主,页面无 JS 也应可用。
|
||
|
||
(function () {
|
||
if (window.__SAASSHOP_ADMIN_JS__) {
|
||
return;
|
||
}
|
||
window.__SAASSHOP_ADMIN_JS__ = true;
|
||
|
||
function qs(sel, root) {
|
||
return (root || document).querySelector(sel);
|
||
}
|
||
|
||
// 续费缺订阅治理:绑定成功后自动滚动到顶部提示区(让运营立刻看到 success/warning/error)
|
||
// 说明:由后端 redirect url 追加 attached_subscription=1 触发。
|
||
if (window.location && window.location.search && window.location.search.indexOf('attached_subscription=1') >= 0) {
|
||
try {
|
||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
} catch (e) {
|
||
window.scrollTo(0, 0);
|
||
}
|
||
}
|
||
|
||
// 通用:表单提交后禁用按钮,避免运营重复点击造成重复请求
|
||
// 用法:form 标记 data-action="disable-on-submit"。
|
||
(function () {
|
||
var forms = document.querySelectorAll('form[data-action="disable-on-submit"]');
|
||
if (!forms || forms.length === 0) {
|
||
return;
|
||
}
|
||
|
||
forms.forEach(function (form) {
|
||
form.addEventListener('submit', function () {
|
||
try {
|
||
var btns = form.querySelectorAll('button, input[type="submit"]');
|
||
btns.forEach(function (b) {
|
||
b.disabled = true;
|
||
// 尽量不改文案(避免影响断言/文案口径);只做禁用
|
||
});
|
||
} catch (e) {}
|
||
});
|
||
});
|
||
})();
|
||
|
||
// 通用:折叠面板(collapsible)记忆展开状态(localStorage)
|
||
// 用法:<details data-role="collapsible" data-storage-key="xxx">
|
||
(function () {
|
||
var nodes = document.querySelectorAll('details[data-role="collapsible"][data-storage-key]');
|
||
if (!nodes || nodes.length === 0) {
|
||
return;
|
||
}
|
||
|
||
nodes.forEach(function (d) {
|
||
var key = d.getAttribute('data-storage-key');
|
||
if (!key) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
var saved = window.localStorage.getItem(key);
|
||
if (saved === 'open') {
|
||
d.open = true;
|
||
} else if (saved === 'closed') {
|
||
d.open = false;
|
||
}
|
||
} catch (e) {}
|
||
|
||
d.addEventListener('toggle', function () {
|
||
try {
|
||
window.localStorage.setItem(key, d.open ? 'open' : 'closed');
|
||
} catch (e) {}
|
||
});
|
||
});
|
||
})();
|
||
|
||
// 通用:将后端 flash 信息同步到 toast(更像 Ant Design Pro 的反馈方式)
|
||
// 说明:渐进增强。页面仍保留原本的提示块,不依赖 JS。
|
||
(function () {
|
||
var container = qs('[data-role="toast-container"]');
|
||
if (!container) {
|
||
return;
|
||
}
|
||
|
||
var flashNodes = document.querySelectorAll('[data-flash]');
|
||
if (!flashNodes || flashNodes.length === 0) {
|
||
return;
|
||
}
|
||
|
||
function createToast(type, text) {
|
||
var div = document.createElement('div');
|
||
div.className = 'toast toast-' + type;
|
||
div.setAttribute('role', 'status');
|
||
|
||
var content = document.createElement('div');
|
||
content.className = 'toast-content';
|
||
content.textContent = text;
|
||
|
||
var close = document.createElement('button');
|
||
close.type = 'button';
|
||
close.className = 'toast-close';
|
||
close.textContent = '×';
|
||
close.addEventListener('click', function () {
|
||
try {
|
||
container.removeChild(div);
|
||
} catch (e) {}
|
||
});
|
||
|
||
div.appendChild(content);
|
||
div.appendChild(close);
|
||
return div;
|
||
}
|
||
|
||
flashNodes.forEach(function (node) {
|
||
var type = node.getAttribute('data-flash') || 'info';
|
||
var text = (node.textContent || '').trim();
|
||
if (!text) {
|
||
return;
|
||
}
|
||
|
||
container.appendChild(createToast(type, text));
|
||
});
|
||
|
||
// 自动消失(success/warning),error 保留更久
|
||
setTimeout(function () {
|
||
try {
|
||
var toasts = container.querySelectorAll('.toast');
|
||
toasts.forEach(function (t) {
|
||
var cls = t.className || '';
|
||
var isError = cls.indexOf('toast-error') >= 0;
|
||
if (!isError) {
|
||
container.removeChild(t);
|
||
}
|
||
});
|
||
} catch (e) {}
|
||
}, 4500);
|
||
|
||
setTimeout(function () {
|
||
try {
|
||
var toasts = container.querySelectorAll('.toast');
|
||
toasts.forEach(function (t) {
|
||
try {
|
||
container.removeChild(t);
|
||
} catch (e) {}
|
||
});
|
||
} catch (e) {}
|
||
}, 9000);
|
||
})();
|
||
|
||
// 续费缺订阅治理:订单详情页“绑定订阅ID”输入框,小交互增强:
|
||
// - 输入后按 Enter 直接提交
|
||
// - 自动聚焦,减少点击
|
||
var attachInput = qs('#attach_site_subscription_id');
|
||
if (attachInput) {
|
||
try {
|
||
attachInput.focus();
|
||
} catch (e) {}
|
||
|
||
attachInput.addEventListener('keydown', function (e) {
|
||
if (e && (e.key === 'Enter' || e.keyCode === 13)) {
|
||
var form = attachInput.form;
|
||
if (form) {
|
||
e.preventDefault();
|
||
form.submit();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
})();
|