永久会员与模板库后台化:预览门控、轻量首页与 Admin CRUD

- 会员改为永久激活方案;云端文件不再拦截非会员;预览弹窗内导出/打印才校验
- 首页最近文件支持本地记录,登录后与云端合并;移除独立会员页与订阅页
- 模板库入库管理:soon_templates 表、Admin 上传 CRUD、/templates 轻量列表与按需下载

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
24kycj
2026-06-08 23:52:56 +08:00
parent 152228d41f
commit ebe191b06d
45 changed files with 1616 additions and 1259 deletions
+29 -14
View File
@@ -124,7 +124,14 @@
}
function listCloudFiles(pageOrLimit, sizeOrOffset) {
if (!requireCloudAuth('查看文件')) return Promise.reject(new Error('unauthorized'));
if (!getAccessToken()) {
var empty = { items: [], total: 0 };
if (typeof pageOrLimit === 'object' && pageOrLimit) {
empty.page = pageOrLimit.page || 1;
empty.size = pageOrLimit.size || 12;
}
return Promise.resolve(empty);
}
var url;
var fallback = { items: [], total: 0 };
if (typeof pageOrLimit === 'object' && pageOrLimit) {
@@ -145,9 +152,6 @@
function createCloudFile(name, jsonStr) {
if (!requireCloudAuth('保存')) return Promise.reject(new Error('unauthorized'));
if (typeof window.soonRequireMember === 'function' && !window.soonRequireMember('保存')) {
return Promise.reject(new Error('membership_required'));
}
return authedFetch('files', {
method: 'POST',
headers: JSON_HEADERS,
@@ -159,9 +163,6 @@
function updateCloudFile(id, name, jsonStr, version) {
if (!requireCloudAuth('保存')) return Promise.reject(new Error('unauthorized'));
if (typeof window.soonRequireMember === 'function' && !window.soonRequireMember('保存')) {
return Promise.reject(new Error('membership_required'));
}
var body = { name: normalizeSoonName(name), json: jsonStr };
if (version != null) body.version = version;
return authedFetch('files/' + id, {
@@ -186,9 +187,6 @@
function downloadCloudFile(id, fileName) {
if (!requireCloudAuth('下载')) return Promise.reject(new Error('unauthorized'));
if (typeof window.soonRequireMember === 'function' && !window.soonRequireMember('下载')) {
return Promise.reject(new Error('membership_required'));
}
return authedFetch('files/' + id + '/download', { headers: { Accept: 'application/octet-stream' } })
.then(function (response) {
if (!response.ok) {
@@ -328,14 +326,31 @@
pathOrHandle = typeof pathOrHandle.name === 'string' ? pathOrHandle.name : 'design.soon';
}
if (!requireCloudAuth('保存')) {
return Promise.reject(new Error('unauthorized'));
}
var name = typeof pathOrHandle === 'string' ? pathOrHandle : 'design.soon';
var cloudRef = parseCloudRef(name);
var fileName = normalizeSoonName(name);
if (!getAccessToken()) {
if (cloudRef && cloudRef.id) {
requireCloudAuth('保存');
return Promise.reject(new Error('unauthorized'));
}
var sessionKey = name.indexOf('soondesign_session:') === 0
? name
: 'soondesign_session:' + fileName.replace(/\.soon$/i, '') + '-' + Date.now();
try {
sessionStorage.setItem(sessionKey, str);
try { localStorage.setItem(sessionKey, str); } catch (e2) { /* ignore quota */ }
return Promise.resolve({ fileKey: sessionKey, name: fileName, version: 0 });
} catch (e) {
return Promise.reject(new Error('save_failed'));
}
}
if (!requireCloudAuth('保存')) {
return Promise.reject(new Error('unauthorized'));
}
if (cloudRef && cloudRef.id) {
var ver = cloudRef.version;
if (ver == null && window._soonFileMeta && window._soonFileMeta.id === cloudRef.id) {