Web 端数据交互与 design2 布局修复
统一门户 JSON 契约:新增 GET /templates/{id},模板/云文件/保存/打开走虚拟 key;
layer 保存弹层替代 prompt,本地 .soon 已登录后台 POST 登记;修复保存静默失败与 design2 全宽布局。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,9 +2,23 @@
|
||||
'use strict';
|
||||
|
||||
var FILE_PREFIX = 'soondesign_file:';
|
||||
var TEMPLATE_PREFIX = 'soondesign_template:';
|
||||
|
||||
function soonParseTemplateKey(key) {
|
||||
if (!key || typeof key !== 'string') return null;
|
||||
var m = key.match(/^soondesign_template:(\d+)$/);
|
||||
if (!m) return null;
|
||||
return { id: parseInt(m[1], 10) };
|
||||
}
|
||||
|
||||
function soonMakeTemplateKey(id) {
|
||||
return TEMPLATE_PREFIX + id;
|
||||
}
|
||||
|
||||
function soonIsWebPortal() {
|
||||
return typeof window !== 'undefined' && window.platformBridge && !window.fs;
|
||||
if (typeof window === 'undefined') return false;
|
||||
if (window.SOON_DEPLOY_CONFIG) return true;
|
||||
return !!(window.platformBridge && window.fs == null);
|
||||
}
|
||||
|
||||
function soonGetAccessToken() {
|
||||
@@ -31,6 +45,10 @@
|
||||
var meta = window._soonFileMeta;
|
||||
return (meta && meta.name) ? meta.name : 'design.soon';
|
||||
}
|
||||
if (n.indexOf(TEMPLATE_PREFIX) === 0) {
|
||||
var tpl = soonParseTemplateKey(n);
|
||||
return tpl ? ('template-' + tpl.id + '.soon') : 'template.soon';
|
||||
}
|
||||
if (n.indexOf('soondesign_session:') === 0) {
|
||||
n = n.replace(/^soondesign_session:/, '');
|
||||
}
|
||||
@@ -45,8 +63,68 @@
|
||||
return soonMakeFileKey(data.id, data.version);
|
||||
}
|
||||
|
||||
function soonSyncOpenNavigation(fileKey, type) {
|
||||
if (typeof sessionStorage === 'undefined') {
|
||||
if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) window._soonFileMeta = null;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (fileKey) {
|
||||
sessionStorage.setItem('soondesign_open_file', fileKey);
|
||||
sessionStorage.setItem('soondesign_open_type', String(type || 1));
|
||||
if (fileKey.indexOf(FILE_PREFIX) === 0 && window._soonFileMeta) {
|
||||
sessionStorage.setItem('soondesign_open_meta', JSON.stringify(window._soonFileMeta));
|
||||
} else {
|
||||
sessionStorage.removeItem('soondesign_open_meta');
|
||||
if (fileKey.indexOf(FILE_PREFIX) !== 0) window._soonFileMeta = null;
|
||||
}
|
||||
} else {
|
||||
sessionStorage.removeItem('soondesign_open_file');
|
||||
sessionStorage.removeItem('soondesign_open_type');
|
||||
sessionStorage.removeItem('soondesign_open_meta');
|
||||
window._soonFileMeta = null;
|
||||
}
|
||||
} catch (e) { /* ignore quota */ }
|
||||
}
|
||||
|
||||
function soonResolveOpenFileKey(getParams) {
|
||||
var params = typeof getParams === 'function' ? getParams() : null;
|
||||
if (!params || typeof params.has !== 'function') return '';
|
||||
var file = params.has('file') ? (params.get('file') || '') : null;
|
||||
if (file === null && typeof sessionStorage !== 'undefined') {
|
||||
try {
|
||||
file = sessionStorage.getItem('soondesign_open_file') || '';
|
||||
if (file) {
|
||||
sessionStorage.removeItem('soondesign_open_file');
|
||||
sessionStorage.removeItem('soondesign_open_type');
|
||||
}
|
||||
} catch (e) {
|
||||
file = '';
|
||||
}
|
||||
}
|
||||
return file || '';
|
||||
}
|
||||
|
||||
function soonConsumeOpenMeta(fileKey) {
|
||||
if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) {
|
||||
window._soonFileMeta = null;
|
||||
return;
|
||||
}
|
||||
if (typeof sessionStorage === 'undefined') return;
|
||||
try {
|
||||
var metaRaw = sessionStorage.getItem('soondesign_open_meta');
|
||||
if (metaRaw) {
|
||||
window._soonFileMeta = JSON.parse(metaRaw);
|
||||
sessionStorage.removeItem('soondesign_open_meta');
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function soonBindFileMeta(fileKey, opts) {
|
||||
if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) return;
|
||||
if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) {
|
||||
window._soonFileMeta = null;
|
||||
return;
|
||||
}
|
||||
var parsed = soonParseFileKey(fileKey);
|
||||
if (!parsed) return;
|
||||
var prev = window._soonFileMeta || {};
|
||||
@@ -137,16 +215,22 @@
|
||||
soonApplyMembership(null);
|
||||
return Promise.resolve(_membership);
|
||||
}
|
||||
var url = soonApiBase() + '/plans/me';
|
||||
var url = soonApiBase() + '/auth/me';
|
||||
var fetchFn = typeof window.soonAuthedFetch === 'function'
|
||||
? window.soonAuthedFetch(url, { headers: { Accept: 'application/json' } })
|
||||
: fetch(url, { headers: { Authorization: 'Bearer ' + soonGetAccessToken(), Accept: 'application/json' } });
|
||||
_membership.loading = fetchFn
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (r) {
|
||||
if (r.status === 401) {
|
||||
soonApplyMembership(null);
|
||||
return null;
|
||||
}
|
||||
return r.json();
|
||||
})
|
||||
.then(function (j) {
|
||||
if (j && j.ok && j.data) {
|
||||
soonApplyMembership(j.data.membership || j.data);
|
||||
} else {
|
||||
soonApplyMembership(j.data);
|
||||
} else if (j !== null) {
|
||||
soonApplyMembership(null);
|
||||
}
|
||||
return _membership;
|
||||
@@ -184,20 +268,27 @@
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (soonIsMember()) {
|
||||
onAllowed();
|
||||
function allowOrActivate() {
|
||||
if (soonIsMember()) {
|
||||
onAllowed();
|
||||
return;
|
||||
}
|
||||
if (typeof window.soonShowActivateGate === 'function') {
|
||||
window.soonShowActivateGate({
|
||||
reason: actionLabel || '导出或打印',
|
||||
onSuccess: function () {
|
||||
onAllowed();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
soonToast('请先激活会员后再' + (actionLabel || '操作'), 'warn');
|
||||
}
|
||||
}
|
||||
if (!_membership.loaded) {
|
||||
soonLoadMembership(false).then(allowOrActivate);
|
||||
return;
|
||||
}
|
||||
if (typeof window.soonShowActivateGate === 'function') {
|
||||
window.soonShowActivateGate({
|
||||
reason: actionLabel || '导出或打印',
|
||||
onSuccess: function () {
|
||||
onAllowed();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
soonToast('请先激活会员后再' + (actionLabel || '操作'), 'warn');
|
||||
}
|
||||
allowOrActivate();
|
||||
}
|
||||
|
||||
function soonGuardCloudSave() {
|
||||
@@ -223,7 +314,11 @@
|
||||
|
||||
function soonOpenSoonJsonLocally(j, fileName) {
|
||||
var key = soonPutSoonSession(j, fileName);
|
||||
if (!key) return '';
|
||||
if (!key) {
|
||||
soonToast('无法打开文件(存储空间不足)', 'error');
|
||||
return '';
|
||||
}
|
||||
soonScheduleCloudImport(key, fileName);
|
||||
var type = soonSoonTypeFromJson(j);
|
||||
if (window.platformBridge && window.platformBridge.openDesignPage) {
|
||||
window.platformBridge.openDesignPage(key, type);
|
||||
@@ -231,6 +326,75 @@
|
||||
return key;
|
||||
}
|
||||
|
||||
var PENDING_IMPORT_KEY = 'soondesign_pending_import';
|
||||
|
||||
function soonScheduleCloudImport(sessionKey, fileName) {
|
||||
if (!soonGetAccessToken() || !sessionKey) return;
|
||||
if (sessionKey.indexOf('soondesign_session:') !== 0) return;
|
||||
try {
|
||||
sessionStorage.setItem(PENDING_IMPORT_KEY, JSON.stringify({
|
||||
sessionKey: sessionKey,
|
||||
name: soonNormalizeSoonName(fileName || 'design.soon'),
|
||||
at: Date.now()
|
||||
}));
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function soonClearPendingImport() {
|
||||
try { sessionStorage.removeItem(PENDING_IMPORT_KEY); } catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function soonTryConsumeCloudImport(currentFileKey) {
|
||||
if (!currentFileKey || currentFileKey.indexOf('soondesign_session:') !== 0) return;
|
||||
if (!soonGetAccessToken()) return;
|
||||
if (typeof window.openAs !== 'undefined' && window.openAs && window.openAs.name &&
|
||||
window.openAs.name.indexOf(FILE_PREFIX) === 0) {
|
||||
soonClearPendingImport();
|
||||
return;
|
||||
}
|
||||
var pendingRaw;
|
||||
try {
|
||||
pendingRaw = sessionStorage.getItem(PENDING_IMPORT_KEY);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (!pendingRaw) return;
|
||||
var pending;
|
||||
try {
|
||||
pending = JSON.parse(pendingRaw);
|
||||
} catch (e) {
|
||||
try { sessionStorage.removeItem(PENDING_IMPORT_KEY); } catch (e2) { /* ignore */ }
|
||||
return;
|
||||
}
|
||||
if (!pending || pending.sessionKey !== currentFileKey) return;
|
||||
try { sessionStorage.removeItem(PENDING_IMPORT_KEY); } catch (e) { /* ignore */ }
|
||||
|
||||
var jsonRaw;
|
||||
try {
|
||||
jsonRaw = sessionStorage.getItem(currentFileKey);
|
||||
if (!jsonRaw && typeof localStorage !== 'undefined') jsonRaw = localStorage.getItem(currentFileKey);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (!jsonRaw) return;
|
||||
|
||||
var bridge = window.platformBridge;
|
||||
if (!bridge || typeof bridge.importSoonFile !== 'function') return;
|
||||
|
||||
bridge.importSoonFile(pending.name || 'design.soon', jsonRaw).then(function (res) {
|
||||
if (res && res.fileKey && typeof window.openAs !== 'undefined' && window.openAs) {
|
||||
window.openAs.name = res.fileKey;
|
||||
}
|
||||
}).catch(function (err) {
|
||||
if (err && err.status) return;
|
||||
soonToast((err && err.message) ? err.message : '云端登记失败,可稍后保存重试', 'warn');
|
||||
});
|
||||
}
|
||||
|
||||
function soonReportOpenLoadError(message) {
|
||||
soonToast(message || '文件加载失败', 'error');
|
||||
}
|
||||
|
||||
function soonToast(message, type) {
|
||||
if (typeof window.soonToast === 'function') window.soonToast(message, type);
|
||||
}
|
||||
@@ -289,6 +453,14 @@
|
||||
|
||||
function soonDisplayFileName(pathOrKey) {
|
||||
if (!pathOrKey) return '';
|
||||
if (pathOrKey.indexOf(TEMPLATE_PREFIX) === 0) {
|
||||
var tplMeta = window._soonTemplateMeta;
|
||||
var tplParsed = soonParseTemplateKey(pathOrKey);
|
||||
if (tplMeta && tplParsed && tplMeta.id === tplParsed.id && tplMeta.name) {
|
||||
return tplMeta.name;
|
||||
}
|
||||
return tplParsed ? ('模板 #' + tplParsed.id) : pathOrKey;
|
||||
}
|
||||
if (pathOrKey.indexOf(FILE_PREFIX) === 0) {
|
||||
var meta = window._soonFileMeta;
|
||||
if (meta && meta.name) return meta.name;
|
||||
@@ -333,12 +505,21 @@
|
||||
window.soonNormalizeSoonName = soonNormalizeSoonName;
|
||||
window.soonApplyCloudMeta = soonApplyCloudMeta;
|
||||
window.soonBindFileMeta = soonBindFileMeta;
|
||||
window.soonSyncOpenNavigation = soonSyncOpenNavigation;
|
||||
window.soonResolveOpenFileKey = soonResolveOpenFileKey;
|
||||
window.soonConsumeOpenMeta = soonConsumeOpenMeta;
|
||||
window.soonFormatOpenTitle = soonFormatOpenTitle;
|
||||
window.soonGuardCloudSave = soonGuardCloudSave;
|
||||
window.soonGuardPreviewDeliver = soonGuardPreviewDeliver;
|
||||
window.soonHandlePayReturn = soonHandlePayReturn;
|
||||
window.soonOpenSoonJsonLocally = soonOpenSoonJsonLocally;
|
||||
window.soonPutSoonSession = soonPutSoonSession;
|
||||
window.soonScheduleCloudImport = soonScheduleCloudImport;
|
||||
window.soonTryConsumeCloudImport = soonTryConsumeCloudImport;
|
||||
window.soonClearPendingImport = soonClearPendingImport;
|
||||
window.soonReportOpenLoadError = soonReportOpenLoadError;
|
||||
window.soonParseTemplateKey = soonParseTemplateKey;
|
||||
window.soonMakeTemplateKey = soonMakeTemplateKey;
|
||||
window.soonSoonTypeFromJson = soonSoonTypeFromJson;
|
||||
window.soonLoadMembership = soonLoadMembership;
|
||||
window.soonApplyMembership = soonApplyMembership;
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
return '未获取到支付信息';
|
||||
}
|
||||
|
||||
function payEmptyStateHtml(channel) {
|
||||
function paySheetHtml(opts) {
|
||||
opts = opts || {};
|
||||
var resumeOrderNo = opts.orderNo || null;
|
||||
var channels = opts.displayChannels || _displayChannels;
|
||||
|
||||
Reference in New Issue
Block a user