Files
wordpress-theme-aksrt/assets/js/protected-download.js
T
kate522andClaude Opus 5 fac4a714e0 feat(creator-studio): 前台 Gutenberg 创作工作台与受保护付费附件
前台投稿页改为沉浸式创作工作台:Gutenberg 负责区块解析与序列化,
React + TypeScript 负责工作台外壳与发布抽屉,Jio 服务端继续作为权限、
审核与付费的唯一权威。

- 新增 assets/creator-studio 独立构建(wp-scripts,锁定 WP 6.4 时代包),
  仅在投稿模板加载,构建缺失或游客访问时回退原有 TinyMCE 表单
- 自动保存(4s 防抖 + rev 冲突 409)、本地快照恢复、发布配置抽屉、
  移动端全屏单列与安全区适配
- 图片插入走现有 front-submit 上传管线,保留能力校验与待认领生命周期
- 已发布文章的改稿写入私有版本,审核通过前线上内容/链接/付费条款不变;
  原生后台「改稿审核」一次性应用或退回,并校验源文章并发指纹
- 私有附件新表 jio_private_asset + jio_dl_token.asset_id,schema 升到 3.4.0;
  文件存放 ABSPATH 之外,未配置私有存储时 fail closed
- 下载令牌绑定文章/附件/用户/IP/UA/次数,每次交付复核 Visibility 的
  订单、VIP 与配额判定;中断传输归还次数
- 付费字段改为写入前校验,非法价格不再留下半保存文章
- 新增 creator-studio 契约测试;更新受影响的 schema/下载/投稿契约

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-06 14:53:23 +08:00

79 lines
2.2 KiB
JavaScript

/**
* 受保护下载按钮:先换取短期令牌,再用令牌地址下载。
*
* 按钮由下载区模板输出,只携带随机 asset_key,不携带文件路径或公开 URL。
*
* @package Jio
*/
(function () {
'use strict';
var i18n = (window.jioData && window.jioData.protectedDownload) || {};
var tokenUrl = i18n.tokenUrl || '';
function toast(message, type) {
if (typeof window.notyf === 'function') {
window.notyf(message, type || 'danger');
}
}
function message(data) {
if (data && typeof data.message === 'string' && data.message !== '') {
return data.message;
}
return i18n.error || '下载失败,请稍后重试';
}
function download(button) {
var assetKey = button.getAttribute('data-jio-protected-asset') || '';
var postId = button.getAttribute('data-jio-protected-post') || '';
if (!assetKey || !postId || !tokenUrl) {
return;
}
if (button.getAttribute('aria-busy') === 'true') {
return;
}
button.setAttribute('aria-busy', 'true');
var body = new URLSearchParams();
body.set('post_id', postId);
body.set('asset_key', assetKey);
fetch(tokenUrl, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-WP-Nonce': (window.jioData && window.jioData.restNonce) || ''
},
body: body.toString()
})
.then(function (response) {
return response.json().then(function (data) {
return { ok: response.ok, data: data };
});
})
.then(function (result) {
if (!result.ok || !result.data || !result.data.url) {
throw new Error(message(result.data));
}
window.location.href = result.data.url;
})
.catch(function (error) {
toast(error && error.message ? error.message : (i18n.error || '下载失败,请稍后重试'));
})
.finally(function () {
button.removeAttribute('aria-busy');
});
}
document.addEventListener('click', function (event) {
var button = event.target.closest('[data-jio-protected-asset]');
if (!button) {
return;
}
event.preventDefault();
download(button);
});
})();