302 lines
13 KiB
JavaScript
302 lines
13 KiB
JavaScript
/**
|
||
* Reference-style paid download resource editor for the front submit page.
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
(function () {
|
||
'use strict';
|
||
|
||
var fields = ['url', 'attachment_id', 'extract_code', 'copy_key', 'copy_val', 'label', 'class'];
|
||
var buttonClasses = [
|
||
'',
|
||
'c-red', 'c-yellow', 'c-cyan', 'c-blue', 'c-green', 'c-purple',
|
||
'b-red', 'b-yellow', 'b-cyan', 'b-blue', 'b-green', 'b-purple',
|
||
'jb-red', 'jb-pink', 'jb-yellow', 'jb-cyan', 'jb-blue', 'jb-green', 'jb-purple',
|
||
'jb-vip1', 'jb-vip2',
|
||
];
|
||
|
||
function escapeHtml(value) {
|
||
return String(value || '')
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"')
|
||
.replace(/'/g, ''');
|
||
}
|
||
|
||
function validHttpUrl(value) {
|
||
try {
|
||
var url = new URL(String(value || '').trim(), window.location.href);
|
||
return /^(https?:)$/i.test(url.protocol) ? url.href : '';
|
||
} catch (error) {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
function createItem() {
|
||
var item = document.createElement('div');
|
||
item.className = 'flex ac jsb lists-item';
|
||
item.setAttribute('data-pay-download-item', '');
|
||
|
||
var edit = document.createElement('button');
|
||
edit.type = 'button';
|
||
edit.className = 'flex1 name-link pay-dawnload-add-edit';
|
||
edit.setAttribute('data-pay-download-edit', '');
|
||
item.appendChild(edit);
|
||
|
||
var remove = document.createElement('button');
|
||
remove.type = 'button';
|
||
remove.className = 'pay-dawnload-add-delete em12 ml10 hollow but cir c-red';
|
||
remove.setAttribute('data-pay-download-remove', '');
|
||
remove.setAttribute('aria-label', '删除资源');
|
||
remove.innerHTML = '<i class="fa far fa-trash-alt" aria-hidden="true"></i>';
|
||
item.appendChild(remove);
|
||
|
||
var hidden = document.createElement('div');
|
||
hidden.className = 'hidden-input';
|
||
fields.forEach(function (field) {
|
||
var input = document.createElement('input');
|
||
input.type = 'hidden';
|
||
input.setAttribute('data-pay-download-field', field);
|
||
hidden.appendChild(input);
|
||
});
|
||
item.appendChild(hidden);
|
||
|
||
return item;
|
||
}
|
||
|
||
function init(options) {
|
||
var root = options && options.root;
|
||
if (!root || root.getAttribute('data-pay-download-ready') === '1') {
|
||
return;
|
||
}
|
||
|
||
var list = root.querySelector('[data-pay-download-list]');
|
||
var addButton = root.querySelector('[data-pay-download-add]');
|
||
if (!list || !addButton) {
|
||
return;
|
||
}
|
||
|
||
root.setAttribute('data-pay-download-ready', '1');
|
||
var cfg = window.aksrtSubmitData || {};
|
||
var i18n = cfg.i18n || {};
|
||
var activeItem = null;
|
||
var previousFocus = null;
|
||
var modal = document.createElement('div');
|
||
modal.className = 'aksrt-editor-media pay-dawnload-edit-modal';
|
||
modal.hidden = true;
|
||
modal.innerHTML =
|
||
'<button type="button" class="aksrt-editor-media__backdrop" data-pay-download-close tabindex="-1" aria-label="' +
|
||
escapeHtml(i18n.close || '关闭') + '"></button>' +
|
||
'<div class="aksrt-editor-media__dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-pay-download-title" tabindex="-1">' +
|
||
'<button type="button" class="aksrt-editor-media__close" data-pay-download-close aria-label="' +
|
||
escapeHtml(i18n.close || '关闭') + '">×</button>' +
|
||
'<div class="pay-dawnload-edit-content">' +
|
||
'<div class="mb20"><b class="modal-title flex ac"><span class="toggle-radius mr10 b-theme"><i class="fa fas fa-download" aria-hidden="true"></i></span><span id="aksrt-pay-download-title" data-pay-download-title></span></b></div>' +
|
||
'<div class="mini-scrollbar scroll-y max-vh7 pay-dawnload-edit-fields">' +
|
||
'<div class="mb20"><div class="muted-color mb6">' + escapeHtml(i18n.downloadUrl || '下载地址') + '</div>' +
|
||
'<div class="flex ac pay-dawnload-url-row"><input type="url" class="form-control" data-pay-resource-field="url" placeholder="' + escapeHtml(i18n.enterDownloadUrl || '请输入资源下载地址') + '">' +
|
||
'<input type="hidden" data-pay-resource-field="attachment_id">' +
|
||
'<button type="button" class="flex0 ml6 pay-upload-btn but hollow c-blue" data-pay-resource-upload><i class="fa fas fa-upload" aria-hidden="true"></i>' + escapeHtml(i18n.uploadFile || '上传附件') + '</button></div>' +
|
||
'<div class="px12 muted-3-color mt6">' + escapeHtml(i18n.pasteLinkHint || '支持直接粘贴网盘分享链接,并自动识别提取码') + '</div></div>' +
|
||
'<div class="mb20"><div class="muted-color mb6">' + escapeHtml(i18n.resourceNote || '资源备注') + '</div>' +
|
||
'<input type="text" class="form-control" data-pay-resource-field="extract_code" placeholder="' + escapeHtml(i18n.enterResourceNote || '请输入资源备注') + '">' +
|
||
'<div class="px12 muted-3-color mt6">' + escapeHtml(i18n.resourceNoteHint || '例如提取码、解压密码等') + '</div></div>' +
|
||
'<div class="mb20"><div class="muted-color mb6">' + escapeHtml(i18n.clickCopy || '点击复制') + '</div>' +
|
||
'<div class="flex ac pay-dawnload-copy-row"><input type="text" class="form-control mr10" data-pay-resource-field="copy_key" placeholder="' + escapeHtml(i18n.copyName || '复制名称') + '">' +
|
||
'<input type="text" class="form-control" data-pay-resource-field="copy_val" placeholder="' + escapeHtml(i18n.copyContent || '复制内容') + '"></div>' +
|
||
'<div class="px12 muted-3-color mt6">' + escapeHtml(i18n.copyHint || '填写后,用户可点击资源备注复制内容') + '</div></div>' +
|
||
'<div class="mb6"><div class="muted-color mb6">' + escapeHtml(i18n.customButton || '自定义按钮') + '</div>' +
|
||
'<input type="text" class="form-control" data-pay-resource-field="label" placeholder="' + escapeHtml(i18n.customButtonPlaceholder || '自定义下载按钮名称') + '"></div>' +
|
||
'<div class="mb20"><div class="muted-2-color mb6 px12">' + escapeHtml(i18n.selectButtonStyle || '选择按钮样式') + '</div>' +
|
||
'<div class="flex ac hh" data-pay-resource-classes></div><input type="hidden" data-pay-resource-field="class"></div>' +
|
||
'</div>' +
|
||
'<div class="modal-buts but-average" data-pay-download-actions><button type="button" class="but c-blue pay-dawnload-submit" data-pay-download-submit>' + escapeHtml(i18n.confirm || '确认') + '</button></div>' +
|
||
'</div>' +
|
||
'</div>';
|
||
document.body.appendChild(modal);
|
||
|
||
var dialog = modal.querySelector('.aksrt-editor-media__dialog');
|
||
var title = modal.querySelector('[data-pay-download-title]');
|
||
var actions = modal.querySelector('[data-pay-download-actions]');
|
||
var uploadButton = modal.querySelector('[data-pay-resource-upload]');
|
||
var inputMap = {};
|
||
fields.forEach(function (field) {
|
||
inputMap[field] = modal.querySelector('[data-pay-resource-field="' + field + '"]');
|
||
});
|
||
|
||
var classBox = modal.querySelector('[data-pay-resource-classes]');
|
||
buttonClasses.forEach(function (buttonClass) {
|
||
var button = document.createElement('button');
|
||
button.type = 'button';
|
||
button.className = 'class-choice badg ' + (buttonClass || 'b-theme');
|
||
button.setAttribute('data-pay-resource-class', buttonClass);
|
||
button.setAttribute('aria-label', i18n.selectButtonStyle || '选择按钮样式');
|
||
classBox.appendChild(button);
|
||
});
|
||
|
||
function markDirty() {
|
||
if (typeof options.markDirty === 'function') {
|
||
options.markDirty();
|
||
}
|
||
}
|
||
|
||
function notify(message, type, time, id) {
|
||
if (typeof options.notify === 'function') {
|
||
options.notify(message, type, time, id);
|
||
}
|
||
}
|
||
|
||
function reindex() {
|
||
list.querySelectorAll('[data-pay-download-item]').forEach(function (item, index) {
|
||
item.querySelectorAll('[data-pay-download-field]').forEach(function (input) {
|
||
var field = input.getAttribute('data-pay-download-field');
|
||
input.name = 'aksrt_pay[downloads][' + index + '][' + field + ']';
|
||
});
|
||
});
|
||
}
|
||
|
||
function setButtonClass(value) {
|
||
inputMap.class.value = buttonClasses.indexOf(value) === -1 ? '' : value;
|
||
classBox.querySelectorAll('[data-pay-resource-class]').forEach(function (button) {
|
||
button.classList.toggle('is-active', button.getAttribute('data-pay-resource-class') === inputMap.class.value);
|
||
});
|
||
}
|
||
|
||
function syncActions() {
|
||
actions.hidden = inputMap.url.value.trim() === '';
|
||
}
|
||
|
||
function closeModal() {
|
||
modal.hidden = true;
|
||
document.body.classList.remove('aksrt-editor-media-open');
|
||
if (previousFocus && typeof previousFocus.focus === 'function') {
|
||
previousFocus.focus();
|
||
}
|
||
}
|
||
|
||
function openModal(item) {
|
||
activeItem = item || null;
|
||
previousFocus = document.activeElement;
|
||
fields.forEach(function (field) {
|
||
var stored = activeItem && activeItem.querySelector('[data-pay-download-field="' + field + '"]');
|
||
inputMap[field].value = stored ? stored.value : '';
|
||
});
|
||
title.textContent = activeItem ? (i18n.editResource || '编辑资源') : (i18n.addResource || '添加资源');
|
||
setButtonClass(inputMap.class.value);
|
||
syncActions();
|
||
modal.hidden = false;
|
||
document.body.classList.add('aksrt-editor-media-open');
|
||
dialog.focus();
|
||
}
|
||
|
||
function saveResource() {
|
||
var url = validHttpUrl(inputMap.url.value);
|
||
if (!url) {
|
||
notify(i18n.invalidMediaUrl || '请填写有效地址', 'warning');
|
||
return;
|
||
}
|
||
|
||
var item = activeItem || createItem();
|
||
fields.forEach(function (field) {
|
||
var input = item.querySelector('[data-pay-download-field="' + field + '"]');
|
||
input.value = field === 'url' ? url : inputMap[field].value.trim();
|
||
});
|
||
item.querySelector('[data-pay-download-edit]').textContent = url;
|
||
if (!activeItem) {
|
||
list.appendChild(item);
|
||
}
|
||
reindex();
|
||
markDirty();
|
||
closeModal();
|
||
}
|
||
|
||
addButton.addEventListener('click', function () {
|
||
openModal(null);
|
||
});
|
||
|
||
list.addEventListener('click', function (event) {
|
||
var remove = event.target.closest('[data-pay-download-remove]');
|
||
if (remove) {
|
||
var removeItem = remove.closest('[data-pay-download-item]');
|
||
if (removeItem) {
|
||
removeItem.remove();
|
||
reindex();
|
||
markDirty();
|
||
}
|
||
return;
|
||
}
|
||
|
||
var edit = event.target.closest('[data-pay-download-edit]');
|
||
if (edit) {
|
||
openModal(edit.closest('[data-pay-download-item]'));
|
||
}
|
||
});
|
||
|
||
modal.addEventListener('click', function (event) {
|
||
if (event.target.closest('[data-pay-download-close]')) {
|
||
closeModal();
|
||
return;
|
||
}
|
||
var classButton = event.target.closest('[data-pay-resource-class]');
|
||
if (classButton) {
|
||
setButtonClass(classButton.getAttribute('data-pay-resource-class'));
|
||
}
|
||
});
|
||
modal.querySelector('[data-pay-download-submit]').addEventListener('click', saveResource);
|
||
inputMap.url.addEventListener('input', function () {
|
||
inputMap.attachment_id.value = '';
|
||
syncActions();
|
||
});
|
||
inputMap.url.addEventListener('paste', function (event) {
|
||
var text = event.clipboardData ? event.clipboardData.getData('text') : '';
|
||
if (!text) {
|
||
return;
|
||
}
|
||
var urlMatch = text.match(/https?:\/\/.*?(?=[\r\n\s]|提取码|密码|$)/i);
|
||
if (urlMatch && urlMatch[0]) {
|
||
event.preventDefault();
|
||
inputMap.url.value = urlMatch[0];
|
||
}
|
||
var codeMatch = text.match(/(?:提取码|密码)[::]\s*([a-zA-Z0-9]{4,6})/);
|
||
if (codeMatch && codeMatch[1]) {
|
||
inputMap.extract_code.value = (i18n.extractCodeColon || '提取码:') + codeMatch[1];
|
||
inputMap.copy_key.value = i18n.extractCode || '提取码';
|
||
inputMap.copy_val.value = codeMatch[1];
|
||
}
|
||
inputMap.attachment_id.value = '';
|
||
syncActions();
|
||
});
|
||
|
||
var canUseMediaPicker = !!(window.AksrtSubmitMedia && typeof window.AksrtSubmitMedia.open === 'function');
|
||
uploadButton.hidden = false;
|
||
uploadButton.addEventListener('click', function () {
|
||
if (!canUseMediaPicker) {
|
||
notify(i18n.mediaPickerUnavailable || '媒体选择器加载失败,请刷新页面后重试', 'danger');
|
||
return;
|
||
}
|
||
window.AksrtSubmitMedia.open({
|
||
type: 'file',
|
||
multiple: false,
|
||
allowExternal: false,
|
||
onSelect: function (item) {
|
||
if (!item) return;
|
||
inputMap.url.value = item.url || '';
|
||
inputMap.attachment_id.value = String(item.attachment_id || item.id || 0);
|
||
syncActions();
|
||
notify(i18n.uploaded || '附件上传成功', 'success', 5, 'aksrt-front-submit-resource-upload-toast');
|
||
},
|
||
});
|
||
});
|
||
|
||
document.addEventListener('keydown', function (event) {
|
||
if (!modal.hidden && event.key === 'Escape') {
|
||
closeModal();
|
||
}
|
||
});
|
||
reindex();
|
||
}
|
||
|
||
window.aksrtSubmitPayDownloads = { init: init };
|
||
})();
|