Files
SoonDesign/lib/index.js
T
24kycj 2e6578247e 网页端:平台桥与部署修复(宝塔/Nginx)
- lib/platform:网页 Electron 统一 bridge/web/electron,子目录 API 基路径、返回首页跳站点根、路径末尾斜杠兼容
- index/design*.web.html:网页入口,web.js 加缓存参数避免旧脚本缓存
- api:PHP 读写 soon;文档说明目录权限与 Nginx
- lib/design*、lib/index:与 platformBridge 对接及网页侧逻辑
- 公共资源 JsBarcode/jr-qrcode;文档与 package/README/.gitignore 等同步更新

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 18:57:53 +08:00

303 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 使用平台桥(桌面端由 lib/platform/electron.js 注入 window.ipcRenderer / window.dialog / window.sysAPI
var ipcRenderer = typeof window !== 'undefined' ? window.ipcRenderer : null;
var dialog = typeof window !== 'undefined' ? window.dialog : null;
// 辅助函数:获取文件名 (保留扩展名)
function get_filename(filePath) {
if (!filePath) return "";
return filePath.split(/[/\\]/).pop();
}
// 辅助函数:HTML 属性转义,避免 path 中的 "&<> 破坏属性导致点击传参错误
function escapeAttr(s) {
if (s == null) return "";
return String(s).replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
let s_lan = "zh";
function language_str(str) {
let t = {
"noFile": { zh: "当前文件不存在!", ozh: "This file does not exist!", en: "File not found!" },
"saveTime": { zh: "保存时间:", ozh: "保存時間:", en: "Saved on:" },
"selectFile": { zh: "请选择文件", ozh: "請選擇文件", en: "Please select a file" },
"comfirm": { zh: "确认", ozh: "確認", en: "Confirm" },
"cancel": { zh: "取消", ozh: "取消", en: "Cancel" },
"SDFile": { zh: "SoonDesign模板文件", ozh: "SoonDesign模闆文件", en: "SoonDesign Template File" },
"vers": { zh: "版本:", ozh: "版本:", en: "Version:" },
"copyright": { zh: "版权所有 © 2023", ozh: "版權所有 © 2023", en: "Copyright © 2023" },
"about": { zh: "关于 SoonDesign", ozh: "關於 SoonDesign", en: "About SoonDesign" },
"lost": { zh: "(文件已丢失)", ozh: "(文件已丟失)", en: "(File Lost)" },
"clickToDelete": { zh: "文件已丢失,点击删除此记录", ozh: "文件已丟失,點擊刪除此記錄", en: "File lost, click to remove" },
"deleted": { zh: "已删除", ozh: "已刪除", en: "Deleted" },
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Save current file?" }, // 补全可能用到的翻译
"delTitle": { zh: "警告", ozh: "警告", en: "Warning" },
"delContent": { zh: "文件已丢失,确认是否删除?", ozh: "文件已丟失,確認是否刪除?", en: "File lost, confirm delete?" }
}
return t[str][s_lan] || t[str]['zh'];
}
layui.use(['layer', 'form', 'jquery'], function () {
var $ = layui.$;
var layer = layui.layer
, form = layui.form;
if (window.sysAPI && window.sysAPI.getAppVersion) {
window.sysAPI.getAppVersion().then(ver => {
$("#app-version").text("v" + ver);
}).catch(e => console.log(e));
}
if (ipcRenderer) {
ipcRenderer.send('get-sys-language');
ipcRenderer.on('close', (event, message) => {
ipcRenderer.send('run-close');
});
}
function langua_ge(lan = 'zh') {
$("[language='m']").each(function (i) {
$(this).html($(this).attr(lan));
})
$("[language='t']").each(function (i) {
$(this).attr("title", $(this).attr(lan));
})
}
$('#language_select').on('change', function () {
langua_ge($(this).find('option:selected').val());
s_lan = $(this).find('option:selected').val();
localStorage.setItem("lang", s_lan);
loadHistory();
});
if (ipcRenderer && ipcRenderer.on) {
ipcRenderer.on('sys-lan', (event, data) => {
let lang = localStorage.getItem("lang");
if (lang) {
s_lan = lang;
} else {
if (data && data.startsWith('zh')) {
s_lan = data === 'zh-TW' ? 'ozh' : 'zh';
} else {
s_lan = 'en';
}
}
langua_ge(s_lan);
$("#language_select").val(s_lan);
localStorage.setItem("lang", s_lan);
loadHistory();
});
}
// ==========================================
// 加载列表
// ==========================================
async function loadHistory() {
try {
if (!window.sysAPI || typeof window.sysAPI.readHistory !== 'function') {
$(".card-list").html("");
return;
}
const j = await window.sysAPI.readHistory();
if (!j || !Array.isArray(j.history)) {
$(".card-list").html("");
return;
}
let h = "";
let needUpdate = false;
for (let item of j.history) {
let src = "";
let fileExists = true;
let imgStyle = "";
let realType = item.type;
const soonData = await window.sysAPI.readJsonFile(item.path);
if (soonData) {
src = soonData.frontDisplayPic;
let fileType = soonData.soonType ? soonData.soonType : (soonData.backBlackPic ? 2 : 1);
if (item.type != fileType) {
item.type = fileType;
realType = fileType;
needUpdate = true;
}
} else {
fileExists = false;
if (realType && (realType == 2 || realType == "2")) {
src = "./public/images/bg_2.png";
} else {
src = "./public/images/bg_1.png";
}
imgStyle = "opacity: 0.6; filter: grayscale(100%);";
}
// 网页端历史 path 为 soondesign_session:文件名.soon,展示时去掉前缀
const sessionPrefix = 'soondesign_session:';
let displayName = (item.path && item.path.indexOf(sessionPrefix) === 0)
? item.path.substring(sessionPrefix.length)
: get_filename(item.path);
let cardTitle = (item.path && item.path.indexOf(sessionPrefix) === 0)
? displayName
: item.path;
let cardStyle = "";
if (!fileExists) {
displayName += ` <span style='color:#ff5722;font-size:12px;'>${language_str("lost")}</span>`;
cardTitle = language_str("clickToDelete");
cardStyle = "border: 1px dashed #ff5722;";
}
h += `<div class="card" data-file="${escapeAttr(item.path)}" title="${escapeAttr(cardTitle)}" style="${cardStyle}">
<div class="rect ${realType == 2 ? 'rect1' : ''}">
<img src="${src}" style="width:190px; ${imgStyle}">
<div class="tip">${displayName}</div>
</div>
</div>`
}
$(".card-list").html(h);
if (needUpdate) {
await window.sysAPI.writeHistory({ history: j.history });
}
} catch (e) {
console.error("加载历史记录出错", e);
}
}
loadHistory();
// 按钮事件
$("#openfile").click(function () { OpenDialog(); });
$("#new1").click(function () {
if (window.platformBridge && window.platformBridge.openDesignPage) window.platformBridge.openDesignPage("", 1);
else if (ipcRenderer && ipcRenderer.send) ipcRenderer.send('open-design-page', "", 1);
});
$("#new2").click(function () {
if (window.platformBridge && window.platformBridge.openDesignPage) window.platformBridge.openDesignPage("", 2);
else if (ipcRenderer && ipcRenderer.send) ipcRenderer.send('open-design-page', "", 2);
});
$("#about").click(async function () {
let version = "3.0.0";
try {
if (window.sysAPI && window.sysAPI.getAppVersion) {
const v = await window.sysAPI.getAppVersion();
version = "v" + v;
}
} catch (e) {}
layer.open({
type: 1
, title: language_str("about")
, area: '450px;'
, id: 'LAY_layuipro'
, moveType: 1
, content: '<div style="padding-top:20px;padding-bottom:30px;background-color: #32363A; color: #fff; font-weight: 300;text-align:center;">' +
'<div style="width: 120px;margin: 0 auto;"><img style="width: 120px;" src="./public/images/IconA.png"></div>' +
'<div style="font-size:24px;">Soon Design</div>' +
'<div style="font-size:14px;">' + language_str("vers") + ' ' + version + '</div>' +
'<div style="font-size:14px;">' + language_str("copyright") + '</div>' +
'</div>'
});
});
// ==========================================
// 点击事件 (修改后:完全匹配“保存”弹窗样式)
// ==========================================
$(".card-list").on("click", '.card', async function () {
let filePath = $(this).attr("data-file") || $(this).attr("data");
// 再次检查文件是否存在
const soonData = await window.sysAPI.readJsonFile(filePath);
if (soonData) {
// 1. 文件存在 -> 正常打开
let type = soonData.soonType ? soonData.soonType : (soonData.backBlackPic ? 2 : 1);
const currentData = await window.sysAPI.readHistory();
let newHistory = currentData.history.filter(item => item.path !== filePath);
newHistory.unshift({ path: filePath, time: Date.now(), type: type });
await window.sysAPI.writeHistory({ history: newHistory });
if (window.platformBridge && window.platformBridge.openDesignPage) window.platformBridge.openDesignPage(filePath, type);
else if (ipcRenderer && ipcRenderer.send) ipcRenderer.send('open-design-page', filePath, type);
} else {
// 2. 文件不存在 -> 警告确认
// 【关键修改】
// - 纯文字,左对齐 (text-align: left)
// - 适当的 padding
// - 去除所有图标
let contentHtml = `
<div style="padding: 20px 20px; text-align: left; color: #333; font-size: 14px;">
${language_str("delContent")}
</div>
`;
// 使用 layer.open
layer.open({
type: 1,
title: language_str("delTitle"), // 标题:警告
content: contentHtml,
btn: [language_str("comfirm"), language_str("cancel")],
btnAlign: 'r', // 【关键修改】按钮右对齐
area: ['300px', 'auto'], // 【关键修改】宽度设为 300px,标准小窗口
resize: false,
shadeClose: true,
yes: async function(index){
const currentData = await window.sysAPI.readHistory();
const newHistory = currentData.history.filter(item => item.path !== filePath);
if (newHistory.length !== currentData.history.length) {
await window.sysAPI.writeHistory({ history: newHistory });
layer.msg(language_str("deleted"), { icon: 1, time: 1000 });
loadHistory();
}
layer.close(index);
}
});
}
});
function OpenDialog() {
var dialogApi = (typeof dialog !== 'undefined' && dialog) ? dialog : (window.platformBridge && window.platformBridge.showOpenDialog ? { showOpenDialog: function(opts) { return window.platformBridge.showOpenDialog(opts); } } : null);
if (!dialogApi) return;
dialogApi.showOpenDialog({
title: language_str("selectFile"),
buttonLabel: language_str("comfirm"),
filters: [
{ name: language_str("SDFile"), extensions: ['soon'] },
]
}).then(async function(result) {
if (result.canceled) return;
var filePath = result.filePaths && result.filePaths[0];
var file = (result.files && result.files[0]) || result.file;
var soonData;
if (file && file.text) {
filePath = file.name || 'design.soon';
soonData = await window.sysAPI.readJsonFile(file);
// 网页端:将内容存到 sessionStorage,设计页通过 sessionKey 读取
if (soonData && typeof sessionStorage !== 'undefined' && window.platformBridge) {
try {
sessionStorage.setItem('soondesign_session:' + filePath, JSON.stringify(soonData));
filePath = 'soondesign_session:' + filePath;
} catch (e) {}
}
} else if (filePath) {
soonData = await window.sysAPI.readJsonFile(filePath);
}
if (!soonData) {
if (!filePath && !file) return;
layer.msg(language_str("noFile"));
return;
}
var type = soonData.soonType ? soonData.soonType : (soonData.backBlackPic ? 2 : 1);
var currentData = await window.sysAPI.readHistory();
var newHistory = currentData.history.filter(function(item) { return item.path !== filePath; });
newHistory.unshift({ path: filePath, time: Date.now(), type: type });
await window.sysAPI.writeHistory({ history: newHistory });
if (window.platformBridge && window.platformBridge.openDesignPage) window.platformBridge.openDesignPage(filePath, type);
else if (ipcRenderer && ipcRenderer.send) ipcRenderer.send('open-design-page', filePath, type);
loadHistory();
}).catch(function(err) { console.log(err); });
}
});