fix(web): 修复 .soon/模板加载、旧文件兼容与另存为离开提示
- 删除 design1 ui 遗留代码,修复加载竞态与新建不弹保存提示 - cloud-files 归一化旧版 .soon,IndexedDB 写入完成后再跳转设计页 - 模板/本地 .soon 首次保存须另存为,离开前统一确认 - 发版缓存 bust(version.js、soon-cache.js)及宝塔 Nginx 配置文档 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -75,28 +75,7 @@ function soonDesign1ApplyDiscAlpha(tctx, w, h, holeDiameterMm) {
|
||||
tctx.restore();
|
||||
}
|
||||
|
||||
function soonDesign1ApplyDiscMatte(tctx, w, h, holeDiameterMm, color) {
|
||||
var snap = document.createElement('canvas');
|
||||
snap.width = w;
|
||||
snap.height = h;
|
||||
snap.getContext('2d').drawImage(tctx.canvas, 0, 0);
|
||||
tctx.fillStyle = color;
|
||||
tctx.fillRect(0, 0, w, h);
|
||||
tctx.save();
|
||||
var cx = w / 2;
|
||||
var cy = h / 2;
|
||||
var rOuter = w / 2;
|
||||
var rInner = rOuter * (holeDiameterMm / 120);
|
||||
tctx.beginPath();
|
||||
tctx.arc(cx, cy, rOuter, 0, Math.PI * 2);
|
||||
tctx.moveTo(cx + rInner, cy);
|
||||
tctx.arc(cx, cy, rInner, 0, Math.PI * 2, true);
|
||||
tctx.clip('evenodd');
|
||||
tctx.drawImage(snap, 0, 0);
|
||||
tctx.restore();
|
||||
}
|
||||
|
||||
function soonDesign1CaptureCanvasRect(canvas, outW, outH, format, quality, clipDisc, discMatte) {
|
||||
function soonDesign1CaptureCanvasRect(canvas, outW, outH, format, quality, clipDisc) {
|
||||
var bg = window.background_image1 || window.background_image;
|
||||
if (!canvas || !bg) return '';
|
||||
var srcEl = canvas.lowerCanvasEl;
|
||||
@@ -117,9 +96,7 @@ function soonDesign1CaptureCanvasRect(canvas, outW, outH, format, quality, clipD
|
||||
bg.left * retina, bg.top * retina, sw * retina, sh * retina,
|
||||
0, 0, outW, outH
|
||||
);
|
||||
if (discMatte) {
|
||||
soonDesign1ApplyDiscMatte(tctx, outW, outH, soonDesign1GetHoleDiameterMm(canvas), discMatte);
|
||||
} else if (clipDisc && format !== 'jpeg') {
|
||||
if (clipDisc && format !== 'jpeg') {
|
||||
soonDesign1ApplyDiscAlpha(tctx, outW, outH, soonDesign1GetHoleDiameterMm(canvas));
|
||||
}
|
||||
if (format === 'jpeg') return tmp.toDataURL('image/jpeg', quality == null ? 0.75 : quality);
|
||||
@@ -128,14 +105,80 @@ function soonDesign1CaptureCanvasRect(canvas, outW, outH, format, quality, clipD
|
||||
|
||||
function soonDesign1CaptureDiscPng(canvas, outW, outH) {
|
||||
window._soonSkipDesign1CdMask = true;
|
||||
if (canvas.discardActiveObject) canvas.discardActiveObject();
|
||||
canvas.renderAll();
|
||||
var url = soonDesign1CaptureCanvasRect(canvas, outW, outH, 'png', null, true);
|
||||
window._soonSkipDesign1CdMask = false;
|
||||
canvas.renderAll();
|
||||
return url;
|
||||
try {
|
||||
if (canvas.discardActiveObject) canvas.discardActiveObject();
|
||||
canvas.renderAll();
|
||||
return soonDesign1CaptureCanvasRect(canvas, outW, outH, 'png', null, true);
|
||||
} finally {
|
||||
window._soonSkipDesign1CdMask = false;
|
||||
canvas.renderAll();
|
||||
}
|
||||
}
|
||||
|
||||
function soonStripDesign1HeavyFields(con_o) {
|
||||
if (!con_o) return con_o;
|
||||
delete con_o.frontColorPic;
|
||||
delete con_o.backColorPic;
|
||||
delete con_o.frontBlackPic;
|
||||
delete con_o.backBlackPic;
|
||||
delete con_o.frontData;
|
||||
delete con_o.backData;
|
||||
delete con_o.backDisplayPic;
|
||||
if (typeof con_o.frontDisplayPic === 'string' && con_o.frontDisplayPic.length > 120000) {
|
||||
delete con_o.frontDisplayPic;
|
||||
}
|
||||
return con_o;
|
||||
}
|
||||
|
||||
function soonNormalizeSoonJson(j) {
|
||||
if (!j || typeof j !== 'object') return null;
|
||||
soonStripDesign1HeavyFields(j);
|
||||
if (!j.f || !j.f.objects || !Array.isArray(j.f.objects)) {
|
||||
if (j.objects && Array.isArray(j.objects) && j.objects.length > 0) {
|
||||
j.f = { version: j.version || '4.6.0', objects: j.objects, hoverCursor: j.hoverCursor || 'move' };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (j.f.objects.length === 0) return null;
|
||||
if (!j.b || !j.b.objects || !Array.isArray(j.b.objects)) {
|
||||
j.b = { version: '4.6.0', objects: [], hoverCursor: 'move' };
|
||||
}
|
||||
if (!j.fo) j.fo = [];
|
||||
if (!j.bo) j.bo = [];
|
||||
var o0 = j.f.objects[0];
|
||||
if (o0) {
|
||||
if (o0.left == null || isNaN(o0.left)) o0.left = 0;
|
||||
if (o0.top == null || isNaN(o0.top)) o0.top = 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
window.soonNormalizeSoonJson = soonNormalizeSoonJson;
|
||||
|
||||
function soonRunWhenDesignBgReady(fn, onTimeout) {
|
||||
if (typeof fn !== 'function') return;
|
||||
function ready() {
|
||||
return !!(window.background_image1 || window.background_image);
|
||||
}
|
||||
if (ready()) {
|
||||
fn();
|
||||
return;
|
||||
}
|
||||
var n = 0;
|
||||
(function tick() {
|
||||
if (ready()) {
|
||||
fn();
|
||||
return;
|
||||
}
|
||||
if (++n > 120) {
|
||||
if (typeof onTimeout === 'function') onTimeout();
|
||||
return;
|
||||
}
|
||||
setTimeout(tick, 50);
|
||||
})();
|
||||
}
|
||||
window.soonRunWhenDesignBgReady = soonRunWhenDesignBgReady;
|
||||
|
||||
// 将 display_func 附加到 window 对象,确保全局可访问
|
||||
window.display_func = function display_func(img1, img2, img3) {
|
||||
$("#base_control").hide();
|
||||
@@ -1171,14 +1214,20 @@ window.regenerateQrCodesAndBarcodes = function regenerateQrCodesAndBarcodes(canv
|
||||
window.openFile = function open(file, jAlready) {
|
||||
if (!file) return;
|
||||
function doOpenWithJson(j) {
|
||||
if (!j || !background_image) return;
|
||||
if (!j.f || !j.f.objects || !Array.isArray(j.f.objects) || j.f.objects.length === 0) return;
|
||||
if (!j.b || !j.b.objects || !Array.isArray(j.b.objects) || j.b.objects.length === 0) {
|
||||
j.b = { version: '4.6.0', objects: [], hoverCursor: 'move' };
|
||||
j = soonNormalizeSoonJson(j);
|
||||
if (!j) {
|
||||
if (typeof window.soonReportOpenLoadError === 'function') window.soonReportOpenLoadError('模板/文件加载失败');
|
||||
return;
|
||||
}
|
||||
function runOpen() {
|
||||
var bgRef = window.background_image1 || window.background_image;
|
||||
if (!bgRef) {
|
||||
if (typeof window.soonReportOpenLoadError === 'function') window.soonReportOpenLoadError('模板/文件加载失败');
|
||||
return;
|
||||
}
|
||||
openAs.name = file;
|
||||
var left = background_image.left;
|
||||
var top = background_image.top;
|
||||
var left = bgRef.left;
|
||||
var top = bgRef.top;
|
||||
var new_left = j.f.objects[0].left;
|
||||
var new_top = j.f.objects[0].top;
|
||||
for (var i = 0; i < j.f.objects.length; i++) {
|
||||
@@ -1249,6 +1298,10 @@ window.openFile = function open(file, jAlready) {
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
soonRunWhenDesignBgReady(runOpen, function () {
|
||||
if (typeof window.soonReportOpenLoadError === 'function') window.soonReportOpenLoadError('模板/文件加载失败');
|
||||
});
|
||||
}
|
||||
if (arguments.length >= 2 && jAlready) {
|
||||
doOpenWithJson(jAlready);
|
||||
@@ -1257,12 +1310,22 @@ window.openFile = function open(file, jAlready) {
|
||||
}
|
||||
file = resolveDiskPath(file);
|
||||
if (window.platformBridge && window.platformBridge.readJsonFile) {
|
||||
if (typeof window.soonShowOpenFileLoading === 'function') window.soonShowOpenFileLoading();
|
||||
return window.platformBridge.readJsonFile(file).then(function(j) {
|
||||
if (typeof window.soonHideOpenFileLoading === 'function') window.soonHideOpenFileLoading();
|
||||
if (j) {
|
||||
doOpenWithJson(j);
|
||||
openAs.name = file;
|
||||
} else if (typeof window.soonReportOpenLoadError === 'function') {
|
||||
window.soonReportOpenLoadError('模板/文件加载失败');
|
||||
}
|
||||
}).catch(function() {});
|
||||
}).catch(function () {
|
||||
if (typeof window.soonReportOpenLoadError === 'function') window.soonReportOpenLoadError('模板/文件加载失败');
|
||||
else if (typeof window.soonHideOpenFileLoading === 'function') window.soonHideOpenFileLoading();
|
||||
}).finally(function () {
|
||||
if (typeof window.soonHideOpenFileLoading === 'function') window.soonHideOpenFileLoading();
|
||||
if (typeof window.soonCleanupLayerMask === 'function') window.soonCleanupLayerMask();
|
||||
});
|
||||
}
|
||||
try {
|
||||
var fs = typeof require !== 'undefined' ? require('fs') : null;
|
||||
@@ -1352,6 +1415,9 @@ function saveAs(op1, callback) {
|
||||
|
||||
let o = { f: j, b: {}, fo: objs1, bo: objs2 };
|
||||
let con_o = Object.assign(o, op1);
|
||||
con_o.soonType = 1;
|
||||
if (typeof window.soonApplySavePreview === 'function') window.soonApplySavePreview(con_o, canvas1);
|
||||
soonStripDesign1HeavyFields(con_o);
|
||||
var dialogApi = (typeof dialog !== 'undefined' && dialog) ? dialog : (window.platformBridge && window.platformBridge.showSaveDialog ? { showSaveDialog: function(opts) { return window.platformBridge.showSaveDialog(opts); } } : null);
|
||||
if (!dialogApi) return;
|
||||
dialogApi.showSaveDialog({
|
||||
@@ -1364,7 +1430,6 @@ function saveAs(op1, callback) {
|
||||
var pathExt = (typeof window !== 'undefined' && window.path && window.path.extname) ? window.path.extname(fp) : (fp.indexOf('.') >= 0 ? fp.slice(fp.lastIndexOf('.')) : '');
|
||||
if (pathExt !== '.soon') fp = (fp || 'design').replace(/\.soon$/i, '') + '.soon';
|
||||
var content = JSON.stringify(con_o);
|
||||
con_o.soonType = 1;
|
||||
if (window.platformBridge && window.platformBridge.writeFile) {
|
||||
await window.platformBridge.writeFile(result.fileHandle || fp, content);
|
||||
openAs.name = isWebPortal() ? ('soondesign_session:' + fp) : (result.filePath || fp);
|
||||
@@ -1418,8 +1483,10 @@ function save(op1, callback) {
|
||||
|
||||
let o = { f: j, b: {}, fo: objs1, bo: objs2 };
|
||||
let con_o = Object.assign(o, op1);
|
||||
con_o.soonType = 1;
|
||||
if (typeof window.soonApplySavePreview === 'function') window.soonApplySavePreview(con_o, canvas1);
|
||||
soonStripDesign1HeavyFields(con_o);
|
||||
if (openAs.name != "") {
|
||||
con_o.soonType = 1;
|
||||
var content = JSON.stringify(con_o);
|
||||
if (isWebPortal() && openAs.name.indexOf('soondesign_session:') === 0) {
|
||||
webSessionStore(content, openAs.name);
|
||||
@@ -1463,7 +1530,6 @@ function save(op1, callback) {
|
||||
var pathExt = (typeof window !== 'undefined' && window.path && window.path.extname) ? window.path.extname(fp) : (fp.indexOf('.') >= 0 ? fp.slice(fp.lastIndexOf('.')) : '');
|
||||
if (pathExt !== '.soon') fp = (fp || 'design').replace(/\.soon$/i, '') + '.soon';
|
||||
var content = JSON.stringify(con_o);
|
||||
con_o.soonType = 1;
|
||||
if (window.platformBridge && window.platformBridge.writeFile) {
|
||||
await window.platformBridge.writeFile(result.fileHandle || fp, content);
|
||||
openAs.name = isWebPortal() ? ('soondesign_session:' + fp) : (result.filePath || fp);
|
||||
|
||||
Reference in New Issue
Block a user