(function () { '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() { if (typeof window === 'undefined') return false; if (window.SOON_DEPLOY_CONFIG) return true; return !!(window.platformBridge && window.fs == null); } function soonGetAccessToken() { if (typeof window.soonGetAccessToken === 'function') { return window.soonGetAccessToken(); } try { return localStorage.getItem('soon_access') || ''; } catch (e) { return ''; } } function soonParseFileKey(key) { if (!key || typeof key !== 'string') return null; var m = key.match(/^soondesign_file:(\d+)(?::v(\d+))?$/); if (!m) return null; return { id: parseInt(m[1], 10), version: m[2] ? parseInt(m[2], 10) : null }; } function soonMakeFileKey(id, version) { return FILE_PREFIX + id + ':v' + version; } function soonIsTemplateKey(key) { return !!(key && typeof key === 'string' && key.indexOf(TEMPLATE_PREFIX) === 0); } function soonNeedsSaveDialog(key) { return !key || soonIsTemplateKey(key); } function soonDefaultNewSoonName() { var d = new Date(); function pad(n) { return n < 10 ? '0' + n : String(n); } var yy = String(d.getFullYear()).slice(-2); var stamp = yy + pad(d.getMonth() + 1) + pad(d.getDate()) + pad(d.getHours()) + pad(d.getMinutes()) + pad(d.getSeconds()); return 'design' + stamp + '.soon'; } function soonEnsureSoonExt(name) { var n = String(name || 'design.soon').trim(); if (!/\.soon$/i.test(n)) n = (n.replace(/\.soon$/i, '') || 'design') + '.soon'; return n; } function soonSessionSlug(nameOrKey) { var s = String(nameOrKey || 'design').replace(/^soondesign_session:/, '').split(/[/\\]/).pop(); s = s.replace(/\.soon$/i, ''); s = s.replace(/-\d{10,}$/, ''); return s || 'design'; } function soonMakeSessionKey(nameOrKey) { return 'soondesign_session:' + soonSessionSlug(nameOrKey); } function soonSessionDisplayName(keyOrName) { return soonEnsureSoonExt(soonSessionSlug(keyOrName)); } function soonBuildSavePreviewPic(canvas) { var THUMB_MAX = 102400; if (!canvas || typeof canvas.getObjects !== 'function') return ''; var hidden = []; canvas.getObjects().forEach(function (obj) { if (obj.isGuideLine) { hidden.push(obj); obj.visible = false; } }); if (hidden.length) canvas.renderAll(); window._soonSkipDesign1CdMask = true; var mult = 0.18; var quality = 0.72; var url = ''; 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; }); canvas.renderAll(); if (typeof window.soonClearFabricOverlay === 'function') window.soonClearFabricOverlay(canvas); if (canvas.requestRenderAll) canvas.requestRenderAll(); return url; } function soonApplySavePreview(con_o, canvas) { if (!con_o) return con_o; var pic = soonBuildSavePreviewPic(canvas); if (pic) con_o.frontDisplayPic = pic; return con_o; } function soonSaveDialogDefaultPath(openKey) { if (soonNeedsSaveDialog(openKey)) return soonDefaultNewSoonName(); return openKey || undefined; } function soonEnsureSaveFileName(fp) { var name = String(fp || 'design.soon'); if (typeof window !== 'undefined' && window.platformBridge && window.fs == null) { return soonEnsureSoonExt(name); } if (typeof window !== 'undefined' && window.path && window.path.extname) { if (window.path.extname(name) !== '.soon') { name = (name.replace(/\.soon$/i, '') || 'design') + '.soon'; } } else if (!/\.soon$/i.test(name)) { name = (name.replace(/\.soon$/i, '') || 'design') + '.soon'; } 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, message: (err && err.message) || '保存失败', code: err && err.code }); } else { soonToast((err && err.message) || '保存失败', 'error'); } } function soonWriteSoonContentWeb(fp, content, prevOpenKey, onDone, onError) { if (!window.platformBridge || !window.platformBridge.writeFile) return false; 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; } function soonDownloadBlob(filename, content, mime) { var name = soonEnsureSoonExt(filename || 'design.soon'); var blob = content instanceof Blob ? content : new Blob([content], { type: mime || 'application/json' }); var a = document.createElement('a'); a.download = name; a.href = URL.createObjectURL(blob); a.click(); URL.revokeObjectURL(a.href); } function soonDownloadRecentItem(item) { if (!item) return Promise.resolve(); var key = item.filePath || item.key || ''; var name = soonEnsureSoonExt(item.name || 'design.soon'); var kind = item.kind || (typeof window.soonRecentKindFromKey === 'function' ? window.soonRecentKindFromKey(key) : 'local'); if (kind === 'template') { var tpl = soonParseTemplateKey(key); if (!tpl) { soonToast('无法下载模板', 'error'); return Promise.resolve(); } var base = (window.SOON_DEPLOY_CONFIG && window.SOON_DEPLOY_CONFIG.api_v1_base) || ''; if (!base) { soonToast('下载地址未配置', 'error'); return Promise.resolve(); } return fetch(base + '/templates/' + tpl.id + '/file', { headers: { Accept: 'application/json' } }) .then(function (r) { if (!r.ok) throw new Error('download_failed'); return r.text(); }) .then(function (text) { soonDownloadBlob(name, text, 'application/json'); }) .catch(function () { soonToast('模板下载失败', 'error'); }); } if (kind === 'cloud') { function tryCloudApiDownload() { if (!item.fileId || !soonGetAccessToken()) return Promise.resolve(false); var bridge = window.platformBridge; if (!bridge || typeof bridge.downloadCloudFile !== 'function') return Promise.resolve(false); return bridge.downloadCloudFile(item.fileId, name).then(function () { return true; }).catch(function () { soonToast('下载失败', 'error'); return true; }); } if (key && typeof window.soonLocalGet === 'function') { return window.soonLocalGet(key).then(function (hit) { if (hit && hit.json) { soonDownloadBlob(name, JSON.stringify(hit.json), 'application/json'); return; } return tryCloudApiDownload().then(function (done) { if (!done) soonToast('请先打开或保存该文件', 'warn'); }); }); } return tryCloudApiDownload().then(function (done) { if (!done) soonToast('请先打开或保存该文件', 'warn'); }); } if (key.indexOf('soondesign_session:') === 0 || kind === 'local') { if (typeof window.soonLocalGet !== 'function') { soonToast('本地缓存不可用', 'error'); return Promise.resolve(); } return window.soonLocalGet(key).then(function (hit) { if (!hit || !hit.json) { soonToast('请先打开或保存该文件', 'warn'); return; } soonDownloadBlob(name, JSON.stringify(hit.json), 'application/json'); }); } soonToast('无法下载该文件', 'warn'); return Promise.resolve(); } function soonLookupRecentCloudName(fileId) { if (!fileId || typeof window.soonRecentList !== 'function') return ''; var items = window.soonRecentList(); for (var i = 0; i < items.length; i++) { if (items[i].fileId === fileId && items[i].name) return items[i].name; } return ''; } function soonResolveCloudFileName(fileKey) { if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) return ''; var parsed = soonParseFileKey(fileKey); if (!parsed) return ''; var meta = window._soonFileMeta; if (meta && meta.id === parsed.id && meta.name) return meta.name; var recentName = soonLookupRecentCloudName(parsed.id); if (recentName) return recentName; return ''; } function soonNormalizeSoonName(pathOrName) { var n = String(pathOrName || 'design.soon'); if (n.indexOf(FILE_PREFIX) === 0) { var resolved = soonResolveCloudFileName(n); if (resolved) return resolved; return 'design.soon'; } if (n.indexOf(TEMPLATE_PREFIX) === 0) { return soonDefaultNewSoonName(); } if (n.indexOf('soondesign_session:') === 0) { return soonSessionDisplayName(n); } n = n.split(/[/\\]/).pop(); if (!/\.soon$/i.test(n)) n = (n.replace(/\.soon$/i, '') || 'design') + '.soon'; return n; } function soonApplyCloudMeta(data) { if (!data || !data.id) return null; window._soonFileMeta = { id: data.id, version: data.version, name: data.name }; 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) { window._soonFileMeta = null; return; } var parsed = soonParseFileKey(fileKey); if (!parsed) return; var prev = window._soonFileMeta || {}; var name = (opts && opts.name) || (prev.id === parsed.id ? prev.name : '') || ''; if (!name) name = soonLookupRecentCloudName(parsed.id); window._soonFileMeta = { id: parsed.id, version: parsed.version != null ? parsed.version : prev.version, name: name }; } function soonFormatOpenTitle(name) { if (!name) return ''; if (typeof window.soonDisplayFileName === 'function') return window.soonDisplayFileName(name); return String(name).split(/[/\\]/).pop(); } var _membership = { loaded: false, isMember: false, name: '普通用户', tier: 'free', loading: null, }; function soonApiBase() { var cfg = (typeof window !== 'undefined' && window.SOON_DEPLOY_CONFIG && window.SOON_DEPLOY_CONFIG.api_v1_base); if (cfg) return String(cfg).replace(/\/+$/, ''); if (typeof window !== 'undefined' && window.location) { return window.location.origin + '/api/v1'; } return '/api/v1'; } function soonApplyMembership(data) { var m = data || {}; var sub = m.subscription || {}; var isMember = m.is_member === true || m.tier === 'member' || m.tier === 'pro' || (sub.status && sub.status !== 'free' && sub.status !== 'expired'); _membership = { loaded: true, isMember: !!isMember, name: isMember ? (m.name || '会员') : '普通用户', tier: m.tier || (isMember ? 'member' : 'free'), loading: null, }; if (typeof window.soonRefreshPortalIdentity === 'function') { window.soonRefreshPortalIdentity(); } return _membership; } function soonRefreshPortalIdentity() { var el = document.getElementById('auth_identity'); if (!el) return; if (!soonGetAccessToken()) { el.style.display = 'none'; el.textContent = ''; return; } if (!_membership.loaded) { soonLoadMembership(false).then(function () { soonRefreshPortalIdentity(); }); return; } var text; var cls = 'soon-portal-identity'; if (_membership.isMember) { cls += ' soon-portal-identity--member'; text = _membership.name || '会员'; } else { cls += ' soon-portal-identity--free'; text = _membership.name || '普通用户'; } el.className = cls; el.textContent = text; el.style.display = 'inline-flex'; var account = document.getElementById('auth_account'); if (account) account.style.display = 'inline-flex'; } function soonLoadMembership(force) { if (_membership.loaded && !force) return Promise.resolve(_membership); if (_membership.loading && !force) return _membership.loading; if (!soonGetAccessToken()) { soonApplyMembership(null); return Promise.resolve(_membership); } 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) { if (r.status === 401) { soonApplyMembership(null); return null; } return r.json(); }) .then(function (j) { if (j && j.ok && j.data) { soonApplyMembership(j.data); } else if (j !== null) { soonApplyMembership(null); } return _membership; }) .catch(function () { soonApplyMembership(null); return _membership; }) .finally(function () { _membership.loading = null; }); return _membership.loading; } function soonIsMember() { return !!_membership.isMember; } function soonGuardPreviewDeliver(actionLabel, onAllowed) { if (typeof onAllowed !== 'function') return; if (!soonIsWebPortal()) { onAllowed(); return; } if (!soonGetAccessToken()) { if (typeof window.soonShowLoginGate === 'function') { window.soonShowLoginGate({ reason: actionLabel || '导出或打印', onSuccess: function () { soonGuardPreviewDeliver(actionLabel, onAllowed); }, }); } else { soonRequireLogin(actionLabel); } return; } 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; } allowOrActivate(); } function soonGuardCloudSave() { return true; } function soonSoonTypeFromJson(j) { return j && j.soonType ? j.soonType : (j && j.backBlackPic ? 2 : 1); } function soonPutSoonSession(j, fileName) { if (!j) return ''; var displayName = soonEnsureSoonExt(fileName || 'design.soon'); var key = soonMakeSessionKey(displayName); if (typeof window.soonLocalCacheAndThumb === 'function') { window.soonLocalCacheAndThumb(key, j, { source: 'session', name: displayName }); try { sessionStorage.setItem(key, 'idb'); } catch (e) { /* ignore */ } return key; } try { sessionStorage.setItem(key, JSON.stringify(j)); return key; } catch (e) { return ''; } } function soonOpenSoonJsonLocally(j, fileName) { var key = soonPutSoonSession(j, fileName); if (!key) { soonToast('无法打开文件(存储空间不足)', 'error'); return ''; } if (typeof window.soonRecentUpsertFromOpen === 'function') { window.soonRecentUpsertFromOpen(key, j); } soonScheduleCloudImport(key, fileName); var type = soonSoonTypeFromJson(j); if (window.platformBridge && window.platformBridge.openDesignPage) { window.platformBridge.openDesignPage(key, type); } 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 */ } function loadJsonForImport() { if (typeof window.soonLocalGet === 'function') { return window.soonLocalGet(currentFileKey).then(function (hit) { if (hit && hit.json) return hit.json; try { var raw = sessionStorage.getItem(currentFileKey); if (raw && raw !== 'idb') return JSON.parse(raw); } catch (e) { /* ignore */ } return null; }); } try { var raw = sessionStorage.getItem(currentFileKey); if (raw && raw !== 'idb') return JSON.parse(raw); } catch (e) { /* ignore */ } return Promise.resolve(null); } var bridge = window.platformBridge; if (!bridge || typeof bridge.importSoonFile !== 'function') return; loadJsonForImport().then(function (jsonObj) { if (!jsonObj) return; var oldKey = currentFileKey; return bridge.importSoonFile(pending.name || 'design.soon', jsonObj).then(function (res) { if (res && res.fileKey && typeof window.openAs !== 'undefined' && window.openAs) { window.openAs.name = res.fileKey; } if (res && res.fileKey && typeof window.soonLocalRenameKey === 'function') { window.soonLocalRenameKey(oldKey, res.fileKey, { source: 'cloud', name: res.name || pending.name }); } try { sessionStorage.removeItem(oldKey); localStorage.removeItem(oldKey); } catch (e) { /* ignore */ } if (typeof window.soonRecentOnCloudSave === 'function') { window.soonRecentOnCloudSave(res, oldKey, soonSoonTypeFromJson(jsonObj)); } }); }).catch(function (err) { if (typeof window.soonShowApiError === 'function') { window.soonShowApiError({ status: err && err.status, message: (err && err.message) || '云端登记失败,可稍后保存重试', code: err && err.code }); } else { soonToast((err && err.message) || '云端登记失败,可稍后保存重试', 'warn'); } }); } 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 }); } function soonHideOpenFileLoading() { 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, options) { options = options || {}; if (soonGetAccessToken()) return true; var label = actionLabel || '继续'; 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; } function soonParseApiError(response, bodyText) { var msg = '操作失败,请稍后重试'; var code = ''; try { var j = bodyText ? JSON.parse(bodyText) : null; if (j && j.message) msg = j.message; if (j && j.error) code = j.error; } catch (e) { /* ignore */ } if (response && response.status === 401) { return { status: 401, message: '请先登录', code: code || 'unauthorized' }; } if (response && response.status === 409) { return { status: 409, message: '文件已被其他端修改,请刷新后重试', code: code || 'conflict' }; } if (response && response.status === 413) { if (code === 'file_limit_exceeded') { return { status: 413, message: msg || '文件数量已达上限,请清理文件', code: code }; } return { status: 413, message: msg || '存储空间不足,请清理文件', code: code || 'quota_exceeded' }; } if (response && response.status === 404) { return { status: 404, message: '文件不存在', code: code || 'not_found' }; } return { status: response ? response.status : 0, message: msg, code: code }; } function soonShowApiError(info) { if (!info) return; var kind = 'error'; if (info.status === 401) kind = 'warn'; else if (info.status === 409) kind = 'warn'; else if (info.status === 413) kind = 'warn'; soonToast(info.message, kind); if (info.status === 401 && info.requireLogin) { soonRequireLogin('操作', { redirect: true }); } } 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 resolved = soonResolveCloudFileName(pathOrKey); if (resolved) return resolved; var parsed = soonParseFileKey(pathOrKey); return parsed ? ('文件 #' + parsed.id) : pathOrKey; } if (pathOrKey.indexOf('soondesign_session:') === 0) { return soonSessionDisplayName(pathOrKey); } return String(pathOrKey).split(/[/\\]/).pop(); } function soonFetchOrderStatus(orderNo) { var url = soonApiBase() + '/pay/orders/' + encodeURIComponent(orderNo); var fetchFn = typeof window.soonAuthedFetch === 'function' ? window.soonAuthedFetch(url, { headers: { Accept: 'application/json' } }) : fetch(url, { headers: { Authorization: 'Bearer ' + soonGetAccessToken(), Accept: 'application/json' } }); return fetchFn.then(function (r) { if (!r.ok) return null; return r.json(); }).then(function (j) { return j && j.ok && j.data ? j.data : null; }).catch(function () { return null; }); } function soonPollOrderPaid(orderNo, attemptsLeft, delayMs) { return soonFetchOrderStatus(orderNo).then(function (data) { if (data && data.status === 'paid') return data; if (attemptsLeft <= 1) return data; return new Promise(function (resolve) { setTimeout(function () { resolve(soonPollOrderPaid(orderNo, attemptsLeft - 1, delayMs)); }, delayMs); }); }); } function soonHandlePayReturn() { var orderNo = null; try { orderNo = new URLSearchParams(location.search).get('paid'); } catch (e) { /* ignore */ } try { sessionStorage.removeItem('soon_pay_return'); } catch (e) { /* ignore */ } if (!orderNo) return; try { var u = new URL(location.href); u.searchParams.delete('paid'); history.replaceState(null, '', u.pathname + (u.search || '') + (u.hash || '')); } catch (e) { /* ignore */ } if (!soonGetAccessToken()) return; soonPollOrderPaid(orderNo, 10, 3000).then(function (data) { if (data && data.status === 'paid') { return soonLoadMembership(true).then(function () { soonRefreshPortalIdentity(); soonToast('支付成功,会员已激活', 'success'); }); } if (data && data.status === 'cancelled') { soonToast('订单已取消', 'warn'); return; } soonToast('支付尚未完成,如已付款请稍后在会员中心查看', 'warn'); }); } window.soonIsWebPortal = soonIsWebPortal; window.soonParseFileKey = soonParseFileKey; window.soonMakeFileKey = soonMakeFileKey; window.soonNormalizeSoonName = soonNormalizeSoonName; window.soonResolveCloudFileName = soonResolveCloudFileName; 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.soonShowOpenFileLoading = soonShowOpenFileLoading; window.soonHideOpenFileLoading = soonHideOpenFileLoading; window.soonParseTemplateKey = soonParseTemplateKey; window.soonMakeTemplateKey = soonMakeTemplateKey; window.soonSoonTypeFromJson = soonSoonTypeFromJson; window.soonLoadMembership = soonLoadMembership; window.soonApplyMembership = soonApplyMembership; window.soonRefreshPortalIdentity = soonRefreshPortalIdentity; window.soonIsMember = soonIsMember; window.soonRequireLogin = soonRequireLogin; window.soonParseApiError = soonParseApiError; window.soonShowApiError = soonShowApiError; window.soonDisplayFileName = soonDisplayFileName; window.soonIsTemplateKey = soonIsTemplateKey; window.soonNeedsSaveDialog = soonNeedsSaveDialog; window.soonDefaultNewSoonName = soonDefaultNewSoonName; window.soonEnsureSoonExt = soonEnsureSoonExt; window.soonSessionSlug = soonSessionSlug; window.soonMakeSessionKey = soonMakeSessionKey; window.soonSessionDisplayName = soonSessionDisplayName; window.soonBuildSavePreviewPic = soonBuildSavePreviewPic; window.soonApplySavePreview = soonApplySavePreview; window.soonSaveDialogDefaultPath = soonSaveDialogDefaultPath; window.soonEnsureSaveFileName = soonEnsureSaveFileName; window.soonReportSaveError = soonReportSaveError; window.soonWriteSoonContentWeb = soonWriteSoonContentWeb; window.soonDownloadBlob = soonDownloadBlob; window.soonDownloadRecentItem = soonDownloadRecentItem; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', soonHandlePayReturn); } else { soonHandlePayReturn(); } })();