fix(web): 本地优先保存与 design 页体验修复
- 保存先写本地缓存,登录后可选云端同步;退出登录不再因文件操作跳转登录 - 修复 Layui 遮罩残留、design2 保存后线条、toast 被 finally 提前关闭 - 保存过程恢复 loading spinner;成功提示 2.5 秒 - 云端 payload 瘦身与体积超限提示;后端 schema 迁移与 FileService 容错 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -85,16 +85,21 @@
|
||||
fullUrl = getApiBase() + '/' + String(url).replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
var hadSession = !!(token || getRefreshToken());
|
||||
|
||||
return fetch(fullUrl, opts).then(function (response) {
|
||||
if (response.status !== 401) return response;
|
||||
if (!getRefreshToken()) return response;
|
||||
return refreshAccessToken().then(function (newToken) {
|
||||
var retryHeaders = Object.assign({}, opts.headers || {});
|
||||
retryHeaders['Authorization'] = 'Bearer ' + newToken;
|
||||
var retryOpts = Object.assign({}, opts, { headers: retryHeaders });
|
||||
return fetch(fullUrl, retryOpts);
|
||||
}).catch(function () {
|
||||
clearSession();
|
||||
redirectToLogin();
|
||||
if (hadSession) {
|
||||
clearSession();
|
||||
redirectToLogin();
|
||||
}
|
||||
return response;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,22 +88,29 @@
|
||||
}
|
||||
});
|
||||
if (hidden.length) canvas.renderAll();
|
||||
window._soonSkipDesign1CdMask = true;
|
||||
var mult = 0.18;
|
||||
var quality = 0.72;
|
||||
var url = '';
|
||||
for (var i = 0; i < 3; i++) {
|
||||
try {
|
||||
var candidate = canvas.toDataURL({ format: 'jpeg', quality: quality, multiplier: mult });
|
||||
if (candidate && candidate.indexOf('data:image/') === 0 && candidate.length <= THUMB_MAX) {
|
||||
url = candidate;
|
||||
break;
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
quality -= 0.18;
|
||||
mult -= 0.04;
|
||||
try {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
try {
|
||||
var candidate = canvas.toDataURL({ format: 'jpeg', quality: quality, multiplier: mult });
|
||||
if (candidate && candidate.indexOf('data:image/') === 0 && candidate.length <= THUMB_MAX) {
|
||||
url = candidate;
|
||||
break;
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
quality -= 0.18;
|
||||
mult -= 0.04;
|
||||
}
|
||||
} finally {
|
||||
window._soonSkipDesign1CdMask = false;
|
||||
}
|
||||
hidden.forEach(function (obj) { obj.visible = true; });
|
||||
if (hidden.length) canvas.renderAll();
|
||||
canvas.renderAll();
|
||||
if (typeof window.soonClearFabricOverlay === 'function') window.soonClearFabricOverlay(canvas);
|
||||
if (canvas.requestRenderAll) canvas.requestRenderAll();
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -134,8 +141,20 @@
|
||||
return soonEnsureSoonExt(name);
|
||||
}
|
||||
|
||||
function dismissLayerMask() {
|
||||
if (typeof window.soonCleanupLayerMask === 'function') {
|
||||
window.soonCleanupLayerMask();
|
||||
return;
|
||||
}
|
||||
soonHideOpenFileLoading();
|
||||
invokeLayerCleanup();
|
||||
}
|
||||
|
||||
function soonReportSaveError(err) {
|
||||
if (typeof window.soonFinishSaveUi === 'function') window.soonFinishSaveUi();
|
||||
else dismissLayerMask();
|
||||
if (err && err.conflictSynced) return;
|
||||
if (err && err.apiNotified) return;
|
||||
if (typeof window.soonShowApiError === 'function') {
|
||||
window.soonShowApiError({
|
||||
status: err && err.status,
|
||||
@@ -149,11 +168,27 @@
|
||||
|
||||
function soonWriteSoonContentWeb(fp, content, prevOpenKey, onDone, onError) {
|
||||
if (!window.platformBridge || !window.platformBridge.writeFile) return false;
|
||||
window.platformBridge.writeFile(fp, content).then(function (res) {
|
||||
if (typeof window.soonShowOpenFileLoading === 'function') window.soonShowOpenFileLoading();
|
||||
var writePromise;
|
||||
try {
|
||||
writePromise = window.platformBridge.writeFile(fp, content);
|
||||
} catch (syncErr) {
|
||||
dismissLayerMask();
|
||||
if (typeof onError === 'function') onError(syncErr);
|
||||
else soonReportSaveError(syncErr);
|
||||
return true;
|
||||
}
|
||||
if (!writePromise || typeof writePromise.then !== 'function') {
|
||||
dismissLayerMask();
|
||||
return true;
|
||||
}
|
||||
writePromise.then(function (res) {
|
||||
if (typeof onDone === 'function') onDone(res, prevOpenKey);
|
||||
}).catch(function (err) {
|
||||
if (typeof onError === 'function') onError(err);
|
||||
else soonReportSaveError(err);
|
||||
}).finally(function () {
|
||||
dismissLayerMask();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -656,37 +691,52 @@
|
||||
});
|
||||
}
|
||||
|
||||
function invokeLayerCleanup() {
|
||||
if (typeof window.soonCleanupLayerMask === 'function') {
|
||||
window.soonCleanupLayerMask();
|
||||
}
|
||||
}
|
||||
|
||||
function soonReportOpenLoadError(message) {
|
||||
soonHideOpenFileLoading();
|
||||
invokeLayerCleanup();
|
||||
soonToast(message || '文件加载失败', 'error');
|
||||
}
|
||||
|
||||
function soonShowOpenFileLoading() {
|
||||
if (typeof layer === 'undefined' || !layer.load) return;
|
||||
soonHideOpenFileLoading();
|
||||
window._soonOpenLoadIdx = layer.load(1, { shade: [0.12, '#000'] });
|
||||
window._soonOpenLoadIdx = layer.load(1, { shade: 0 });
|
||||
}
|
||||
|
||||
function soonHideOpenFileLoading() {
|
||||
if (window._soonOpenLoadIdx == null) return;
|
||||
if (typeof layer !== 'undefined' && layer.close) layer.close(window._soonOpenLoadIdx);
|
||||
if (typeof layer !== 'undefined' && layer.closeAll) {
|
||||
layer.closeAll('loading');
|
||||
}
|
||||
if (window._soonOpenLoadIdx != null && typeof layer !== 'undefined' && layer.close) {
|
||||
try { layer.close(window._soonOpenLoadIdx); } catch (e) { /* ignore */ }
|
||||
}
|
||||
window._soonOpenLoadIdx = null;
|
||||
invokeLayerCleanup();
|
||||
}
|
||||
|
||||
function soonToast(message, type) {
|
||||
if (typeof window.soonToast === 'function') window.soonToast(message, type);
|
||||
}
|
||||
|
||||
function soonRequireLogin(actionLabel) {
|
||||
function soonRequireLogin(actionLabel, options) {
|
||||
options = options || {};
|
||||
if (soonGetAccessToken()) return true;
|
||||
var label = actionLabel || '继续';
|
||||
soonToast('请先登录后再' + label, 'warn');
|
||||
if (typeof window.soonRedirectToLogin === 'function') {
|
||||
setTimeout(function () { window.soonRedirectToLogin(); }, 600);
|
||||
} else if (typeof window.redirectToLogin === 'function') {
|
||||
setTimeout(function () { window.redirectToLogin(); }, 600);
|
||||
} else {
|
||||
window.location.href = 'login.web.html';
|
||||
soonToast('请先登录后再' + (label || '操作'), 'warn');
|
||||
if (options.redirect) {
|
||||
if (typeof window.soonRedirectToLogin === 'function') {
|
||||
setTimeout(function () { window.soonRedirectToLogin(); }, 600);
|
||||
} else if (typeof window.redirectToLogin === 'function') {
|
||||
setTimeout(function () { window.redirectToLogin(); }, 600);
|
||||
} else {
|
||||
window.location.href = 'login.web.html';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -724,8 +774,8 @@
|
||||
else if (info.status === 409) kind = 'warn';
|
||||
else if (info.status === 413) kind = 'warn';
|
||||
soonToast(info.message, kind);
|
||||
if (info.status === 401) {
|
||||
soonRequireLogin('操作');
|
||||
if (info.status === 401 && info.requireLogin) {
|
||||
soonRequireLogin('操作', { redirect: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
if (idx != null) layer.close(idx);
|
||||
if (payIdx != null) layer.close(payIdx);
|
||||
}
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
if (fireStay && opts && typeof opts.onStay === 'function') opts.onStay();
|
||||
}
|
||||
|
||||
@@ -93,6 +94,7 @@
|
||||
_gate.payIndex = null;
|
||||
if (typeof layer !== 'undefined' && gateIdx != null) layer.close(gateIdx);
|
||||
_gate = { index: null, payIndex: null, plan: null, gateOpts: null };
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
toast('恭喜您,会员已激活!', 'success');
|
||||
if (typeof window.soonLoadMembership === 'function') {
|
||||
window.soonLoadMembership(true).then(function () {
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
if (idx != null && typeof layer !== 'undefined') {
|
||||
try { layer.close(idx); } catch (e) { /* ignore */ }
|
||||
}
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
}
|
||||
|
||||
function bindModal(modal) {
|
||||
|
||||
@@ -607,6 +607,7 @@
|
||||
displayChannels: channels,
|
||||
onPaid: function () {
|
||||
layer.close(idx);
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
if (typeof opts.onPaid === 'function') opts.onPaid();
|
||||
},
|
||||
onBack: opts.onBack,
|
||||
@@ -617,6 +618,7 @@
|
||||
},
|
||||
end: function () {
|
||||
if (payCtrl) payCtrl.destroy();
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
if (typeof opts.onClose === 'function') opts.onClose();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
localStorage.removeItem('soon_access');
|
||||
localStorage.removeItem('soon_refresh');
|
||||
}
|
||||
if (typeof window.soonApplyMembership === 'function') {
|
||||
window.soonApplyMembership(null);
|
||||
}
|
||||
}
|
||||
|
||||
function initClearCache() {
|
||||
|
||||
@@ -1,14 +1,81 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function soonCleanupLayerMask() {
|
||||
if (typeof layer !== 'undefined' && layer.closeAll) {
|
||||
layer.closeAll('loading');
|
||||
}
|
||||
if (window._soonOpenLoadIdx != null && typeof layer !== 'undefined' && layer.close) {
|
||||
try { layer.close(window._soonOpenLoadIdx); } catch (e) { /* ignore */ }
|
||||
window._soonOpenLoadIdx = null;
|
||||
}
|
||||
if (typeof document === 'undefined') return;
|
||||
var layers = document.querySelectorAll('.layui-layer');
|
||||
for (var j = 0; j < layers.length; j++) {
|
||||
if (layers[j].getAttribute('type') !== 'loading') continue;
|
||||
var loadTimes = layers[j].getAttribute('times');
|
||||
if (loadTimes && typeof layer !== 'undefined' && layer.close) {
|
||||
try { layer.close(loadTimes); } catch (e2) { /* ignore */ }
|
||||
}
|
||||
}
|
||||
var shades = document.querySelectorAll('.layui-layer-shade');
|
||||
for (var i = shades.length - 1; i >= 0; i--) {
|
||||
var shade = shades[i];
|
||||
var times = shade.getAttribute('times');
|
||||
var layerEl = times ? document.getElementById('layui-layer' + times) : null;
|
||||
if (!layerEl || layerEl.getAttribute('type') === 'loading') {
|
||||
if (shade.parentNode) shade.parentNode.removeChild(shade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function soonLayerDismiss(type) {
|
||||
if (typeof layer !== 'undefined' && layer.closeAll) {
|
||||
layer.closeAll(type);
|
||||
}
|
||||
soonCleanupLayerMask();
|
||||
}
|
||||
|
||||
function soonClearFabricOverlay(canvas) {
|
||||
if (!canvas || !canvas.contextTop) return;
|
||||
if (typeof canvas.clearContext === 'function') {
|
||||
canvas.clearContext(canvas.contextTop);
|
||||
}
|
||||
}
|
||||
|
||||
function soonRefreshDesignCanvases() {
|
||||
var names = ['canvas1', 'canvas2', 'canvas'];
|
||||
for (var n = 0; n < names.length; n++) {
|
||||
var c = window[names[n]];
|
||||
if (!c || typeof c.renderAll !== 'function') continue;
|
||||
if (c.discardActiveObject) c.discardActiveObject();
|
||||
soonClearFabricOverlay(c);
|
||||
if (c.requestRenderAll) c.requestRenderAll();
|
||||
else c.renderAll();
|
||||
}
|
||||
}
|
||||
|
||||
function soonFinishSaveUi() {
|
||||
if (typeof window.soonHideOpenFileLoading === 'function') window.soonHideOpenFileLoading();
|
||||
else soonCleanupLayerMask();
|
||||
soonRefreshDesignCanvases();
|
||||
if (typeof requestAnimationFrame === 'function') {
|
||||
requestAnimationFrame(function () {
|
||||
soonCleanupLayerMask();
|
||||
soonRefreshDesignCanvases();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function soonToast(message, type) {
|
||||
if (typeof layer === 'undefined' || !layer.msg) return;
|
||||
var skin = 'soon-toast';
|
||||
if (type === 'success') skin += ' soon-toast--success';
|
||||
else if (type === 'error') skin += ' soon-toast--error';
|
||||
else if (type === 'warn') skin += ' soon-toast--warn';
|
||||
var time = type === 'success' ? 2500 : (type === 'error' ? 4200 : 3600);
|
||||
layer.msg(message, {
|
||||
time: 2400,
|
||||
time: time,
|
||||
shade: 0,
|
||||
offset: '72px',
|
||||
icon: -1,
|
||||
@@ -16,5 +83,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
window.soonCleanupLayerMask = soonCleanupLayerMask;
|
||||
window.soonLayerDismiss = soonLayerDismiss;
|
||||
window.soonClearFabricOverlay = soonClearFabricOverlay;
|
||||
window.soonRefreshDesignCanvases = soonRefreshDesignCanvases;
|
||||
window.soonFinishSaveUi = soonFinishSaveUi;
|
||||
window.soonToast = soonToast;
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user