From ee4e599f2d0d3af6acd118276360d9d2289875a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Aug 2026 18:25:42 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E4=BA=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=B0=8F=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/css/frontend/pages/submit.css | 74 ++++- assets/js/front-submit-pay-download.js | 302 ++++++++++++++++++ assets/js/front-submit.js | 64 +--- inc/helpers/aksrt-pay.php | 15 +- src/Core/DomainModel.php | 12 + src/Core/FrontSubmitPay.php | 3 + src/Core/ResourceMetaBox.php | 2 +- src/Core/Setup.php | 3 + templates/pages/page-submit.php | 28 +- templates/parts/submit/sidebar-pay.php | 17 +- tests/asset-ledger/FrontSubmitPayTest.php | 20 ++ .../post-editor-reference-contract.test.cjs | 26 ++ tests/widget-system/toast-contract.test.cjs | 5 +- 13 files changed, 496 insertions(+), 75 deletions(-) create mode 100644 assets/js/front-submit-pay-download.js diff --git a/assets/css/frontend/pages/submit.css b/assets/css/frontend/pages/submit.css index 50914a79..658fe34f 100644 --- a/assets/css/frontend/pages/submit.css +++ b/assets/css/frontend/pages/submit.css @@ -127,6 +127,10 @@ padding: 10px; } +.aksrt-editor-media[hidden] { + display: none !important; +} + .aksrt-editor-media__backdrop { position: absolute; inset: 0; @@ -500,7 +504,7 @@ body.aksrt-editor-media-open { .pay-dawnload-edit .lists-item { gap: 5px; - padding: 6px 8px; + padding: 4px 12px; word-break: break-all; } @@ -508,9 +512,62 @@ body.aksrt-editor-media-open { border-top: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.08)); } -.pay-dawnload-edit .lists-item .form-control { +.pay-dawnload-edit .name-link { min-width: 0; - padding: 5px 7px; + padding: 5px 0; + overflow: hidden; + border: 0; + background: transparent; + color: var(--focus-color, #f04494); + line-height: 1.5; + text-align: left; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; +} + +.pay-dawnload-edit .name-link:focus, +.pay-dawnload-edit .name-link:active { + outline: 0; + box-shadow: none; +} + +.pay-dawnload-edit-modal .aksrt-editor-media__dialog { + width: min(600px, calc(100vw - 20px)); +} + +.pay-dawnload-edit-content { + padding: 20px; +} + +.pay-dawnload-edit-content .pay-dawnload-edit-fields { + padding: 0 3px; +} + +.pay-dawnload-edit-content .form-control { + width: 100%; + min-width: 0; +} + +.pay-dawnload-edit-content .class-choice { + width: 29px; + height: 22px; + margin: 2px; + padding: 0; + border: 2px solid var(--main-bg-color, #fff); + cursor: pointer; +} + +.pay-dawnload-edit-content .class-choice.is-active { + box-shadow: 0 0 0 2px var(--muted-2-color, #999); +} + +.pay-dawnload-edit-content .modal-buts { + margin: 18px -20px -20px; +} + +.pay-dawnload-edit-content .pay-upload-btn .fa { + margin-right: 4px; } .newposts-wrap [hidden] { @@ -576,8 +633,13 @@ body.aksrt-editor-media-open { min-height: 150px; } - .pay-dawnload-edit .lists-item { - align-items: stretch; - flex-direction: column; + .pay-dawnload-edit-content { + padding: 18px 15px; + } + + .pay-dawnload-edit-content .modal-buts { + margin-right: -15px; + margin-bottom: -18px; + margin-left: -15px; } } diff --git a/assets/js/front-submit-pay-download.js b/assets/js/front-submit-pay-download.js new file mode 100644 index 00000000..e01793a8 --- /dev/null +++ b/assets/js/front-submit-pay-download.js @@ -0,0 +1,302 @@ +/** + * Reference-style paid download resource editor for the front submit page. + * + * @package AKSRT + */ +(function () { + 'use strict'; + + var fields = ['url', '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, '''); + } + + 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 = ''; + 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 = + '' + + ''; + 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', 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]; + } + syncActions(); + }); + + var canUpload = !!((cfg.uploads || {}).resource && typeof options.pickUpload === 'function' && typeof options.uploadFile === 'function'); + uploadButton.hidden = !canUpload; + if (canUpload) { + uploadButton.addEventListener('click', function () { + var toastId = 'aksrt-front-submit-resource-upload-toast'; + options.pickUpload('resource', '*/*').then(function (file) { + if (!file) { + return null; + } + uploadButton.disabled = true; + notify(i18n.uploading || '正在上传附件…', 'load', '', toastId); + return options.uploadFile('resource', file); + }).then(function (file) { + if (!file) { + return; + } + inputMap.url.value = file.url || ''; + syncActions(); + notify(i18n.uploaded || '附件上传成功', 'success', 5, toastId); + }).catch(function (error) { + notify(error.message || i18n.error || '附件上传失败', 'danger', 5, toastId); + }).finally(function () { + uploadButton.disabled = false; + }); + }); + } + + document.addEventListener('keydown', function (event) { + if (!modal.hidden && event.key === 'Escape') { + closeModal(); + } + }); + reindex(); + } + + window.aksrtSubmitPayDownloads = { init: init }; +})(); diff --git a/assets/js/front-submit.js b/assets/js/front-submit.js index ccee267c..c76e70c1 100644 --- a/assets/js/front-submit.js +++ b/assets/js/front-submit.js @@ -587,60 +587,16 @@ }); }); - var list = qs('[data-pay-download-list]', box); - var tpl = qs('[data-pay-download-tpl]', box); - var addBtn = qs('[data-pay-download-add]', box); - if (addBtn && list && tpl) { - addBtn.addEventListener('click', function () { - var node = tpl.content.cloneNode(true); - var idx = list.querySelectorAll('[data-pay-download-item]').length; - qsa('[data-name]', node).forEach(function (input) { - input.name = 'aksrt_pay[downloads][' + idx + '][' + input.getAttribute('data-name') + ']'; - }); - list.appendChild(node); - }); - } - var uploadBtn = qs('[data-pay-download-upload]', box); - if (uploadBtn && list && tpl) { - uploadBtn.addEventListener('click', function () { - var toastId = 'aksrt-front-submit-resource-upload-toast'; - App.pickUpload('resource', '*/*').then(function (file) { - if (!file) return null; - uploadBtn.disabled = true; - notyf(i18n.uploading || '正在上传附件…', 'load', '', toastId); - return App.uploadFile('resource', file); - }).then(function (file) { - if (!file) return; - var node = tpl.content.cloneNode(true); - var idx = list.querySelectorAll('[data-pay-download-item]').length; - qsa('[data-name]', node).forEach(function (input) { - input.name = 'aksrt_pay[downloads][' + idx + '][' + input.getAttribute('data-name') + ']'; - }); - var url = qs('[data-pay-download-url]', node); - var label = qs('[data-pay-download-label]', node); - if (url) url.value = file.url || ''; - if (label) label.value = file.name || ''; - list.appendChild(node); - notyf(i18n.uploaded || '附件上传成功', 'success', 5, toastId); - }).catch(function (error) { - notyf(error.message || i18n.error || '附件上传失败', 'danger', 5, toastId); - }).finally(function () { - uploadBtn.disabled = false; - }); - }); - } - if (list) { - list.addEventListener('click', function (e) { - var rm = e.target.closest('[data-pay-download-remove]'); - if (!rm) { - return; - } - var item = rm.closest('[data-pay-download-item]'); - if (item) { - item.remove(); - } - }); - } + window.aksrtSubmitPayDownloads.init({ + root: box, + pickUpload: this.pickUpload.bind(this), + uploadFile: this.uploadFile.bind(this), + notify: notyf, + markDirty: function () { + App.isDirty = true; + App.form.setAttribute('data-dirty', 'true'); + }, + }); }, bindAi: function () { diff --git a/inc/helpers/aksrt-pay.php b/inc/helpers/aksrt-pay.php index 234ece7d..8d38664a 100644 --- a/inc/helpers/aksrt-pay.php +++ b/inc/helpers/aksrt-pay.php @@ -1331,12 +1331,23 @@ if (!function_exists('aksrt_get_paid_download_actions_html')) { $label = (string) ($service['name'] ?? __('本地下载', 'aksrt')); } $type = sanitize_key((string) ($download['type'] ?? 'direct')); - $has_extract = trim((string) ($download['extract_code'] ?? '')) !== ''; + $extract_code = trim((string) ($download['extract_code'] ?? '')); + $has_extract = $extract_code !== ''; $service_key = sanitize_html_class((string) ($service['key'] ?? 'other')) ?: 'other'; + $button_class = trim((string) ($download['class'] ?? '')); + $button_class = $button_class !== '' ? $button_class : 'b-theme ' . $service_key; + $copy_value = trim((string) ($download['copy_val'] ?? '')); + $copy_key = trim((string) ($download['copy_key'] ?? '')); + $copy_label = $extract_code !== '' ? $extract_code : ($copy_key !== '' ? $copy_key : __('更多内容', 'aksrt')); $buttons .= '
'; - $buttons .= ''; + if ($copy_value !== '') { + $buttons .= ''; + } elseif ($extract_code !== '') { + $buttons .= '' . esc_html($extract_code) . ''; + } $buttons .= '
'; } diff --git a/src/Core/DomainModel.php b/src/Core/DomainModel.php index 7aed1f31..7c874097 100644 --- a/src/Core/DomainModel.php +++ b/src/Core/DomainModel.php @@ -181,6 +181,13 @@ class DomainModel { } $allowed_types = ['direct', 'net_disk', 'external']; + $allowed_classes = [ + '', + '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', + ]; $downloads = []; foreach ($value as $row) { @@ -229,6 +236,11 @@ class DomainModel { 'url' => $url, 'type' => $type, 'extract_code' => $extract_code, + 'copy_key' => isset($row['copy_key']) ? sanitize_text_field((string) $row['copy_key']) : '', + 'copy_val' => isset($row['copy_val']) ? sanitize_text_field((string) $row['copy_val']) : '', + 'class' => isset($row['class']) && in_array($row['class'], $allowed_classes, true) + ? (string) $row['class'] + : '', ]; } diff --git a/src/Core/FrontSubmitPay.php b/src/Core/FrontSubmitPay.php index 61091d5f..d930d392 100644 --- a/src/Core/FrontSubmitPay.php +++ b/src/Core/FrontSubmitPay.php @@ -229,6 +229,9 @@ trait FrontSubmitPay { 'url' => $url, 'type' => $attachment_id > 0 ? 'direct' : 'external', 'extract_code' => sanitize_text_field((string) ($row['extract_code'] ?? '')), + 'copy_key' => sanitize_text_field((string) ($row['copy_key'] ?? '')), + 'copy_val' => sanitize_text_field((string) ($row['copy_val'] ?? '')), + 'class' => sanitize_key((string) ($row['class'] ?? '')), ]; } return DomainModel::sanitize_downloads($out); diff --git a/src/Core/ResourceMetaBox.php b/src/Core/ResourceMetaBox.php index 308fa53c..57d49d93 100644 --- a/src/Core/ResourceMetaBox.php +++ b/src/Core/ResourceMetaBox.php @@ -200,7 +200,7 @@ class ResourceMetaBox { /** @param int|string $index */ private function download_row($index, array $row): void { ?> -
+
['type' => 'string', 'format' => 'uri'], 'type' => ['type' => 'string'], 'extract_code' => ['type' => 'string'], + 'copy_key' => ['type' => 'string'], + 'copy_val' => ['type' => 'string'], + 'class' => ['type' => 'string'], ], ], ], diff --git a/templates/pages/page-submit.php b/templates/pages/page-submit.php index dccceef6..0ba6353a 100644 --- a/templates/pages/page-submit.php +++ b/templates/pages/page-submit.php @@ -54,10 +54,18 @@ if (file_exists($css)) { } $js = get_template_directory() . '/assets/js/front-submit.js'; if (file_exists($js)) { + $pay_download_js = get_template_directory() . '/assets/js/front-submit-pay-download.js'; + wp_enqueue_script( + 'aksrt-front-submit-pay-download', + get_template_directory_uri() . '/assets/js/front-submit-pay-download.js', + [], + (string) filemtime($pay_download_js), + true + ); wp_enqueue_script( 'aksrt-front-submit', get_template_directory_uri() . '/assets/js/front-submit.js', - ['aksrt-runtime'], + ['aksrt-runtime', 'aksrt-front-submit-pay-download'], (string) filemtime($js), true ); @@ -180,6 +188,24 @@ if (file_exists($js)) { 'loginVisible' => __('登录可见', 'aksrt'), 'vipVisible' => __('VIP 可见', 'aksrt'), 'payVisible' => __('付费可见', 'aksrt'), + 'addResource' => __('添加资源', 'aksrt'), + 'editResource' => __('编辑资源', 'aksrt'), + 'downloadUrl' => __('下载地址', 'aksrt'), + 'enterDownloadUrl' => __('请输入资源下载地址', 'aksrt'), + 'pasteLinkHint' => __('支持直接粘贴网盘分享链接,并自动识别提取码', 'aksrt'), + 'resourceNote' => __('资源备注', 'aksrt'), + 'enterResourceNote' => __('请输入资源备注', 'aksrt'), + 'resourceNoteHint' => __('例如提取码、解压密码等', 'aksrt'), + 'clickCopy' => __('点击复制', 'aksrt'), + 'copyName' => __('复制名称', 'aksrt'), + 'copyContent' => __('复制内容', 'aksrt'), + 'copyHint' => __('填写后,用户可点击资源备注复制内容', 'aksrt'), + 'customButton' => __('自定义按钮', 'aksrt'), + 'customButtonPlaceholder' => __('自定义下载按钮名称', 'aksrt'), + 'selectButtonStyle' => __('选择按钮样式', 'aksrt'), + 'extractCode' => __('提取码', 'aksrt'), + 'extractCodeColon' => __('提取码:', 'aksrt'), + 'confirm' => __('确认', 'aksrt'), ], ]); } diff --git a/templates/parts/submit/sidebar-pay.php b/templates/parts/submit/sidebar-pay.php index 3df993be..7e7b3121 100644 --- a/templates/parts/submit/sidebar-pay.php +++ b/templates/parts/submit/sidebar-pay.php @@ -62,22 +62,21 @@ if (!function_exists('aksrt_submit_pay_line')) {
-
- - -
+
$row) : ?>
- - - - + + +
+ + + +
-
diff --git a/tests/asset-ledger/FrontSubmitPayTest.php b/tests/asset-ledger/FrontSubmitPayTest.php index ea8cc94b..89489b2e 100644 --- a/tests/asset-ledger/FrontSubmitPayTest.php +++ b/tests/asset-ledger/FrontSubmitPayTest.php @@ -86,6 +86,26 @@ final class FrontSubmitPayTest extends TestCase { self::assertSame('0.00', $meta['vip2_price']); } + public function test_download_resource_modal_fields_are_sanitized_as_one_payload(): void { + $downloads = DomainModel::sanitize_downloads([ + [ + 'url' => 'https://example.com/file.zip', + 'label' => '镜像下载', + 'extract_code' => ' 提取码:1234 ', + 'copy_key' => '提取码', + 'copy_val' => ' 1234 ', + 'class' => 'jb-blue', + ], + ]); + + self::assertCount(1, $downloads); + self::assertSame('镜像下载', $downloads[0]['label']); + self::assertSame('提取码:1234', $downloads[0]['extract_code']); + self::assertSame('提取码', $downloads[0]['copy_key']); + self::assertSame('1234', $downloads[0]['copy_val']); + self::assertSame('jb-blue', $downloads[0]['class']); + } + private function settings(bool $vip1_enabled, bool $vip2_enabled): array { return [ 'pay_free_s' => true, diff --git a/tests/widget-system/post-editor-reference-contract.test.cjs b/tests/widget-system/post-editor-reference-contract.test.cjs index bfcbf74f..42403e62 100644 --- a/tests/widget-system/post-editor-reference-contract.test.cjs +++ b/tests/widget-system/post-editor-reference-contract.test.cjs @@ -49,6 +49,32 @@ test('front submit follows the reference newposts shell and cards', () => { assert.match(submit, /new-posts-submit/); }); +test('front submit paid resources use the reference modal editor and compact list', () => { + const page = read('templates/pages/page-submit.php'); + const pay = read('templates/parts/submit/sidebar-pay.php'); + const submit = read('assets/js/front-submit.js'); + const downloads = read('assets/js/front-submit-pay-download.js'); + const model = read('src/Core/DomainModel.php'); + + assert.match(page, /aksrt-front-submit-pay-download/); + assert.match(submit, /aksrtSubmitPayDownloads\.init/); + assert.match(pay, /data-pay-download-add/); + assert.match(pay, /data-pay-download-edit/); + assert.match(pay, /data-pay-download-remove/); + assert.match(pay, /class="hidden-input"/); + assert.doesNotMatch(pay, /data-pay-download-upload|data-pay-download-tpl/); + + ['url', 'extract_code', 'copy_key', 'copy_val', 'label', 'class'].forEach((field) => { + assert.match(downloads, new RegExp(`['"]${field}['"]`)); + assert.match(model, new RegExp(`['"]${field}['"]`)); + }); + assert.match(downloads, /pay-dawnload-edit-modal/); + assert.match(downloads, /data-pay-resource-upload/); + assert.match(downloads, /data-pay-resource-classes/); + assert.match(downloads, /提取码\|密码/); + assert.doesNotMatch(downloads, /shop|forum|bbs_/i); +}); + test('front submit image and visibility actions live in the TinyMCE toolbar', () => { const main = read('templates/parts/submit/editor-main.php'); const page = read('templates/pages/page-submit.php'); diff --git a/tests/widget-system/toast-contract.test.cjs b/tests/widget-system/toast-contract.test.cjs index 85e4be79..7a42c6df 100644 --- a/tests/widget-system/toast-contract.test.cjs +++ b/tests/widget-system/toast-contract.test.cjs @@ -370,7 +370,8 @@ test('settings actions use rehydrated fixed-id notyf flows', () => { test('front submit actions use direct fixed-id notyf flows', () => { const submit = read('assets/js/front-submit.js'); const editor = read('assets/js/front-submit-editor.js'); - const source = submit + '\n' + editor; + const downloads = read('assets/js/front-submit-pay-download.js'); + const source = submit + '\n' + editor + '\n' + downloads; const page = read('templates/pages/page-submit.php'); [ @@ -399,7 +400,7 @@ test('front submit actions use direct fixed-id notyf flows', () => { assert.match(submit, new RegExp("notyf\\([^;]+?'danger'[^;]+?" + variable + "\\);")); }); - assert.match(submit, /aksrt-front-submit-resource-upload-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); + assert.match(downloads, /aksrt-front-submit-resource-upload-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(editor, /aksrt-front-submit-editor-media-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(submit, /aksrt-front-submit-ai-tags-toast[\s\S]*?aksrt-front-submit-ai-summary-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(submit, /needContent[^;]+?'warning'/);