2e6578247e
- 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>
303 lines
12 KiB
JavaScript
303 lines
12 KiB
JavaScript
// 使用平台桥(桌面端由 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, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
||
}
|
||
|
||
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); });
|
||
}
|
||
}); |