前端配置迁至 config/local.js,完善支付、模板库与部署脚本

- 页面直接引用 local.js 设置 SOON_DEPLOY_CONFIG,移除 deploy-config
- Docker sync-config 生成 local.js;更新 README 与 agent-core 说明
- 模板库自动扫描 .soon;新增后端部署/种子/排查脚本
- 完善支付配置、订阅弹窗与后台支付管理页

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
24kycj
2026-06-08 20:48:51 +08:00
parent 88c6ce8ccc
commit 152228d41f
47 changed files with 1448 additions and 486 deletions
+85 -13
View File
@@ -425,24 +425,92 @@ layui.use(['layer', 'form', 'jquery'], function () {
}
function templateCardHtml(m, i) {
var defaultThumb = soonAsset('bg_1.png');
var thumbSrc = typeof soonSafeImageUrl === 'function'
? soonSafeImageUrl(m.thumbnail_url, defaultThumb)
: (m.thumbnail_url || defaultThumb);
if (!thumbSrc) thumbSrc = defaultThumb;
function templateFallbackThumb(type) {
var t = Number(type) || 1;
return soonAsset(t === 2 ? 'bg_2.png' : 'bg_1.png');
}
async function resolveTemplateItem(m) {
var type = Number(m.type) || 1;
var fallbackThumb = templateFallbackThumb(type);
var fileUrl = m.file_url || '';
var out = {
name: m.name || m.title || '模板',
type: type,
file_url: fileUrl,
thumbSrc: fallbackThumb,
_soonData: null
};
if (!fileUrl) return out;
try {
var r = await fetch(fileUrl);
if (!r.ok) throw new Error('fetch');
var soonData = await r.json();
if (!soonData) return out;
out._soonData = soonData;
type = soonData.soonType ? soonData.soonType : (soonData.backBlackPic ? 2 : 1);
out.type = type;
fallbackThumb = templateFallbackThumb(type);
var src = typeof soonSafeImageUrl === 'function'
? soonSafeImageUrl(soonData.frontDisplayPic, fallbackThumb)
: (soonData.frontDisplayPic || fallbackThumb);
out.thumbSrc = src || fallbackThumb;
} catch (e) { /* 与最近文件一致:失败时用默认图 */ }
return out;
}
function openTemplateItem(m) {
var type = Number(m.type) || 1;
function openWithJson(j) {
if (!j) {
openDesign(type, '');
return;
}
var key = 'soondesign_session:tpl-' + Date.now();
try {
sessionStorage.setItem(key, JSON.stringify(j));
openDesign(type, key);
} catch (e) {
openDesign(type, '');
}
}
if (m._soonData) {
openWithJson(m._soonData);
return;
}
var fileUrl = m.file_url || '';
if (!fileUrl) {
openDesign(type, '');
return;
}
fetch(fileUrl).then(function (r) {
if (!r.ok) throw new Error('fetch');
return r.json();
}).then(openWithJson).catch(function () {
openDesign(type, '');
});
}
function templateCardHtml(m, itemIndex) {
var type = Number(m.type) || 1;
var thumbSrc = m.thumbSrc || templateFallbackThumb(type);
var esc = typeof soonEscapeHtml === 'function' ? soonEscapeHtml : escapeAttr;
var name = esc(m.name || m.title || '模板');
return '<div class="soon-template-card" style="animation-delay:' + (i * 0.05) + 's" data-type="' + (m.type || 1) + '">' +
var rectClass = 'rect' + (type == 2 ? ' rect1' : '');
return '<div class="card" data-type="' + type + '" data-index="' + itemIndex + '" title="' + name + '">' +
'<div class="' + rectClass + '">' +
'<img src="' + esc(thumbSrc) + '" alt="">' +
'<span>' + name + '</span></div>';
'<div class="tip">' + name + '</div>' +
'</div></div>';
}
function bindTemplateCards(grid) {
if (!grid) return;
grid.querySelectorAll('.soon-template-card').forEach(function (card) {
grid.querySelectorAll('.card[data-index]').forEach(function (card) {
card.onclick = function () {
openDesign(Number(card.dataset.type) || 1, '');
var idx = Number(card.dataset.index);
var m = templateListState.items[idx];
if (m) openTemplateItem(m);
};
});
}
@@ -482,7 +550,7 @@ layui.use(['layer', 'form', 'jquery'], function () {
var start = (templateListState.page - 1) * templateListState.size;
var slice = items.slice(start, start + templateListState.size);
grid.innerHTML = slice.map(function (m, i) { return templateCardHtml(m, i); }).join('');
grid.innerHTML = slice.map(function (m, i) { return templateCardHtml(m, start + i); }).join('');
bindTemplateCards(grid);
renderTemplatePager();
}
@@ -524,8 +592,12 @@ layui.use(['layer', 'form', 'jquery'], function () {
}
var items = (j.data && j.data.items) ? j.data.items : [];
templateListState.items = items;
templateListState.total = items.length;
var resolved = [];
for (var ti = 0; ti < items.length; ti++) {
resolved.push(await resolveTemplateItem(items[ti]));
}
templateListState.items = resolved;
templateListState.total = resolved.length;
templateListState.page = 1;
renderTemplatesPage();