(function () { 'use strict'; var FILE_PREFIX = 'soondesign_file:'; function soonIsWebPortal() { return typeof window !== 'undefined' && window.platformBridge && !window.fs; } 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 soonNormalizeSoonName(pathOrName) { var n = String(pathOrName || 'design.soon'); if (n.indexOf(FILE_PREFIX) === 0) { var meta = window._soonFileMeta; return (meta && meta.name) ? meta.name : 'design.soon'; } if (n.indexOf('soondesign_session:') === 0) { n = n.replace(/^soondesign_session:/, ''); } 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 soonBindFileMeta(fileKey, opts) { if (!fileKey || fileKey.indexOf(FILE_PREFIX) !== 0) return; var parsed = soonParseFileKey(fileKey); if (!parsed) return; var prev = window._soonFileMeta || {}; window._soonFileMeta = { id: parsed.id, version: parsed.version != null ? parsed.version : prev.version, name: (opts && opts.name) || (prev.id === parsed.id ? prev.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() + '/plans/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 (j) { if (j && j.ok && j.data) { soonApplyMembership(j.data.membership || j.data); } else { 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; } if (soonIsMember()) { onAllowed(); return; } if (typeof window.soonShowActivateGate === 'function') { window.soonShowActivateGate({ reason: actionLabel || '导出或打印', onSuccess: function () { onAllowed(); }, }); } else { soonToast('请先激活会员后再' + (actionLabel || '操作'), 'warn'); } } 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 hint = (fileName || 'design').replace(/\.soon$/i, ''); var key = 'soondesign_session:' + hint + '-' + Date.now(); try { sessionStorage.setItem(key, JSON.stringify(j)); try { localStorage.setItem(key, JSON.stringify(j)); } catch (e2) { /* ignore quota */ } return key; } catch (e) { return ''; } } function soonOpenSoonJsonLocally(j, fileName) { var key = soonPutSoonSession(j, fileName); if (!key) return ''; var type = soonSoonTypeFromJson(j); if (window.platformBridge && window.platformBridge.openDesignPage) { window.platformBridge.openDesignPage(key, type); } return key; } function soonToast(message, type) { if (typeof window.soonToast === 'function') window.soonToast(message, type); } function soonRequireLogin(actionLabel) { 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'; } 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) { soonRequireLogin('操作'); } } function soonDisplayFileName(pathOrKey) { if (!pathOrKey) return ''; if (pathOrKey.indexOf(FILE_PREFIX) === 0) { var meta = window._soonFileMeta; if (meta && meta.name) return meta.name; var parsed = soonParseFileKey(pathOrKey); return parsed ? ('文件 #' + parsed.id) : pathOrKey; } if (pathOrKey.indexOf('soondesign_session:') === 0) { return pathOrKey.replace(/^soondesign_session:/, ''); } return String(pathOrKey).split(/[/\\]/).pop(); } function soonHandlePayReturn() { var paid = null; var flag = false; try { paid = new URLSearchParams(location.search).get('paid'); } catch (e) { /* ignore */ } try { flag = !!sessionStorage.getItem('soon_pay_return'); } catch (e) { /* ignore */ } if (!paid && !flag) return; try { sessionStorage.removeItem('soon_pay_return'); } catch (e) { /* ignore */ } if (paid) { try { var u = new URL(location.href); u.searchParams.delete('paid'); history.replaceState(null, '', u.pathname + (u.search || '') + (u.hash || '')); } catch (e) { /* ignore */ } } soonLoadMembership(true).then(function () { soonRefreshPortalIdentity(); soonToast('支付成功,会员已激活', 'success'); }); } window.soonIsWebPortal = soonIsWebPortal; window.soonParseFileKey = soonParseFileKey; window.soonMakeFileKey = soonMakeFileKey; window.soonNormalizeSoonName = soonNormalizeSoonName; window.soonApplyCloudMeta = soonApplyCloudMeta; window.soonBindFileMeta = soonBindFileMeta; window.soonFormatOpenTitle = soonFormatOpenTitle; window.soonGuardCloudSave = soonGuardCloudSave; window.soonGuardPreviewDeliver = soonGuardPreviewDeliver; window.soonHandlePayReturn = soonHandlePayReturn; window.soonOpenSoonJsonLocally = soonOpenSoonJsonLocally; window.soonPutSoonSession = soonPutSoonSession; 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; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', soonHandlePayReturn); } else { soonHandlePayReturn(); } })();