更新优化
This commit is contained in:
@@ -7,3 +7,7 @@ npm-debug.log
|
|||||||
npm-debug.log.*
|
npm-debug.log.*
|
||||||
thumbs.db
|
thumbs.db
|
||||||
!.gitkeep
|
!.gitkeep
|
||||||
|
|
||||||
|
# 加密相关文件(不要提交到 Git)
|
||||||
|
*.jsc
|
||||||
|
.backup/
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# SoonDesign 设计工具
|
||||||
|
|
||||||
|
简单易用的桌面设计软件,支持光盘和卡片模板设计。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 第一次使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 安装依赖(只需一次)
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 2. 启动程序
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
> **前置要求**:需要安装 [Node.js](https://nodejs.org/)(推荐 16 或更高版本)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 发布流程(傻瓜式操作)
|
||||||
|
|
||||||
|
### 方式一:一键发布 ⭐ 推荐
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows 系统
|
||||||
|
npm run release:win
|
||||||
|
|
||||||
|
# Mac 系统
|
||||||
|
npm run release:mac
|
||||||
|
|
||||||
|
# Linux 系统
|
||||||
|
npm run release:linux
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **自动完成**:加密 → 测试 → 清理 → 打包
|
||||||
|
✅ **安装包位置**:`build` 文件夹
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 方式二:分步操作(手动控制)
|
||||||
|
|
||||||
|
#### 步骤 1:加密代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run encrypt:win # Windows
|
||||||
|
npm run encrypt:linux # Mac/Linux
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ 生成 `.jsc` 加密文件(自动覆盖旧文件)
|
||||||
|
|
||||||
|
#### 步骤 2:测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ 确认程序正常运行,无报错
|
||||||
|
|
||||||
|
#### 步骤 3:清理源文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run cleanup
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ 删除 `.js` 源文件,自动备份到 `.backup` 文件夹
|
||||||
|
|
||||||
|
#### 步骤 4:打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build:win # Windows
|
||||||
|
npm run build:mac # Mac
|
||||||
|
npm run build:linux # Linux
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ 生成安装包到 `build` 文件夹
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 其他常用命令
|
||||||
|
|
||||||
|
### 恢复源文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run restore
|
||||||
|
```
|
||||||
|
|
||||||
|
> 从 `.backup` 文件夹恢复所有源文件(误删除时使用)
|
||||||
|
|
||||||
|
### 清理加密文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run cleanup:jsc
|
||||||
|
```
|
||||||
|
|
||||||
|
> 删除所有 `.jsc` 文件(重新加密前使用)
|
||||||
|
|
||||||
|
### 修改文件名映射
|
||||||
|
|
||||||
|
编辑 `lib/module-map.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "core1", // 修改这里
|
||||||
|
"output": "output1",
|
||||||
|
"ui": "ui1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
然后重新运行 `npm run encrypt:win`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
|
- **开发时**:保留 `.js` 源文件,不要运行 `cleanup`
|
||||||
|
- **发布时**:必须先加密、再清理、最后打包
|
||||||
|
- **备份在**:`.backup` 文件夹(不会被打包进应用)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
lib/
|
||||||
|
├── module-map.json - 文件名映射配置
|
||||||
|
├── index.js - 首页入口
|
||||||
|
├── design1.js - 光盘模板入口
|
||||||
|
├── design2.js - 卡片模板入口
|
||||||
|
├── design1/ - 光盘模板功能模块
|
||||||
|
│ ├── core.js - 核心功能
|
||||||
|
│ ├── output.js - 导出/保存
|
||||||
|
│ └── ui.js - 界面交互
|
||||||
|
└── design2/ - 卡片模板功能模块
|
||||||
|
├── core.js
|
||||||
|
├── output.js
|
||||||
|
└── ui.js
|
||||||
|
|
||||||
|
scripts/encrypt/ - 加密脚本(不会被打包)
|
||||||
|
.backup/ - 源文件备份(不会被打包)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 调试模式
|
||||||
|
|
||||||
|
按 `F12` 或 `Ctrl+Shift+I` 打开开发者工具查看错误信息。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 更多文档
|
||||||
|
|
||||||
|
- [加密详细说明](scripts/encrypt/README.md)
|
||||||
|
- 当前版本:v2.3.017
|
||||||
+39
-8
File diff suppressed because one or more lines are too long
+40
-9
File diff suppressed because one or more lines are too long
+40
-7
@@ -216,13 +216,46 @@
|
|||||||
|
|
||||||
<script src="./layui/layui.js"></script>
|
<script src="./layui/layui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
require('bytenode');
|
(function() {
|
||||||
require.extensions['.dl'] = require.extensions['.jsc'];
|
const path = require('path'), fs = require('fs'), remote = require('@electron/remote');
|
||||||
try {
|
const appPath = (() => { try { return remote.app.getAppPath(); } catch(e) { return __dirname || process.cwd(); } })();
|
||||||
require('./lib/index.js');
|
|
||||||
} catch (error) {
|
// 读取模块映射配置
|
||||||
require('./lib/directx9.dl');
|
let mappedName = 'index';
|
||||||
}
|
try {
|
||||||
|
const moduleMapPath = path.join(appPath, 'lib', 'module-map.json');
|
||||||
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
const moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
mappedName = moduleMap.mappings?.main?.index || 'index';
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
const jscPath = path.join(appPath, 'lib', `${mappedName}.jsc`);
|
||||||
|
const jsPath = path.join(appPath, 'lib', 'index.js');
|
||||||
|
|
||||||
|
// 优先加载映射的 .jsc 文件
|
||||||
|
try {
|
||||||
|
require('bytenode');
|
||||||
|
require.extensions['.dl'] = require.extensions['.jsc'];
|
||||||
|
if (fs.existsSync(jscPath)) {
|
||||||
|
require(jscPath);
|
||||||
|
console.log(`[加载] ✅ index → ${mappedName}.jsc`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch(e) { console.error('[加载] .jsc 加载失败:', e.message); }
|
||||||
|
|
||||||
|
// 回退到 .js 源文件
|
||||||
|
if (fs.existsSync(jsPath)) {
|
||||||
|
try {
|
||||||
|
require(jsPath);
|
||||||
|
console.log('[加载] ✅ index → index.js');
|
||||||
|
} catch(e) {
|
||||||
|
alert('文件加载失败!\n\n错误: ' + e.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('文件不存在!\n\n请检查:\n1. ' + jscPath + '\n2. ' + jsPath);
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Binary file not shown.
+403
-167
@@ -5,7 +5,7 @@ require('./common/fabric-ext.js');
|
|||||||
// 过滤 Canvas2D willReadFrequently 警告(不影响功能,只是性能提示)
|
// 过滤 Canvas2D willReadFrequently 警告(不影响功能,只是性能提示)
|
||||||
if (typeof console !== 'undefined' && console.warn) {
|
if (typeof console !== 'undefined' && console.warn) {
|
||||||
const originalWarn = console.warn;
|
const originalWarn = console.warn;
|
||||||
console.warn = function(...args) {
|
console.warn = function (...args) {
|
||||||
const message = args.join(' ');
|
const message = args.join(' ');
|
||||||
// 过滤掉 willReadFrequently 相关的警告
|
// 过滤掉 willReadFrequently 相关的警告
|
||||||
if (message.includes('willReadFrequently') || message.includes('getImageData')) {
|
if (message.includes('willReadFrequently') || message.includes('getImageData')) {
|
||||||
@@ -17,117 +17,219 @@ if (typeof console !== 'undefined' && console.warn) {
|
|||||||
|
|
||||||
// Electron相关导入
|
// Electron相关导入
|
||||||
const remote = require('@electron/remote');
|
const remote = require('@electron/remote');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
const exePath = remote.app.getPath('userData');
|
const exePath = remote.app.getPath('userData');
|
||||||
const { ipcRenderer } = require('electron');
|
const { ipcRenderer } = require('electron');
|
||||||
const { dialog } = require('@electron/remote');
|
const { dialog } = require('@electron/remote');
|
||||||
var jrQrcode = require('jr-qrcode');
|
var jrQrcode = require('jr-qrcode');
|
||||||
var JsBarcode = require('jsbarcode');
|
var JsBarcode = require('jsbarcode');
|
||||||
const { clipboard } = require('electron');
|
const { clipboard } = require('electron');
|
||||||
const dpi = 600;
|
const dpi = 600;
|
||||||
|
|
||||||
// 发送IPC消息
|
// 发送IPC消息
|
||||||
ipcRenderer.send('get-sys-fonts');
|
ipcRenderer.send('get-sys-fonts');
|
||||||
ipcRenderer.send('get-scale-rate');
|
ipcRenderer.send('get-scale-rate');
|
||||||
|
|
||||||
// 使用layui
|
// 使用layui
|
||||||
layui.use(['layer', 'slider', 'form', 'colorpicker'], function () {
|
layui.use(['layer', 'slider', 'form', 'colorpicker'], function () {
|
||||||
let myDate = new Date();
|
let myDate = new Date();
|
||||||
let s_lan = "";
|
let s_lan = "";
|
||||||
ipcRenderer.send('get-sys-language');
|
// 确保 s_lan 在全局作用域中可用(用于 .jsc 文件加载)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.s_lan = s_lan;
|
||||||
|
}
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.s_lan = s_lan;
|
||||||
|
}
|
||||||
|
ipcRenderer.send('get-sys-language');
|
||||||
|
|
||||||
var $ = layui.$;
|
var $ = layui.$;
|
||||||
var layer = layui.layer;
|
var layer = layui.layer;
|
||||||
var slider = layui.slider;
|
var slider = layui.slider;
|
||||||
|
var form = layui.form;
|
||||||
|
var colorpicker = layui.colorpicker;
|
||||||
|
|
||||||
|
// 确保所有必要的变量在全局作用域中可用(用于 .jsc 文件加载)
|
||||||
|
// 在 Electron 的渲染进程中,需要同时设置 window 和 global
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.$ = $;
|
||||||
|
window.jQuery = $;
|
||||||
|
window.ipcRenderer = ipcRenderer;
|
||||||
|
window.layer = layer;
|
||||||
|
window.slider = slider;
|
||||||
|
window.form = form;
|
||||||
|
window.colorpicker = colorpicker;
|
||||||
|
window.dialog = dialog;
|
||||||
|
window.remote = remote;
|
||||||
|
window.path = path;
|
||||||
|
window.jrQrcode = jrQrcode;
|
||||||
|
window.JsBarcode = JsBarcode;
|
||||||
|
window.clipboard = clipboard;
|
||||||
|
window.dpi = dpi;
|
||||||
|
// language_str 会在后面定义,但先确保引用正确
|
||||||
|
}
|
||||||
|
// 在 Node.js 上下文中也设置(require 加载 .jsc 文件时使用)
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.$ = $;
|
||||||
|
global.jQuery = $;
|
||||||
|
global.ipcRenderer = ipcRenderer;
|
||||||
|
global.layer = layer;
|
||||||
|
global.slider = slider;
|
||||||
|
global.form = form;
|
||||||
|
global.colorpicker = colorpicker;
|
||||||
|
global.dialog = dialog;
|
||||||
|
global.remote = remote;
|
||||||
|
global.path = path;
|
||||||
|
global.jrQrcode = jrQrcode;
|
||||||
|
global.JsBarcode = JsBarcode;
|
||||||
|
global.clipboard = clipboard;
|
||||||
|
global.dpi = dpi;
|
||||||
|
}
|
||||||
|
var layer = layui.layer;
|
||||||
|
var slider = layui.slider;
|
||||||
var colorpicker = layui.colorpicker;
|
var colorpicker = layui.colorpicker;
|
||||||
|
|
||||||
// 历史记录文件路径(供 output.js 使用)
|
// 历史记录文件路径(供 output.js 使用)
|
||||||
var fullPath = path.join(exePath, 'data.json');
|
var fullPath = path.join(exePath, 'data.json');
|
||||||
|
// 确保 fullPath 在全局作用域中可用(用于 .jsc 文件加载)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.fullPath = fullPath;
|
||||||
|
window.exePath = exePath;
|
||||||
|
}
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.fullPath = fullPath;
|
||||||
|
global.exePath = exePath;
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 公共函数定义(需要在layui.use回调内部,因为依赖jQuery)
|
// 公共函数定义(需要在layui.use回调内部,因为依赖jQuery)
|
||||||
|
// 注意:所有函数都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|
||||||
// DES加密函数
|
// DES加密函数
|
||||||
|
window.desEncrypt = function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
||||||
|
var APIFMS;
|
||||||
|
try {
|
||||||
|
// 确保输入字符串是 UTF-8 编码
|
||||||
|
var keyHex = CryptoJS.enc.Utf8.parse(key);
|
||||||
|
var encrypted = CryptoJS.DES.encrypt(str, keyHex, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7
|
||||||
|
});
|
||||||
|
// 使用 Base64 编码确保中文字符正确输出
|
||||||
|
APIFMS = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('des 加密错误:', err);
|
||||||
|
APIFMS = '';
|
||||||
|
}
|
||||||
|
return APIFMS;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
||||||
var keyHex = CryptoJS.enc.Utf8.parse(key);
|
return window.desEncrypt(str, key);
|
||||||
var encrypted = CryptoJS.DES.encrypt(str, keyHex, {
|
|
||||||
mode: CryptoJS.mode.ECB,
|
|
||||||
padding: CryptoJS.pad.Pkcs7
|
|
||||||
});
|
|
||||||
return encrypted.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多语言切换
|
// 多语言切换
|
||||||
function langua_ge(lan = 'zh') {
|
window.langua_ge = function langua_ge(lan = 'zh') {
|
||||||
$("[language='m']").each(function (i) {
|
$("[language='m']").each(function (i) {
|
||||||
$(this).html($(this).attr(lan));
|
$(this).html($(this).attr(lan));
|
||||||
});
|
});
|
||||||
$("[language='t']").each(function (i) {
|
$("[language='t']").each(function (i) {
|
||||||
$(this).attr("title", $(this).attr(lan));
|
$(this).attr("title", $(this).attr(lan));
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function langua_ge(lan = 'zh') {
|
||||||
|
return window.langua_ge(lan);
|
||||||
|
}
|
||||||
|
|
||||||
// 多语言字符串获取
|
// 多语言字符串获取
|
||||||
function language_str(str) {
|
window.language_str = function language_str(str) {
|
||||||
let t = {
|
let t = {
|
||||||
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" },
|
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" },
|
||||||
"save": { zh: "保存", ozh: "保存", en: "Save" },
|
"save": { zh: "保存", ozh: "保存", en: "Save" },
|
||||||
"noSave": { zh: "不保存", ozh: "不保存", en: "No saving" },
|
"noSave": { zh: "不保存", ozh: "不保存", en: "No saving" },
|
||||||
"cancel": { zh: "取消", ozh: "取消", en: "Cancel" },
|
"cancel": { zh: "取消", ozh: "取消", en: "Cancel" },
|
||||||
"saveSucc": { zh: "保存成功至", ozh: "保存成功至", en: "Save successfully to" },
|
"saveSucc": { zh: "保存成功至", ozh: "保存成功至", en: "Save successfully to" },
|
||||||
"saveFile": { zh: "保存文件", ozh: "保存文件", en: "Save file" },
|
"saveFile": { zh: "保存文件", ozh: "保存文件", en: "Save file" },
|
||||||
"display": { zh: "预览", ozh: "預覽", en: "Display" },
|
"display": { zh: "预览", ozh: "預覽", en: "Display" },
|
||||||
"output": { zh: "导出", ozh: "導出", en: "Export" },
|
"output": { zh: "导出", ozh: "導出", en: "Export" },
|
||||||
"bg": { zh: "背景", ozh: "背景", en: "Background" },
|
"bg": { zh: "背景", ozh: "背景", en: "Background" },
|
||||||
"selectPic": { zh: "请选择图片", ozh: "請選擇圖片", en: "Please select a picture" },
|
"selectPic": { zh: "请选择图片", ozh: "請選擇圖片", en: "Please select a picture" },
|
||||||
"img": { zh: "圖片", ozh: "圖片", en: "Image" },
|
"img": { zh: "圖片", ozh: "圖片", en: "Image" },
|
||||||
"simg": { zh: "合成圖片", ozh: "合成圖片", en: "Synthesized Image" },
|
"simg": { zh: "合成圖片", ozh: "合成圖片", en: "Synthesized Image" },
|
||||||
"text": { zh: "文本", ozh: "文本", en: "Text" },
|
"text": { zh: "文本", ozh: "文本", en: "Text" },
|
||||||
"ctext": { zh: "圆形文本", ozh: "圆形文本", en: "Circle Text" },
|
"ctext": { zh: "圆形文本", ozh: "圆形文本", en: "Circle Text" },
|
||||||
"stext": { zh: "合成文本", ozh: "合成文本", en: "Synthesized Text" },
|
"stext": { zh: "合成文本", ozh: "合成文本", en: "Synthesized Text" },
|
||||||
"rect": { zh: "矩形", ozh: "矩形", en: "Rectangle" },
|
"rect": { zh: "矩形", ozh: "矩形", en: "Rectangle" },
|
||||||
"circ": { zh: "圓形", ozh: "圓形", en: "Circle" },
|
"circ": { zh: "圓形", ozh: "圓形", en: "Circle" },
|
||||||
"line": { zh: "直線", ozh: "直線", en: "Line" },
|
"line": { zh: "直線", ozh: "直線", en: "Line" },
|
||||||
"qrc": { zh: "二維碼", ozh: "二維碼", en: "QR code" },
|
"qrc": { zh: "二維碼", ozh: "二維碼", en: "QR code" },
|
||||||
"barc": { zh: "條形碼", ozh: "條形碼", en: "Barcode" },
|
"barc": { zh: "條形碼", ozh: "條形碼", en: "Barcode" },
|
||||||
"counter": { zh: "計數器", ozh: "计数器", en: "Counter" },
|
"counter": { zh: "計數器", ozh: "计数器", en: "Counter" },
|
||||||
"about": { zh: "关于Soon Design", ozh: "關於Soon Design", en: "About Soon Design" },
|
"about": { zh: "关于Soon Design", ozh: "關於Soon Design", en: "About Soon Design" },
|
||||||
"vers": { zh: "版本", ozh: "版本", en: "Version" },
|
"vers": { zh: "版本", ozh: "版本", en: "Version" },
|
||||||
"comf": { zh: "确认", ozh: "確認", en: "Select" },
|
"comf": { zh: "确认", ozh: "確認", en: "Select" },
|
||||||
"copyright": { zh: "© 2022 cardsoon Co., Ltd. All rights reserved.", ozh: "© 2022 cardsoon Co., Ltd. All rights reserved.", en: "© 2022 cardsoon Co., Ltd. All rights reserved." }
|
"copyright": { zh: "© 2022 cardsoon Co., Ltd. All rights reserved.", ozh: "© 2022 cardsoon Co., Ltd. All rights reserved.", en: "© 2022 cardsoon Co., Ltd. All rights reserved." }
|
||||||
};
|
};
|
||||||
return t[str] ? t[str][s_lan] : str;
|
// 从全局作用域获取 s_lan(支持 .jsc 文件加载)
|
||||||
|
const currentLang = (typeof global !== 'undefined' && global.s_lan) ? global.s_lan :
|
||||||
|
(typeof window !== 'undefined' && window.s_lan) ? window.s_lan : s_lan;
|
||||||
|
return t[str] ? (t[str][currentLang] || t[str]['zh'] || str) : str;
|
||||||
|
};
|
||||||
|
// 确保 language_str 在 global 作用域中也可用(用于 .jsc 文件加载)
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.language_str = window.language_str;
|
||||||
|
}
|
||||||
|
// 向后兼容
|
||||||
|
function language_str(str) {
|
||||||
|
return window.language_str(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取URL参数
|
// 获取URL参数
|
||||||
function GetFile() {
|
window.GetFile = function GetFile() {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
return params;
|
return params;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function GetFile() {
|
||||||
|
return window.GetFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日期格式化
|
// 日期格式化
|
||||||
function getDate() {
|
window.getDate = function getDate() {
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDate() {
|
||||||
|
return window.getDate();
|
||||||
|
}
|
||||||
|
|
||||||
// 获取对象的绝对坐标
|
// 获取对象的绝对坐标
|
||||||
function getAbsoluteXY(_obj) {
|
window.getAbsoluteXY = function getAbsoluteXY(_obj) {
|
||||||
let coord = _obj.get("lineCoords");
|
let coord = _obj.get("lineCoords");
|
||||||
return [_obj.get("left"), _obj.get("top")];
|
return [_obj.get("left"), _obj.get("top")];
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getAbsoluteXY(_obj) {
|
||||||
|
return window.getAbsoluteXY(_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算两点之间的距离
|
// 计算两点之间的距离
|
||||||
function getDisdance(x1, y1, x2, y2) {
|
window.getDisdance = function getDisdance(x1, y1, x2, y2) {
|
||||||
var dx = Math.abs(x2 - x1);
|
var dx = Math.abs(x2 - x1);
|
||||||
var dy = Math.abs(y2 - y1);
|
var dy = Math.abs(y2 - y1);
|
||||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
return distance;
|
return distance;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDisdance(x1, y1, x2, y2) {
|
||||||
|
return window.getDisdance(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算角度(相对于画布中心)
|
// 计算角度(相对于画布中心)
|
||||||
function getDeg(pointer, canvas) {
|
window.getDeg = function getDeg(pointer, canvas) {
|
||||||
var centerX = canvas.width / 2;
|
var centerX = canvas.width / 2;
|
||||||
var centerY = canvas.height / 2;
|
var centerY = canvas.height / 2;
|
||||||
var mouseX = pointer.x;
|
var mouseX = pointer.x;
|
||||||
@@ -141,130 +243,169 @@ const dpi = 600;
|
|||||||
}
|
}
|
||||||
angleDeg += 90;
|
angleDeg += 90;
|
||||||
return angleDeg;
|
return angleDeg;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDeg(pointer, canvas) {
|
||||||
|
return window.getDeg(pointer, canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查字段名是否重复
|
// 检查字段名是否重复
|
||||||
|
window.checkName = function checkName(name, objs1, objs2) {
|
||||||
|
for (let item of objs1) {
|
||||||
|
if (item.name == name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let item of objs2) {
|
||||||
|
if (item.name == name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
function checkName(name, objs1, objs2) {
|
function checkName(name, objs1, objs2) {
|
||||||
for (let item of objs1) {
|
return window.checkName(name, objs1, objs2);
|
||||||
if (item.name == name) {
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let item of objs2) {
|
|
||||||
if (item.name == name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回不重复的字段名
|
// 返回不重复的字段名
|
||||||
|
window.resName = function resName(pre_name, objs1, objs2) {
|
||||||
|
let num = (objs1.length + objs2.length) - 1;
|
||||||
|
do {
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
while (!window.checkName(pre_name + num, objs1, objs2));
|
||||||
|
return pre_name + num;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
function resName(pre_name, objs1, objs2) {
|
function resName(pre_name, objs1, objs2) {
|
||||||
let num = (objs1.length + objs2.length) - 1;
|
return window.resName(pre_name, objs1, objs2);
|
||||||
do {
|
}
|
||||||
num++;
|
|
||||||
}
|
|
||||||
while (!checkName(pre_name + num, objs1, objs2));
|
|
||||||
return pre_name + num;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取对象在画布中的索引
|
// 获取对象在画布中的索引
|
||||||
|
window.getIndex = function getIndex(target, canvas, _canvas = null) {
|
||||||
|
let temp_objs;
|
||||||
|
let useCanvas = (_canvas == null) ? canvas : _canvas;
|
||||||
|
if (_canvas == null) {
|
||||||
|
temp_objs = canvas.getObjects();
|
||||||
|
} else {
|
||||||
|
temp_objs = _canvas.getObjects();
|
||||||
|
}
|
||||||
|
let i = 0;
|
||||||
|
for (let res of temp_objs) {
|
||||||
|
if (target == res) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
function getIndex(target, canvas, _canvas = null) {
|
function getIndex(target, canvas, _canvas = null) {
|
||||||
let temp_objs;
|
return window.getIndex(target, canvas, _canvas);
|
||||||
let useCanvas = (_canvas == null) ? canvas : _canvas;
|
}
|
||||||
if (_canvas == null) {
|
|
||||||
temp_objs = canvas.getObjects();
|
|
||||||
} else {
|
|
||||||
temp_objs = _canvas.getObjects();
|
|
||||||
}
|
|
||||||
let i = 0;
|
|
||||||
for (let res of temp_objs) {
|
|
||||||
if (target == res) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取对象类型
|
// 获取对象类型
|
||||||
|
window.getType = function getType(target, canvas, objs) {
|
||||||
|
let temp_objs = canvas.getObjects();
|
||||||
|
let i = 0;
|
||||||
|
for (let res of temp_objs) {
|
||||||
|
if (target == res) {
|
||||||
|
return objs[i].type;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
function getType(target, canvas, objs) {
|
function getType(target, canvas, objs) {
|
||||||
let temp_objs = canvas.getObjects();
|
return window.getType(target, canvas, objs);
|
||||||
let i = 0;
|
}
|
||||||
for (let res of temp_objs) {
|
|
||||||
if (target == res) {
|
|
||||||
return objs[i].type;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取坐标的最小X值
|
// 获取坐标的最小X值
|
||||||
function getCoordsMinX(acoords) {
|
window.getCoordsMinX = function getCoordsMinX(acoords) {
|
||||||
let x = acoords[0].x;
|
let x = acoords[0].x;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.x < x) {
|
if (item.x < x) {
|
||||||
x = item.x;
|
x = item.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMinX(acoords) {
|
||||||
|
return window.getCoordsMinX(acoords);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取坐标的最大X值
|
// 获取坐标的最大X值
|
||||||
function getCoordsMaxX(acoords) {
|
window.getCoordsMaxX = function getCoordsMaxX(acoords) {
|
||||||
let x = acoords[0].x;
|
let x = acoords[0].x;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.x > x) {
|
if (item.x > x) {
|
||||||
x = item.x;
|
x = item.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMaxX(acoords) {
|
||||||
|
return window.getCoordsMaxX(acoords);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取坐标的最小Y值
|
// 获取坐标的最小Y值
|
||||||
function getCoordsMinY(acoords) {
|
window.getCoordsMinY = function getCoordsMinY(acoords) {
|
||||||
let y = acoords[0].y;
|
let y = acoords[0].y;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.y < y) {
|
if (item.y < y) {
|
||||||
y = item.y;
|
y = item.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMinY(acoords) {
|
||||||
|
return window.getCoordsMinY(acoords);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取坐标的最大Y值
|
// 获取坐标的最大Y值
|
||||||
function getCoordsMaxY(acoords) {
|
window.getCoordsMaxY = function getCoordsMaxY(acoords) {
|
||||||
let y = acoords[0].y;
|
let y = acoords[0].y;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.y > y) {
|
if (item.y > y) {
|
||||||
y = item.y;
|
y = item.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMaxY(acoords) {
|
||||||
|
return window.getCoordsMaxY(acoords);
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 全局变量定义(所有模块共享)
|
// 全局变量定义(所有模块共享)
|
||||||
|
// 注意:所有变量都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问
|
||||||
// ==========================================
|
// ==========================================
|
||||||
let addState = 0; // 0是不添加
|
window.addState = 0; // 0是不添加
|
||||||
let background_image, background_image1, background_image2;
|
window.background_image = undefined;
|
||||||
let bg_version = 1; // front_bg1.png front_bg2.png
|
window.background_image1 = undefined;
|
||||||
var zoom = 1;
|
window.background_image2 = undefined;
|
||||||
let pre_add_image; // 预添加的图片对象(用于addPic)
|
window.bg_version = 1; // front_bg1.png front_bg2.png
|
||||||
|
window.zoom = 1;
|
||||||
|
window.pre_add_image = undefined; // 预添加的图片对象(用于addPic)
|
||||||
|
|
||||||
// 内部剪贴板
|
// 内部剪贴板
|
||||||
let clipboardData = {
|
window.clipboardData = {
|
||||||
data: null,
|
data: null,
|
||||||
offset: 10 // 粘贴位置偏移量
|
offset: 10 // 粘贴位置偏移量
|
||||||
};
|
};
|
||||||
|
|
||||||
// 文件管理
|
// 文件管理
|
||||||
var openAs = {
|
window.openAs = {
|
||||||
_name: "",
|
_name: "",
|
||||||
set name(val) {
|
set name(val) {
|
||||||
if (val == "") {
|
if (val == "") {
|
||||||
$("title").html('Soon Design');
|
$("title").html('Soon Design');
|
||||||
} else {
|
} else {
|
||||||
$("title").html('Soon Design - ' + val);
|
$("title").html('Soon Design - ' + val);
|
||||||
}
|
}
|
||||||
this._name = val;
|
this._name = val;
|
||||||
@@ -275,46 +416,141 @@ const dpi = 600;
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 对象数组和历史记录
|
// 对象数组和历史记录
|
||||||
let objs1 = [];
|
window.objs1 = [];
|
||||||
let objs2 = [];
|
window.objs2 = [];
|
||||||
let step1 = { val: 0 }, step2 = { val: 0 };
|
window.step1 = { val: 0 };
|
||||||
let step = step1;
|
window.step2 = { val: 0 };
|
||||||
let objs = objs1;
|
window.step = window.step1;
|
||||||
let recordJson1 = [], recordJson2 = [], recordJson = recordJson1, recordObjs1 = [], recordObjs2 = [], recordObjs = recordObjs1;
|
window.objs = window.objs1;
|
||||||
let pre_objs1 = [], pre_objs2 = [], next_objs1 = [], next_objs2 = [], pre_objs = pre_objs1, next_objs = next_objs1;
|
window.recordJson1 = [];
|
||||||
let pre_json1 = [], pre_json2 = [], next_json1 = [], next_json2 = [], pre_json = pre_json1, next_json = next_json1;
|
window.recordJson2 = [];
|
||||||
|
window.recordJson = window.recordJson1;
|
||||||
|
window.recordObjs1 = [];
|
||||||
|
window.recordObjs2 = [];
|
||||||
|
window.recordObjs = window.recordObjs1;
|
||||||
|
window.pre_objs1 = [];
|
||||||
|
window.pre_objs2 = [];
|
||||||
|
window.next_objs1 = [];
|
||||||
|
window.next_objs2 = [];
|
||||||
|
window.pre_objs = window.pre_objs1;
|
||||||
|
window.next_objs = window.next_objs1;
|
||||||
|
window.pre_json1 = [];
|
||||||
|
window.pre_json2 = [];
|
||||||
|
window.next_json1 = [];
|
||||||
|
window.next_json2 = [];
|
||||||
|
window.pre_json = window.pre_json1;
|
||||||
|
window.next_json = window.next_json1;
|
||||||
|
|
||||||
// Canvas对象(将在core.js中初始化)
|
// Canvas对象(将在core.js中初始化)
|
||||||
var canvas1, canvas2;
|
window.canvas1 = undefined;
|
||||||
var canvas; // 当前活动的画布(canvas1 或 canvas2)
|
window.canvas2 = undefined;
|
||||||
var ctx1, ctx2;
|
window.canvas = undefined; // 当前活动的画布(canvas1 或 canvas2)
|
||||||
let is_bgi_add = false;
|
window.ctx1 = undefined;
|
||||||
|
window.ctx2 = undefined;
|
||||||
|
window.is_bgi_add = false;
|
||||||
|
|
||||||
|
// 为了兼容性,同时创建局部变量引用(向后兼容)
|
||||||
|
let addState = window.addState;
|
||||||
|
let background_image = window.background_image;
|
||||||
|
let background_image1 = window.background_image1;
|
||||||
|
let background_image2 = window.background_image2;
|
||||||
|
let bg_version = window.bg_version;
|
||||||
|
var zoom = window.zoom;
|
||||||
|
let pre_add_image = window.pre_add_image;
|
||||||
|
let clipboardData = window.clipboardData;
|
||||||
|
var openAs = window.openAs;
|
||||||
|
let objs1 = window.objs1;
|
||||||
|
let objs2 = window.objs2;
|
||||||
|
let step1 = window.step1;
|
||||||
|
let step2 = window.step2;
|
||||||
|
let step = window.step;
|
||||||
|
let objs = window.objs;
|
||||||
|
let recordJson1 = window.recordJson1;
|
||||||
|
let recordJson2 = window.recordJson2;
|
||||||
|
let recordJson = window.recordJson;
|
||||||
|
let recordObjs1 = window.recordObjs1;
|
||||||
|
let recordObjs2 = window.recordObjs2;
|
||||||
|
let recordObjs = window.recordObjs;
|
||||||
|
let pre_objs1 = window.pre_objs1;
|
||||||
|
let pre_objs2 = window.pre_objs2;
|
||||||
|
let next_objs1 = window.next_objs1;
|
||||||
|
let next_objs2 = window.next_objs2;
|
||||||
|
let pre_objs = window.pre_objs;
|
||||||
|
let next_objs = window.next_objs;
|
||||||
|
let pre_json1 = window.pre_json1;
|
||||||
|
let pre_json2 = window.pre_json2;
|
||||||
|
let next_json1 = window.next_json1;
|
||||||
|
let next_json2 = window.next_json2;
|
||||||
|
let pre_json = window.pre_json;
|
||||||
|
let next_json = window.next_json;
|
||||||
|
var canvas1 = window.canvas1;
|
||||||
|
var canvas2 = window.canvas2;
|
||||||
|
var canvas = window.canvas;
|
||||||
|
var ctx1 = window.ctx1;
|
||||||
|
var ctx2 = window.ctx2;
|
||||||
|
let is_bgi_add = window.is_bgi_add;
|
||||||
|
|
||||||
// 加载design1模块
|
// 加载design1模块
|
||||||
// 由于模块代码需要在layui.use内部执行,我们通过动态加载的方式
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
let bytenode;
|
||||||
// 加载core.js(核心功能)
|
|
||||||
try {
|
try {
|
||||||
const coreCode = fs.readFileSync(__dirname + '/design1/core.js', 'utf8');
|
bytenode = require('bytenode');
|
||||||
eval(coreCode);
|
require.extensions['.dl'] = require.extensions['.jsc'];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载core.js失败:', e);
|
console.warn('[加载模块] bytenode 未安装,无法加载 .jsc 文件');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载output.js(输出功能,需要在ui.js之前加载,因为ui.js中的saveAs会调用output.js中的函数)
|
const appPath = (() => { try { return remote.app.getAppPath(); } catch (e) { return __dirname || process.cwd(); } })();
|
||||||
|
|
||||||
|
// 读取模块映射配置(从 lib 目录读取,跨平台兼容)
|
||||||
|
let moduleMap = {};
|
||||||
try {
|
try {
|
||||||
const outputCode = fs.readFileSync(__dirname + '/design1/output.js', 'utf8');
|
const moduleMapPath = path.join(appPath, 'lib', 'module-map.json');
|
||||||
eval(outputCode);
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载output.js失败:', e);
|
console.warn('[加载模块] 无法读取模块映射配置,使用默认文件名');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载ui.js(UI控制)
|
// 获取映射后的文件名(跨平台兼容)
|
||||||
try {
|
function getMappedFileName(moduleName) {
|
||||||
const uiCode = fs.readFileSync(__dirname + '/design1/ui.js', 'utf8');
|
if (moduleMap.mappings && moduleMap.mappings.design1 && moduleMap.mappings.design1[moduleName]) {
|
||||||
eval(uiCode);
|
return moduleMap.mappings.design1[moduleName];
|
||||||
} catch (e) {
|
}
|
||||||
console.error('加载ui.js失败:', e);
|
return moduleName; // 默认使用原文件名
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadModule = (moduleName) => {
|
||||||
|
const mappedName = getMappedFileName(moduleName);
|
||||||
|
const jscPath = path.join(appPath, 'lib', 'design1', `${mappedName}.jsc`);
|
||||||
|
const jsPath = path.join(appPath, 'lib', 'design1', `${moduleName}.js`);
|
||||||
|
|
||||||
|
// 优先加载映射的 .jsc 文件
|
||||||
|
if (fs.existsSync(jscPath) && bytenode) {
|
||||||
|
try {
|
||||||
|
require(jscPath);
|
||||||
|
console.log(`[加载模块] ✅ ${moduleName} → ${mappedName}.jsc`);
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[加载模块] ❌ ${moduleName}.jsc 加载失败:`, e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回退到 .js 源文件
|
||||||
|
if (fs.existsSync(jsPath)) {
|
||||||
|
try {
|
||||||
|
eval(fs.readFileSync(jsPath, 'utf8'));
|
||||||
|
console.log(`[加载模块] ✅ ${moduleName} → ${moduleName}.js`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[加载模块] ❌ ${moduleName}.js 加载失败:`, e.message);
|
||||||
|
alert(`加载 ${moduleName} 失败!\n\n错误: ${e.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(`文件不存在!\n\n请检查:\n1. ${jscPath}\n2. ${jsPath}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadModule('output'); // 先加载 output,因为 core 中的 addBackground() 需要调用 output 中的 open()
|
||||||
|
loadModule('core');
|
||||||
|
loadModule('ui');
|
||||||
});
|
});
|
||||||
|
|||||||
+236
-951
File diff suppressed because it is too large
Load Diff
+288
-169
File diff suppressed because one or more lines are too long
+530
-284
File diff suppressed because one or more lines are too long
+278
-54
@@ -38,17 +38,67 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
var $ = layui.$;
|
var $ = layui.$;
|
||||||
var layer = layui.layer;
|
var layer = layui.layer;
|
||||||
var slider = layui.slider;
|
var slider = layui.slider;
|
||||||
|
var form = layui.form;
|
||||||
|
var colorpicker = layui.colorpicker;
|
||||||
|
|
||||||
|
// 确保所有必要的变量在全局作用域中可用(用于 .jsc 文件加载)
|
||||||
|
// 在 Electron 的渲染进程中,需要同时设置 window 和 global
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.$ = $;
|
||||||
|
window.jQuery = $;
|
||||||
|
window.ipcRenderer = ipcRenderer;
|
||||||
|
window.layer = layer;
|
||||||
|
window.slider = slider;
|
||||||
|
window.form = form;
|
||||||
|
window.colorpicker = colorpicker;
|
||||||
|
window.dialog = dialog;
|
||||||
|
window.remote = remote;
|
||||||
|
window.path = path;
|
||||||
|
window.jrQrcode = jrQrcode;
|
||||||
|
window.JsBarcode = JsBarcode;
|
||||||
|
window.clipboard = clipboard;
|
||||||
|
// design2 中没有定义 dpi,从 window.dpi 读取(在 design2.js 后面会设置)
|
||||||
|
}
|
||||||
|
// 在 Node.js 上下文中也设置(require 加载 .jsc 文件时使用)
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.$ = $;
|
||||||
|
global.jQuery = $;
|
||||||
|
global.ipcRenderer = ipcRenderer;
|
||||||
|
global.layer = layer;
|
||||||
|
global.slider = slider;
|
||||||
|
global.form = form;
|
||||||
|
global.colorpicker = colorpicker;
|
||||||
|
global.dialog = dialog;
|
||||||
|
global.remote = remote;
|
||||||
|
global.path = path;
|
||||||
|
global.jrQrcode = jrQrcode;
|
||||||
|
global.JsBarcode = JsBarcode;
|
||||||
|
global.clipboard = clipboard;
|
||||||
|
// design2 中没有定义 dpi,从 global.dpi 读取(在 design2.js 后面会设置)
|
||||||
|
}
|
||||||
|
var layer = layui.layer;
|
||||||
|
var slider = layui.slider;
|
||||||
var colorpicker = layui.colorpicker;
|
var colorpicker = layui.colorpicker;
|
||||||
|
|
||||||
// 历史记录文件路径(供 output.js 使用)
|
// 历史记录文件路径(供 output.js 使用)
|
||||||
var fullPath = path.join(exePath, 'data.json');
|
var fullPath = path.join(exePath, 'data.json');
|
||||||
|
// 确保 fullPath 在全局作用域中可用(用于 .jsc 文件加载)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.fullPath = fullPath;
|
||||||
|
window.exePath = exePath;
|
||||||
|
}
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.fullPath = fullPath;
|
||||||
|
global.exePath = exePath;
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 公共函数定义(需要在layui.use回调内部,因为依赖jQuery)
|
// 公共函数定义(需要在layui.use回调内部,因为依赖jQuery)
|
||||||
|
// 注意:所有函数都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|
||||||
// DES加密函数
|
// DES加密函数
|
||||||
function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
window.desEncrypt = function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
||||||
var APIFMS;
|
var APIFMS;
|
||||||
try {
|
try {
|
||||||
var keyHex_encrypt = CryptoJS.enc.Utf8.parse(key);
|
var keyHex_encrypt = CryptoJS.enc.Utf8.parse(key);
|
||||||
@@ -62,20 +112,28 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
return APIFMS;
|
return APIFMS;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
||||||
|
return window.desEncrypt(str, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多语言切换
|
// 多语言切换
|
||||||
function langua_ge(lan = 'zh') {
|
window.langua_ge = function langua_ge(lan = 'zh') {
|
||||||
$("[language='m']").each(function (i) {
|
$("[language='m']").each(function (i) {
|
||||||
$(this).html($(this).attr(lan));
|
$(this).html($(this).attr(lan));
|
||||||
});
|
});
|
||||||
$("[language='t']").each(function (i) {
|
$("[language='t']").each(function (i) {
|
||||||
$(this).attr("title", $(this).attr(lan));
|
$(this).attr("title", $(this).attr(lan));
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function langua_ge(lan = 'zh') {
|
||||||
|
return window.langua_ge(lan);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多语言字符串获取
|
// 多语言字符串获取
|
||||||
function language_str(str) {
|
window.language_str = function language_str(str) {
|
||||||
let t = {
|
let t = {
|
||||||
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" },
|
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" },
|
||||||
"save": { zh: "保存", ozh: "保存", en: "Save" },
|
"save": { zh: "保存", ozh: "保存", en: "Save" },
|
||||||
@@ -103,37 +161,64 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
"comf": { zh: "确认", ozh: "確認", en: "Select" },
|
"comf": { zh: "确认", ozh: "確認", en: "Select" },
|
||||||
"copyright": { zh: "© 2022 cardsoon Co., Ltd. All rights reserved.", ozh: "© 2022 cardsoon Co., Ltd. All rights reserved.", en: "© 2022 cardsoon Co., Ltd. All rights reserved." }
|
"copyright": { zh: "© 2022 cardsoon Co., Ltd. All rights reserved.", ozh: "© 2022 cardsoon Co., Ltd. All rights reserved.", en: "© 2022 cardsoon Co., Ltd. All rights reserved." }
|
||||||
};
|
};
|
||||||
return t[str] ? t[str][s_lan] : str;
|
// 从全局作用域获取 s_lan(支持 .jsc 文件加载)
|
||||||
|
const currentLang = (typeof global !== 'undefined' && global.s_lan) ? global.s_lan :
|
||||||
|
(typeof window !== 'undefined' && window.s_lan) ? window.s_lan : s_lan;
|
||||||
|
return t[str] ? (t[str][currentLang] || t[str]['zh'] || str) : str;
|
||||||
|
};
|
||||||
|
// 确保 language_str 在 global 作用域中也可用(用于 .jsc 文件加载)
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
global.language_str = window.language_str;
|
||||||
|
}
|
||||||
|
// 向后兼容
|
||||||
|
function language_str(str) {
|
||||||
|
return window.language_str(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取URL参数
|
// 获取URL参数
|
||||||
function GetFile() {
|
window.GetFile = function GetFile() {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
return params;
|
return params;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function GetFile() {
|
||||||
|
return window.GetFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日期格式化
|
// 日期格式化
|
||||||
function getDate() {
|
window.getDate = function getDate() {
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDate() {
|
||||||
|
return window.getDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取对象的绝对坐标
|
// 获取对象的绝对坐标
|
||||||
function getAbsoluteXY(_obj) {
|
window.getAbsoluteXY = function getAbsoluteXY(_obj) {
|
||||||
let coord = _obj.get("lineCoords");
|
let coord = _obj.get("lineCoords");
|
||||||
return [_obj.get("left"), _obj.get("top")];
|
return [_obj.get("left"), _obj.get("top")];
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getAbsoluteXY(_obj) {
|
||||||
|
return window.getAbsoluteXY(_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算两点之间的距离
|
// 计算两点之间的距离
|
||||||
function getDisdance(x1, y1, x2, y2) {
|
window.getDisdance = function getDisdance(x1, y1, x2, y2) {
|
||||||
var dx = Math.abs(x2 - x1);
|
var dx = Math.abs(x2 - x1);
|
||||||
var dy = Math.abs(y2 - y1);
|
var dy = Math.abs(y2 - y1);
|
||||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
return distance;
|
return distance;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDisdance(x1, y1, x2, y2) {
|
||||||
|
return window.getDisdance(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算角度(相对于画布中心)
|
// 计算角度(相对于画布中心)
|
||||||
function getDeg(pointer, canvas) {
|
window.getDeg = function getDeg(pointer, canvas) {
|
||||||
var centerX = canvas.width / 2;
|
var centerX = canvas.width / 2;
|
||||||
var centerY = canvas.height / 2;
|
var centerY = canvas.height / 2;
|
||||||
var mouseX = pointer.x;
|
var mouseX = pointer.x;
|
||||||
@@ -147,10 +232,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
angleDeg += 90;
|
angleDeg += 90;
|
||||||
return angleDeg;
|
return angleDeg;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getDeg(pointer, canvas) {
|
||||||
|
return window.getDeg(pointer, canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查字段名是否重复
|
// 检查字段名是否重复
|
||||||
function checkName(name, objs1, objs2) {
|
window.checkName = function checkName(name, objs1, objs2) {
|
||||||
for (let item of objs1) {
|
for (let item of objs1) {
|
||||||
if (item.name == name) {
|
if (item.name == name) {
|
||||||
return false;
|
return false;
|
||||||
@@ -162,20 +251,28 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function checkName(name, objs1, objs2) {
|
||||||
|
return window.checkName(name, objs1, objs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回不重复的字段名
|
// 返回不重复的字段名
|
||||||
function resName(pre_name, objs1, objs2) {
|
window.resName = function resName(pre_name, objs1, objs2) {
|
||||||
let num = (objs1.length + objs2.length) - 1;
|
let num = (objs1.length + objs2.length) - 1;
|
||||||
do {
|
do {
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
while (!checkName(pre_name + num, objs1, objs2));
|
while (!window.checkName(pre_name + num, objs1, objs2));
|
||||||
return pre_name + num;
|
return pre_name + num;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function resName(pre_name, objs1, objs2) {
|
||||||
|
return window.resName(pre_name, objs1, objs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取对象在画布中的索引
|
// 获取对象在画布中的索引
|
||||||
function getIndex(target, canvas, _canvas = null) {
|
window.getIndex = function getIndex(target, canvas, _canvas = null) {
|
||||||
let temp_objs;
|
let temp_objs;
|
||||||
if (_canvas == null) {
|
if (_canvas == null) {
|
||||||
temp_objs = canvas.getObjects();
|
temp_objs = canvas.getObjects();
|
||||||
@@ -190,10 +287,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getIndex(target, canvas, _canvas = null) {
|
||||||
|
return window.getIndex(target, canvas, _canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取对象类型
|
// 获取对象类型
|
||||||
function getType(target, canvas, objs) {
|
window.getType = function getType(target, canvas, objs) {
|
||||||
let temp_objs = canvas.getObjects();
|
let temp_objs = canvas.getObjects();
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (let res of temp_objs) {
|
for (let res of temp_objs) {
|
||||||
@@ -202,10 +303,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getType(target, canvas, objs) {
|
||||||
|
return window.getType(target, canvas, objs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取坐标的最小X值
|
// 获取坐标的最小X值
|
||||||
function getCoordsMinX(acoords) {
|
window.getCoordsMinX = function getCoordsMinX(acoords) {
|
||||||
let x = acoords[0].x;
|
let x = acoords[0].x;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.x < x) {
|
if (item.x < x) {
|
||||||
@@ -213,10 +318,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMinX(acoords) {
|
||||||
|
return window.getCoordsMinX(acoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取坐标的最大X值
|
// 获取坐标的最大X值
|
||||||
function getCoordsMaxX(acoords) {
|
window.getCoordsMaxX = function getCoordsMaxX(acoords) {
|
||||||
let x = acoords[0].x;
|
let x = acoords[0].x;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.x > x) {
|
if (item.x > x) {
|
||||||
@@ -224,10 +333,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMaxX(acoords) {
|
||||||
|
return window.getCoordsMaxX(acoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取坐标的最小Y值
|
// 获取坐标的最小Y值
|
||||||
function getCoordsMinY(acoords) {
|
window.getCoordsMinY = function getCoordsMinY(acoords) {
|
||||||
let y = acoords[0].y;
|
let y = acoords[0].y;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.y < y) {
|
if (item.y < y) {
|
||||||
@@ -235,10 +348,14 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMinY(acoords) {
|
||||||
|
return window.getCoordsMinY(acoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取坐标的最大Y值
|
// 获取坐标的最大Y值
|
||||||
function getCoordsMaxY(acoords) {
|
window.getCoordsMaxY = function getCoordsMaxY(acoords) {
|
||||||
let y = acoords[0].y;
|
let y = acoords[0].y;
|
||||||
for (let item of acoords) {
|
for (let item of acoords) {
|
||||||
if (item.y > y) {
|
if (item.y > y) {
|
||||||
@@ -246,26 +363,37 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function getCoordsMaxY(acoords) {
|
||||||
|
return window.getCoordsMaxY(acoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 全局变量定义(所有模块共享)
|
// 全局变量定义(所有模块共享)
|
||||||
|
// 注意:所有变量都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问
|
||||||
// ==========================================
|
// ==========================================
|
||||||
const dpi = 300; // design2使用300 DPI
|
window.dpi = 300; // design2使用300 DPI
|
||||||
let addState = 0; // 0是不添加
|
// 确保 dpi 在 global 作用域中也可用(用于 .jsc 文件加载)
|
||||||
let background_image, background_image1, background_image2;
|
if (typeof global !== 'undefined') {
|
||||||
let bg_version = 1;
|
global.dpi = window.dpi;
|
||||||
var zoom = 0;
|
}
|
||||||
let pre_add_image; // 预添加的图片对象(用于addPic)
|
window.addState = 0; // 0是不添加
|
||||||
|
window.background_image = undefined;
|
||||||
|
window.background_image1 = undefined;
|
||||||
|
window.background_image2 = undefined;
|
||||||
|
window.bg_version = 1;
|
||||||
|
window.zoom = 0;
|
||||||
|
window.pre_add_image = undefined; // 预添加的图片对象(用于addPic)
|
||||||
|
|
||||||
// 内部剪贴板
|
// 内部剪贴板
|
||||||
let clipboardData = {
|
window.clipboardData = {
|
||||||
data: null,
|
data: null,
|
||||||
offset: 10 // 粘贴位置偏移量
|
offset: 10 // 粘贴位置偏移量
|
||||||
};
|
};
|
||||||
|
|
||||||
// 文件管理
|
// 文件管理
|
||||||
var openAs = {
|
window.openAs = {
|
||||||
_name: "",
|
_name: "",
|
||||||
set name(val) {
|
set name(val) {
|
||||||
if (val == "") {
|
if (val == "") {
|
||||||
@@ -281,46 +409,142 @@ ipcRenderer.send('get-scale-rate');
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 对象数组和历史记录
|
// 对象数组和历史记录
|
||||||
let objs1 = [];
|
window.objs1 = [];
|
||||||
let objs2 = [];
|
window.objs2 = [];
|
||||||
let step1 = { val: 0 }, step2 = { val: 0 };
|
window.step1 = { val: 0 };
|
||||||
let step = step1;
|
window.step2 = { val: 0 };
|
||||||
let objs = objs1;
|
window.step = window.step1;
|
||||||
let recordJson1 = [], recordJson2 = [], recordJson = recordJson1, recordObjs1 = [], recordObjs2 = [], recordObjs = recordObjs1;
|
window.objs = window.objs1;
|
||||||
let pre_objs1 = [], pre_objs2 = [], next_objs1 = [], next_objs2 = [], pre_objs = pre_objs1, next_objs = next_objs1;
|
window.recordJson1 = [];
|
||||||
let pre_json1 = [], pre_json2 = [], next_json1 = [], next_json2 = [], pre_json = pre_json1, next_json = next_json1;
|
window.recordJson2 = [];
|
||||||
|
window.recordJson = window.recordJson1;
|
||||||
|
window.recordObjs1 = [];
|
||||||
|
window.recordObjs2 = [];
|
||||||
|
window.recordObjs = window.recordObjs1;
|
||||||
|
window.pre_objs1 = [];
|
||||||
|
window.pre_objs2 = [];
|
||||||
|
window.next_objs1 = [];
|
||||||
|
window.next_objs2 = [];
|
||||||
|
window.pre_objs = window.pre_objs1;
|
||||||
|
window.next_objs = window.next_objs1;
|
||||||
|
window.pre_json1 = [];
|
||||||
|
window.pre_json2 = [];
|
||||||
|
window.next_json1 = [];
|
||||||
|
window.next_json2 = [];
|
||||||
|
window.pre_json = window.pre_json1;
|
||||||
|
window.next_json = window.next_json1;
|
||||||
|
|
||||||
// Canvas对象(将在core.js中初始化)
|
// Canvas对象(将在core.js中初始化)
|
||||||
var canvas1, canvas2;
|
window.canvas1 = undefined;
|
||||||
var canvas; // 当前活动的画布(canvas1 或 canvas2)
|
window.canvas2 = undefined;
|
||||||
var ctx1, ctx2;
|
window.canvas = undefined; // 当前活动的画布(canvas1 或 canvas2)
|
||||||
let is_bgi_add = false;
|
window.ctx1 = undefined;
|
||||||
|
window.ctx2 = undefined;
|
||||||
|
window.is_bgi_add = false;
|
||||||
|
|
||||||
|
// 为了兼容性,同时创建局部变量引用(向后兼容)
|
||||||
|
const dpi = window.dpi;
|
||||||
|
let addState = window.addState;
|
||||||
|
let background_image = window.background_image;
|
||||||
|
let background_image1 = window.background_image1;
|
||||||
|
let background_image2 = window.background_image2;
|
||||||
|
let bg_version = window.bg_version;
|
||||||
|
var zoom = window.zoom;
|
||||||
|
let pre_add_image = window.pre_add_image;
|
||||||
|
let clipboardData = window.clipboardData;
|
||||||
|
var openAs = window.openAs;
|
||||||
|
let objs1 = window.objs1;
|
||||||
|
let objs2 = window.objs2;
|
||||||
|
let step1 = window.step1;
|
||||||
|
let step2 = window.step2;
|
||||||
|
let step = window.step;
|
||||||
|
let objs = window.objs;
|
||||||
|
let recordJson1 = window.recordJson1;
|
||||||
|
let recordJson2 = window.recordJson2;
|
||||||
|
let recordJson = window.recordJson;
|
||||||
|
let recordObjs1 = window.recordObjs1;
|
||||||
|
let recordObjs2 = window.recordObjs2;
|
||||||
|
let recordObjs = window.recordObjs;
|
||||||
|
let pre_objs1 = window.pre_objs1;
|
||||||
|
let pre_objs2 = window.pre_objs2;
|
||||||
|
let next_objs1 = window.next_objs1;
|
||||||
|
let next_objs2 = window.next_objs2;
|
||||||
|
let pre_objs = window.pre_objs;
|
||||||
|
let next_objs = window.next_objs;
|
||||||
|
let pre_json1 = window.pre_json1;
|
||||||
|
let pre_json2 = window.pre_json2;
|
||||||
|
let next_json1 = window.next_json1;
|
||||||
|
let next_json2 = window.next_json2;
|
||||||
|
let pre_json = window.pre_json;
|
||||||
|
let next_json = window.next_json;
|
||||||
|
var canvas1 = window.canvas1;
|
||||||
|
var canvas2 = window.canvas2;
|
||||||
|
var canvas = window.canvas;
|
||||||
|
var ctx1 = window.ctx1;
|
||||||
|
var ctx2 = window.ctx2;
|
||||||
|
let is_bgi_add = window.is_bgi_add;
|
||||||
|
|
||||||
// 加载design2模块
|
// 加载design2模块
|
||||||
// 由于模块代码需要在layui.use内部执行,我们通过动态加载的方式
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
let bytenode;
|
||||||
// 加载core.js(核心功能)
|
|
||||||
try {
|
try {
|
||||||
const coreCode = fs.readFileSync(__dirname + '/design2/core.js', 'utf8');
|
bytenode = require('bytenode');
|
||||||
eval(coreCode);
|
require.extensions['.dl'] = require.extensions['.jsc'];
|
||||||
} catch (e) {
|
} catch(e) {
|
||||||
console.error('加载core.js失败:', e);
|
console.warn('[加载模块] bytenode 未安装,无法加载 .jsc 文件');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载ui.js(UI控制)
|
const appPath = (() => { try { return remote.app.getAppPath(); } catch(e) { return __dirname || process.cwd(); } })();
|
||||||
|
|
||||||
|
// 读取模块映射配置
|
||||||
|
let moduleMap = {};
|
||||||
try {
|
try {
|
||||||
const uiCode = fs.readFileSync(__dirname + '/design2/ui.js', 'utf8');
|
const moduleMapPath = path.join(appPath, 'lib', 'module-map.json');
|
||||||
eval(uiCode);
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载ui.js失败:', e);
|
console.warn('[加载模块] 无法读取模块映射配置,使用默认文件名');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载output.js(输出功能)
|
// 获取映射后的文件名(跨平台兼容)
|
||||||
try {
|
function getMappedFileName(moduleName) {
|
||||||
const outputCode = fs.readFileSync(__dirname + '/design2/output.js', 'utf8');
|
if (moduleMap.mappings && moduleMap.mappings.design2 && moduleMap.mappings.design2[moduleName]) {
|
||||||
eval(outputCode);
|
return moduleMap.mappings.design2[moduleName];
|
||||||
|
}
|
||||||
|
return moduleName; // 默认使用原文件名
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadModule = (moduleName) => {
|
||||||
|
const mappedName = getMappedFileName(moduleName);
|
||||||
|
const jscPath = path.join(appPath, 'lib', 'design2', `${mappedName}.jsc`);
|
||||||
|
const jsPath = path.join(appPath, 'lib', 'design2', `${moduleName}.js`);
|
||||||
|
|
||||||
|
// 优先加载映射的 .jsc 文件
|
||||||
|
if (fs.existsSync(jscPath) && bytenode) {
|
||||||
|
try {
|
||||||
|
require(jscPath);
|
||||||
|
console.log(`[加载模块] ✅ ${moduleName} → ${mappedName}.jsc`);
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[加载模块] ❌ ${moduleName}.jsc 加载失败:`, e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回退到 .js 源文件
|
||||||
|
if (fs.existsSync(jsPath)) {
|
||||||
|
try {
|
||||||
|
eval(fs.readFileSync(jsPath, 'utf8'));
|
||||||
|
console.log(`[加载模块] ✅ ${moduleName} → ${moduleName}.js`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载output.js失败:', e);
|
console.error(`[加载模块] ❌ ${moduleName}.js 加载失败:`, e.message);
|
||||||
|
alert(`加载 ${moduleName} 失败!\n\n错误: ${e.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(`文件不存在!\n\n请检查:\n1. ${jscPath}\n2. ${jsPath}`);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
loadModule('output'); // 先加载 output,因为 core 中的 addBackground() 需要调用 output 中的 open()
|
||||||
|
loadModule('core');
|
||||||
|
loadModule('ui');
|
||||||
});
|
});
|
||||||
|
|||||||
+256
-957
File diff suppressed because it is too large
Load Diff
+153
-44
@@ -1,4 +1,5 @@
|
|||||||
function display_func(img1, img2, img3) {
|
// 将 display_func 附加到 window 对象,确保全局可访问
|
||||||
|
window.display_func = function display_func(img1, img2, img3) {
|
||||||
$('#base_control').hide()
|
$('#base_control').hide()
|
||||||
$('#line_control').hide()
|
$('#line_control').hide()
|
||||||
$('#pic_control').hide()
|
$('#pic_control').hide()
|
||||||
@@ -15,6 +16,27 @@ function display_func(img1, img2, img3) {
|
|||||||
$('#component_type').text(language_str('bg')) //"背景"
|
$('#component_type').text(language_str('bg')) //"背景"
|
||||||
canvas1.discardActiveObject().renderAll()
|
canvas1.discardActiveObject().renderAll()
|
||||||
canvas2.discardActiveObject().renderAll()
|
canvas2.discardActiveObject().renderAll()
|
||||||
|
|
||||||
|
// 保存所有对象的 selectable 和 evented 状态,确保预览后能恢复
|
||||||
|
const objStates1 = [];
|
||||||
|
const objStates2 = [];
|
||||||
|
canvas1.getObjects().forEach((obj, index) => {
|
||||||
|
if (!obj.isGuideLine) {
|
||||||
|
objStates1[index] = {
|
||||||
|
selectable: obj.selectable,
|
||||||
|
evented: obj.evented
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
canvas2.getObjects().forEach((obj, index) => {
|
||||||
|
if (!obj.isGuideLine) {
|
||||||
|
objStates2[index] = {
|
||||||
|
selectable: obj.selectable,
|
||||||
|
evented: obj.evented
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 过滤掉辅助线
|
// 过滤掉辅助线
|
||||||
let _objs1 = canvas1.getObjects().filter(obj => !obj.isGuideLine)
|
let _objs1 = canvas1.getObjects().filter(obj => !obj.isGuideLine)
|
||||||
let g1 = []
|
let g1 = []
|
||||||
@@ -114,10 +136,9 @@ function display_func(img1, img2, img3) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// g3.push(img1)
|
// g3.push(img1)
|
||||||
// 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整
|
|
||||||
let url3 = new fabric.Group(g3).toDataURL({
|
let url3 = new fabric.Group(g3).toDataURL({
|
||||||
format: 'png',
|
height: 648,
|
||||||
multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容
|
width: 1012,
|
||||||
top: all_top / zoom,
|
top: all_top / zoom,
|
||||||
left: all_left / zoom
|
left: all_left / zoom
|
||||||
})
|
})
|
||||||
@@ -225,10 +246,9 @@ function display_func(img1, img2, img3) {
|
|||||||
width: 1012
|
width: 1012
|
||||||
})
|
})
|
||||||
// g4.push(img2)
|
// g4.push(img2)
|
||||||
// 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整
|
|
||||||
let url4 = new fabric.Group(g4).toDataURL({
|
let url4 = new fabric.Group(g4).toDataURL({
|
||||||
format: 'png',
|
height: 648,
|
||||||
multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容
|
width: 1012,
|
||||||
top: all_top / zoom,
|
top: all_top / zoom,
|
||||||
left: all_left / zoom
|
left: all_left / zoom
|
||||||
})
|
})
|
||||||
@@ -323,23 +343,53 @@ function display_func(img1, img2, img3) {
|
|||||||
</div>`,
|
</div>`,
|
||||||
btn: btns, //'导出'
|
btn: btns, //'导出'
|
||||||
btn1: function (index, layero) {
|
btn1: function (index, layero) {
|
||||||
savePdf(Buffer.from(pdfBuffer))
|
// 只处理导出(保存PDF)
|
||||||
|
if (typeof window.savePdf === 'function') {
|
||||||
|
window.savePdf(Buffer.from(pdfBuffer));
|
||||||
|
} else {
|
||||||
|
console.error('savePdf 函数未定义!');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
btn2: function () {
|
btn2: function () {
|
||||||
|
// 根据 btns[1] 的值决定打印哪一面
|
||||||
if (btns[1] === '打印正面') {
|
if (btns[1] === '打印正面') {
|
||||||
|
// 打印正面
|
||||||
printJS({ printable: printPath3, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
printJS({ printable: printPath3, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
||||||
} else {
|
} else if (btns[1] === '打印背面') {
|
||||||
|
// 打印背面(只有背面时)
|
||||||
printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
btn3: function () {
|
btn3: function () {
|
||||||
//打印背面
|
// 打印背面(两面都有时,btn3 对应 btns[2] = '打印背面')
|
||||||
printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
||||||
|
},
|
||||||
|
end: function() {
|
||||||
|
// 预览窗口关闭后,恢复所有对象的 selectable 和 evented 状态
|
||||||
|
canvas1.getObjects().forEach((obj, index) => {
|
||||||
|
if (!obj.isGuideLine && objStates1[index]) {
|
||||||
|
obj.set({
|
||||||
|
selectable: objStates1[index].selectable,
|
||||||
|
evented: objStates1[index].evented
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
canvas2.getObjects().forEach((obj, index) => {
|
||||||
|
if (!obj.isGuideLine && objStates2[index]) {
|
||||||
|
obj.set({
|
||||||
|
selectable: objStates2[index].selectable,
|
||||||
|
evented: objStates2[index].evented
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
canvas1.renderAll();
|
||||||
|
canvas2.renderAll();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function output(callback = null, _save = save) {
|
// 将 output 附加到 window 对象,确保全局可访问
|
||||||
|
window.output = function output(callback = null, _save = save) {
|
||||||
// 类型改变
|
// 类型改变
|
||||||
fabric.Image.fromURL('./public/images/op_2.png', function (i1) {
|
fabric.Image.fromURL('./public/images/op_2.png', function (i1) {
|
||||||
i1.left = background_image.left
|
i1.left = background_image.left
|
||||||
@@ -464,10 +514,9 @@ function output(callback = null, _save = save) {
|
|||||||
left: left / zoom
|
left: left / zoom
|
||||||
})
|
})
|
||||||
g3.push(img1)
|
g3.push(img1)
|
||||||
// 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整
|
|
||||||
let url3 = new fabric.Group(g3).toDataURL({
|
let url3 = new fabric.Group(g3).toDataURL({
|
||||||
format: 'png',
|
height: 648,
|
||||||
multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容
|
width: 1012,
|
||||||
top: all_top / zoom,
|
top: all_top / zoom,
|
||||||
left: all_left / zoom
|
left: all_left / zoom
|
||||||
})
|
})
|
||||||
@@ -571,10 +620,9 @@ function output(callback = null, _save = save) {
|
|||||||
width: 1012
|
width: 1012
|
||||||
})
|
})
|
||||||
g4.push(img2)
|
g4.push(img2)
|
||||||
// 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整
|
|
||||||
let url4 = new fabric.Group(g4).toDataURL({
|
let url4 = new fabric.Group(g4).toDataURL({
|
||||||
format: 'png',
|
height: 648,
|
||||||
multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容
|
width: 1012,
|
||||||
top: all_top / zoom,
|
top: all_top / zoom,
|
||||||
left: all_left / zoom
|
left: all_left / zoom
|
||||||
})
|
})
|
||||||
@@ -902,7 +950,8 @@ function output(callback = null, _save = save) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重新生成二维码和条形码(加载文件后调用)
|
// 重新生成二维码和条形码(加载文件后调用)
|
||||||
function regenerateQrCodesAndBarcodes(canvas, objsArray) {
|
// 将 regenerateQrCodesAndBarcodes 附加到 window 对象,确保全局可访问
|
||||||
|
window.regenerateQrCodesAndBarcodes = function regenerateQrCodesAndBarcodes(canvas, objsArray) {
|
||||||
if (!canvas || !objsArray || !Array.isArray(objsArray)) return
|
if (!canvas || !objsArray || !Array.isArray(objsArray)) return
|
||||||
|
|
||||||
const objects = canvas.getObjects()
|
const objects = canvas.getObjects()
|
||||||
@@ -924,7 +973,7 @@ function regenerateQrCodesAndBarcodes(canvas, objsArray) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
foreground: objMeta.color || '#000000'
|
foreground: objMeta.color || '#000000'
|
||||||
})
|
})
|
||||||
obj.setSrc(qr, function(img) {
|
obj.setSrc(qr, function (img) {
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -938,7 +987,7 @@ function regenerateQrCodesAndBarcodes(canvas, objsArray) {
|
|||||||
})
|
})
|
||||||
const barcode = document.getElementById('barcode')
|
const barcode = document.getElementById('barcode')
|
||||||
const bar = barcode.toDataURL("image/png")
|
const bar = barcode.toDataURL("image/png")
|
||||||
obj.setSrc(bar, function(img) {
|
obj.setSrc(bar, function (img) {
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -946,7 +995,8 @@ function regenerateQrCodesAndBarcodes(canvas, objsArray) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清理不需要的 src 字段(保留自定义图片的 src)
|
// 清理不需要的 src 字段(保留自定义图片的 src)
|
||||||
function cleanupSrcFields(jsonObjects, objsArray) {
|
// 将 cleanupSrcFields 附加到 window 对象,确保在 ui.js 中的 saveAs 函数也能访问
|
||||||
|
window.cleanupSrcFields = function cleanupSrcFields(jsonObjects, objsArray) {
|
||||||
if (!jsonObjects || !Array.isArray(jsonObjects)) return;
|
if (!jsonObjects || !Array.isArray(jsonObjects)) return;
|
||||||
if (!objsArray || !Array.isArray(objsArray)) return;
|
if (!objsArray || !Array.isArray(objsArray)) return;
|
||||||
|
|
||||||
@@ -972,6 +1022,10 @@ function cleanupSrcFields(jsonObjects, objsArray) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function cleanupSrcFields(jsonObjects, objsArray) {
|
||||||
|
return window.cleanupSrcFields(jsonObjects, objsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAs(op1, callback) {
|
function saveAs(op1, callback) {
|
||||||
@@ -1009,18 +1063,27 @@ function saveAs(op1, callback) {
|
|||||||
dialog
|
dialog
|
||||||
.showSaveDialog({
|
.showSaveDialog({
|
||||||
title: language_str('saveFile'), //'保存文件'
|
title: language_str('saveFile'), //'保存文件'
|
||||||
filters: [{ name: 'Soon File Type', extensions: ['soon'] }]
|
filters: [{ name: 'Soon File Type', extensions: ['soon'] }],
|
||||||
|
defaultPath: openAs.name || undefined
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.filePath == '') {
|
if (result.filePath == '') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
if (result.filePath == null || result.filePath == undefined) {
|
||||||
result.filePath += '.soon'
|
return
|
||||||
}
|
}
|
||||||
|
// 检查文件扩展名,确保以.soon结尾
|
||||||
|
const path = require('path')
|
||||||
|
let filePath = result.filePath
|
||||||
|
const ext = path.extname(filePath).toLowerCase()
|
||||||
|
if (ext !== '.soon') {
|
||||||
|
filePath = filePath + '.soon'
|
||||||
|
}
|
||||||
|
result.filePath = filePath
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
con_o.soonType = 2
|
con_o.soonType = 2
|
||||||
fs.writeFileSync(result.filePath, JSON.stringify(con_o))
|
fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8')
|
||||||
openAs.name = result.filePath
|
openAs.name = result.filePath
|
||||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||||
saveHistory()
|
saveHistory()
|
||||||
@@ -1068,7 +1131,7 @@ function save(op1, callback) {
|
|||||||
//打开的文件
|
//打开的文件
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
con_o.soonType = 2
|
con_o.soonType = 2
|
||||||
fs.writeFileSync(openAs.name, JSON.stringify(con_o))
|
fs.writeFileSync(openAs.name, JSON.stringify(con_o), 'utf8')
|
||||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||||
saveHistory()
|
saveHistory()
|
||||||
if (callback && typeof callback === 'function') {
|
if (callback && typeof callback === 'function') {
|
||||||
@@ -1079,18 +1142,27 @@ function save(op1, callback) {
|
|||||||
dialog
|
dialog
|
||||||
.showSaveDialog({
|
.showSaveDialog({
|
||||||
title: language_str('saveFile'), //'保存文件'
|
title: language_str('saveFile'), //'保存文件'
|
||||||
filters: [{ name: 'Soon File Type', extensions: ['soon'] }]
|
filters: [{ name: 'Soon File Type', extensions: ['soon'] }],
|
||||||
|
defaultPath: openAs.name || undefined
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.filePath == '') {
|
if (result.filePath == '') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
if (result.filePath == null || result.filePath == undefined) {
|
||||||
result.filePath += '.soon'
|
return
|
||||||
}
|
}
|
||||||
|
// 检查文件扩展名,确保以.soon结尾
|
||||||
|
const path = require('path')
|
||||||
|
let filePath = result.filePath
|
||||||
|
const ext = path.extname(filePath).toLowerCase()
|
||||||
|
if (ext !== '.soon') {
|
||||||
|
filePath = filePath + '.soon'
|
||||||
|
}
|
||||||
|
result.filePath = filePath
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
con_o.soonType = 2
|
con_o.soonType = 2
|
||||||
fs.writeFileSync(result.filePath, JSON.stringify(con_o))
|
fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8')
|
||||||
openAs.name = result.filePath
|
openAs.name = result.filePath
|
||||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||||
saveHistory()
|
saveHistory()
|
||||||
@@ -1102,7 +1174,8 @@ function save(op1, callback) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveHistory() {
|
// 将 saveHistory 附加到 window 对象,确保在 ui.js 中也能访问
|
||||||
|
window.saveHistory = function saveHistory() {
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
let j = {}
|
let j = {}
|
||||||
try {
|
try {
|
||||||
@@ -1111,19 +1184,24 @@ function saveHistory() {
|
|||||||
for (let item of j.history) {
|
for (let item of j.history) {
|
||||||
if (item.path == openAs.name) {
|
if (item.path == openAs.name) {
|
||||||
item.time = getDate()
|
item.time = getDate()
|
||||||
fs.writeFileSync(fullPath, JSON.stringify(j))
|
fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
j.history.push({ time: getDate(), path: openAs.name })
|
j.history.push({ time: getDate(), path: openAs.name })
|
||||||
fs.writeFileSync(fullPath, JSON.stringify(j))
|
fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let j = { history: { time: getDate(), path: openAs.name } }
|
let j = { history: { time: getDate(), path: openAs.name } }
|
||||||
fs.writeFileSync(fullPath, JSON.stringify(j))
|
fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8')
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
// 向后兼容
|
||||||
|
function saveHistory() {
|
||||||
|
return window.saveHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
function open(file) {
|
// 使用 window.openFile 避免与浏览器原生的 window.open 冲突
|
||||||
|
window.openFile = function open(file) {
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
var fsData = fs.readFileSync(file)
|
var fsData = fs.readFileSync(file)
|
||||||
openAs.name = file
|
openAs.name = file
|
||||||
@@ -1169,12 +1247,16 @@ function open(file) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 加载 JSON,并在回调中重新生成二维码和条形码
|
// 加载 JSON,并在回调中重新生成二维码和条形码
|
||||||
canvas1.loadFromJSON(j.f, function() {
|
canvas1.loadFromJSON(j.f, function () {
|
||||||
regenerateQrCodesAndBarcodes(canvas1, fo)
|
if (typeof window.regenerateQrCodesAndBarcodes === 'function') {
|
||||||
|
window.regenerateQrCodesAndBarcodes(canvas1, fo);
|
||||||
|
}
|
||||||
canvas1.renderAll()
|
canvas1.renderAll()
|
||||||
})
|
})
|
||||||
canvas2.loadFromJSON(j.b, function() {
|
canvas2.loadFromJSON(j.b, function () {
|
||||||
regenerateQrCodesAndBarcodes(canvas2, bo)
|
if (typeof window.regenerateQrCodesAndBarcodes === 'function') {
|
||||||
|
window.regenerateQrCodesAndBarcodes(canvas2, bo);
|
||||||
|
}
|
||||||
canvas2.renderAll()
|
canvas2.renderAll()
|
||||||
})
|
})
|
||||||
background_image1 = canvas1.getObjects()[0]
|
background_image1 = canvas1.getObjects()[0]
|
||||||
@@ -1203,10 +1285,22 @@ function open(file) {
|
|||||||
}
|
}
|
||||||
canvas1.renderAll()
|
canvas1.renderAll()
|
||||||
canvas2.renderAll()
|
canvas2.renderAll()
|
||||||
updateList() /*
|
// 调用 updateList,现在它已附加到 window 对象
|
||||||
修复打开新文件后无法撤销的bug
|
if (typeof window.updateList === 'function') {
|
||||||
2022-07-16
|
window.updateList(); /*
|
||||||
*/
|
修复打开新文件后无法撤销的bug
|
||||||
|
2022-07-16
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
// 延迟检查,确保 core.js 已加载
|
||||||
|
setTimeout(() => {
|
||||||
|
if (typeof window.updateList === 'function') {
|
||||||
|
window.updateList();
|
||||||
|
} else {
|
||||||
|
console.error('[open函数] ❌ updateList 函数未定义!');
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
recordObjs1.push(JSON.stringify(objs1))
|
recordObjs1.push(JSON.stringify(objs1))
|
||||||
let j1 = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])
|
let j1 = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])
|
||||||
@@ -1257,7 +1351,22 @@ function clearAll() {
|
|||||||
openAs.name = ''
|
openAs.name = ''
|
||||||
canvas1.renderAll()
|
canvas1.renderAll()
|
||||||
canvas2.renderAll()
|
canvas2.renderAll()
|
||||||
updateList()
|
// 调用 updateList,现在它已附加到 window 对象
|
||||||
|
if (typeof window.updateList === 'function') {
|
||||||
|
window.updateList();
|
||||||
|
} else {
|
||||||
|
// 延迟检查,确保 core.js 已加载
|
||||||
|
setTimeout(() => {
|
||||||
|
if (typeof window.updateList === 'function') {
|
||||||
|
window.updateList();
|
||||||
|
} else {
|
||||||
|
console.error('[clearAll] ❌ updateList 函数未定义!');
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
console.log()
|
console.log()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将 clearAll 附加到 window 对象,确保全局可访问
|
||||||
|
window.clearAll = clearAll;
|
||||||
|
|
||||||
|
|||||||
+1036
-839
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
|||||||
Example:
|
|
||||||
nvm install v0.10.32 Install a specific version number
|
|
||||||
nvm use 0.10 Use the latest available 0.10.x release
|
|
||||||
nvm run 0.10.32 app.js Run app.js using node v0.10.32
|
|
||||||
nvm exec 0.10.32 node app.js Run `node app.js` with the PATH pointing to node v0.10.32
|
|
||||||
nvm alias default 0.10.32 Set default node version on a shell
|
|
||||||
|
|
||||||
Note:
|
|
||||||
to remove, delete, or uninstall nvm - just remove the `$NVM_DIR` folder (usually `~/.nvm`)
|
|
||||||
|
|
||||||
Xupnei:~ xuwenwei$ nvm install v16.5.0
|
|
||||||
|
|
||||||
Version 'v16.5.0' not found - try `nvm ls-remote` to browse available versions.
|
|
||||||
Xupnei:~ xuwenwei$
|
|
||||||
Xupnei:~ xuwenwei$ nvm install v16.5.0
|
|
||||||
Downloading and installing node v16.5.0...
|
|
||||||
Downloading https://nodejs.org/dist/v16.5.0/node-v16.5.0-darwin-arm64.tar.gz...
|
|
||||||
######################################################################### 100.0%
|
|
||||||
Computing checksum with shasum -a 256
|
|
||||||
Checksums matched!
|
|
||||||
Now using node v16.5.0 (npm v7.19.1)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
Example:
|
|
||||||
nvm install v0.10.32 Install a specific version number
|
|
||||||
nvm use 0.10 Use the latest available 0.10.x release
|
|
||||||
nvm run 0.10.32 app.js Run app.js using node v0.10.32
|
|
||||||
nvm exec 0.10.32 node app.js Run `node app.js` with the PATH pointing to node v0.10.32
|
|
||||||
nvm alias default 0.10.32 Set default node version on a shell
|
|
||||||
|
|
||||||
Note:
|
|
||||||
to remove, delete, or uninstall nvm - just remove the `$NVM_DIR` folder (usually `~/.nvm`)
|
|
||||||
|
|
||||||
Xupnei:~ xuwenwei$ nvm install v16.5.0
|
|
||||||
|
|
||||||
Version 'v16.5.0' not found - try `nvm ls-remote` to browse available versions.
|
|
||||||
Xupnei:~ xuwenwei$
|
|
||||||
Xupnei:~ xuwenwei$ nvm install v16.5.0
|
|
||||||
Downloading and installing node v16.5.0...
|
|
||||||
Downloading https://nodejs.org/dist/v16.5.0/node-v16.5.0-darwin-arm64.tar.gz...
|
|
||||||
######################################################################### 100.0%
|
|
||||||
Computing checksum with shasum -a 256
|
|
||||||
Checksums matched!
|
|
||||||
Now using node v16.5.0 (npm v7.19.1)
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"description": "模块文件名映射配置 - 用于加密后重命名文件",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "core1",
|
||||||
|
"output": "output1",
|
||||||
|
"ui": "ui1"
|
||||||
|
},
|
||||||
|
"design2": {
|
||||||
|
"core": "core2",
|
||||||
|
"output": "output2",
|
||||||
|
"ui": "ui2"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"index": "index1",
|
||||||
|
"design1": "design11",
|
||||||
|
"design2": "design22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
"修改此文件中的映射值可以重命名加密后的文件",
|
||||||
|
"例如:将 'core' 改为 'core_v2',加密后会生成 core_v2.jsc",
|
||||||
|
"修改后需要重新运行加密脚本",
|
||||||
|
"确保映射值唯一,避免冲突"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
@@ -152,26 +152,78 @@ function createWindow() {
|
|||||||
const fileName = 'User Manual.pdf';
|
const fileName = 'User Manual.pdf';
|
||||||
|
|
||||||
if (app.isPackaged) {
|
if (app.isPackaged) {
|
||||||
helpPath = path.join(process.resourcesPath, 'help', fileName);
|
// Linux打包后的路径:resources/help/ 或 resources/app.asar/help/
|
||||||
|
// Windows/Mac打包后的路径:resources/help/
|
||||||
|
if (process.platform === 'linux') {
|
||||||
|
// Linux上,尝试多个可能的路径
|
||||||
|
const possiblePaths = [
|
||||||
|
path.join(process.resourcesPath, 'help', fileName),
|
||||||
|
path.join(process.resourcesPath, 'app.asar', 'help', fileName),
|
||||||
|
path.join(__dirname, 'help', fileName),
|
||||||
|
path.join(process.resourcesPath, '..', 'help', fileName)
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const testPath of possiblePaths) {
|
||||||
|
if (fs.existsSync(testPath)) {
|
||||||
|
helpPath = testPath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
helpPath = path.join(process.resourcesPath, 'help', fileName);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
helpPath = path.join(process.cwd(), 'help', fileName);
|
helpPath = path.join(process.cwd(), 'help', fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Help file path: ", helpPath);
|
console.log("Help file path: ", helpPath);
|
||||||
|
|
||||||
if (fs.existsSync(helpPath)) {
|
if (helpPath && fs.existsSync(helpPath)) {
|
||||||
try {
|
try {
|
||||||
const errorMessage = await shell.openPath(helpPath);
|
// Linux上使用shell.openExternal更可靠
|
||||||
if (errorMessage) {
|
if (process.platform === 'linux') {
|
||||||
console.error('Error opening help file:', errorMessage);
|
await shell.openExternal(`file://${helpPath}`);
|
||||||
} else {
|
} else {
|
||||||
console.log('Help file opened successfully');
|
const errorMessage = await shell.openPath(helpPath);
|
||||||
|
if (errorMessage) {
|
||||||
|
console.error('Error opening help file:', errorMessage);
|
||||||
|
// 如果openPath失败,尝试openExternal
|
||||||
|
await shell.openExternal(`file://${helpPath}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
console.log('Help file opened successfully');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Exception when opening file:', err);
|
console.error('Exception when opening file:', err);
|
||||||
|
// 尝试使用openExternal作为后备方案
|
||||||
|
try {
|
||||||
|
await shell.openExternal(`file://${helpPath}`);
|
||||||
|
} catch (err2) {
|
||||||
|
console.error('Failed to open with openExternal:', err2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('Help file not found at:', helpPath);
|
console.error('Help file not found at:', helpPath);
|
||||||
|
// 尝试查找help文件的其他可能位置
|
||||||
|
const searchPaths = [
|
||||||
|
path.join(__dirname, 'help', fileName),
|
||||||
|
path.join(process.cwd(), 'help', fileName),
|
||||||
|
path.join(app.getAppPath(), 'help', fileName)
|
||||||
|
];
|
||||||
|
for (const searchPath of searchPaths) {
|
||||||
|
if (fs.existsSync(searchPath)) {
|
||||||
|
console.log('Found help file at alternative path:', searchPath);
|
||||||
|
try {
|
||||||
|
if (process.platform === 'linux') {
|
||||||
|
await shell.openExternal(`file://${searchPath}`);
|
||||||
|
} else {
|
||||||
|
await shell.openPath(searchPath);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to open help file:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+30
-4
@@ -5,11 +5,20 @@
|
|||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
"build": "electron-builder",
|
"encrypt:win": "scripts/encrypt/encrypt-electron-win.bat",
|
||||||
|
"encrypt:linux": "./scripts/encrypt/encrypt-electron.sh",
|
||||||
|
"cleanup:jsc": "node scripts/encrypt/cleanup-jsc.js",
|
||||||
|
"cleanup": "node scripts/encrypt/cleanup.js",
|
||||||
|
"restore": "node scripts/encrypt/restore.js",
|
||||||
"build:win": "electron-builder --win --x64",
|
"build:win": "electron-builder --win --x64",
|
||||||
"build:mac": "electron-builder --mac --x64",
|
"build:mac": "electron-builder --mac --x64",
|
||||||
"build:linux": "electron-builder --linux --x64",
|
"build:linux": "electron-builder --linux --x64",
|
||||||
"build:all": "electron-builder -mwl"
|
"build:linux:arm64": "electron-builder --linux --arm64",
|
||||||
|
"build:all": "electron-builder -mwl",
|
||||||
|
"release:win": "npm run encrypt:win && npm run cleanup && npm run build:win",
|
||||||
|
"release:mac": "npm run encrypt:linux && npm run cleanup && npm run build:mac",
|
||||||
|
"release:linux": "npm run encrypt:linux && npm run cleanup && npm run build:linux",
|
||||||
|
"release:linux:arm64": "npm run build:linux:arm64"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"productName": "SoonDesign",
|
"productName": "SoonDesign",
|
||||||
@@ -21,6 +30,23 @@
|
|||||||
"extraFiles": [
|
"extraFiles": [
|
||||||
"lib"
|
"lib"
|
||||||
],
|
],
|
||||||
|
"files": [
|
||||||
|
"**/*",
|
||||||
|
"!.backup/**",
|
||||||
|
"!scripts/**",
|
||||||
|
"!**/*.jsc.map",
|
||||||
|
"!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}",
|
||||||
|
"!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples}",
|
||||||
|
"!**/node_modules/*.d.ts",
|
||||||
|
"!**/node_modules/.bin",
|
||||||
|
"!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}",
|
||||||
|
"!.editorconfig",
|
||||||
|
"!**/._*",
|
||||||
|
"!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}",
|
||||||
|
"!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}",
|
||||||
|
"!**/{appveyor.yml,.travis.yml,circle.yml}",
|
||||||
|
"!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json}"
|
||||||
|
],
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"oneClick": false,
|
"oneClick": false,
|
||||||
"allowElevation": true,
|
"allowElevation": true,
|
||||||
@@ -65,8 +91,8 @@
|
|||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": [
|
"target": [
|
||||||
{ "target": "AppImage", "arch": ["x64"] },
|
{ "target": "AppImage", "arch": ["x64", "arm64"] },
|
||||||
{ "target": "deb", "arch": ["x64"] }
|
{ "target": "deb", "arch": ["x64", "arm64"] }
|
||||||
],
|
],
|
||||||
"category": "Utility",
|
"category": "Utility",
|
||||||
"icon": "public/images/IconA256.png",
|
"icon": "public/images/IconA256.png",
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ function initAligningGuidelines(canvas) {
|
|||||||
|
|
||||||
if (!transform) return;
|
if (!transform) return;
|
||||||
|
|
||||||
|
// 清空辅助线数组,避免累积
|
||||||
|
verticalLines.length = 0;
|
||||||
|
horizontalLines.length = 0;
|
||||||
|
|
||||||
// It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions,
|
// It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions,
|
||||||
// but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move
|
// but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move
|
||||||
|
|
||||||
@@ -84,6 +88,9 @@ function initAligningGuidelines(canvas) {
|
|||||||
|
|
||||||
if (canvasObjects[i] === activeObject) continue;
|
if (canvasObjects[i] === activeObject) continue;
|
||||||
|
|
||||||
|
// 跳过辅助线对象,避免辅助线之间相互对齐产生重影
|
||||||
|
if (canvasObjects[i].isGuideLine) continue;
|
||||||
|
|
||||||
var objectCenter = canvasObjects[i].getCenterPoint(),
|
var objectCenter = canvasObjects[i].getCenterPoint(),
|
||||||
objectLeft = objectCenter.x,
|
objectLeft = objectCenter.x,
|
||||||
objectTop = objectCenter.y,
|
objectTop = objectCenter.y,
|
||||||
@@ -202,11 +209,40 @@ function initAligningGuidelines(canvas) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
canvas.on('after:render', function() {
|
canvas.on('after:render', function() {
|
||||||
|
// 合并相同 x 坐标的竖向辅助线(使用四舍五入处理浮点数精度问题)
|
||||||
|
var mergedVerticalLines = {};
|
||||||
for (var i = verticalLines.length; i--; ) {
|
for (var i = verticalLines.length; i--; ) {
|
||||||
drawVerticalLine(verticalLines[i]);
|
var line = verticalLines[i];
|
||||||
|
// 使用四舍五入到整数作为 key,避免浮点数精度问题
|
||||||
|
var key = Math.round(line.x);
|
||||||
|
if (!mergedVerticalLines[key]) {
|
||||||
|
mergedVerticalLines[key] = { x: line.x, y1: line.y1, y2: line.y2 };
|
||||||
|
} else {
|
||||||
|
// 合并 y 范围
|
||||||
|
mergedVerticalLines[key].y1 = Math.min(mergedVerticalLines[key].y1, line.y1);
|
||||||
|
mergedVerticalLines[key].y2 = Math.max(mergedVerticalLines[key].y2, line.y2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
for (var key in mergedVerticalLines) {
|
||||||
|
drawVerticalLine(mergedVerticalLines[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并相同 y 坐标的横向辅助线(使用四舍五入处理浮点数精度问题)
|
||||||
|
var mergedHorizontalLines = {};
|
||||||
for (var i = horizontalLines.length; i--; ) {
|
for (var i = horizontalLines.length; i--; ) {
|
||||||
drawHorizontalLine(horizontalLines[i]);
|
var line = horizontalLines[i];
|
||||||
|
// 使用四舍五入到整数作为 key,避免浮点数精度问题
|
||||||
|
var key = Math.round(line.y);
|
||||||
|
if (!mergedHorizontalLines[key]) {
|
||||||
|
mergedHorizontalLines[key] = { y: line.y, x1: line.x1, x2: line.x2 };
|
||||||
|
} else {
|
||||||
|
// 合并 x 范围
|
||||||
|
mergedHorizontalLines[key].x1 = Math.min(mergedHorizontalLines[key].x1, line.x1);
|
||||||
|
mergedHorizontalLines[key].x2 = Math.max(mergedHorizontalLines[key].x2, line.x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var key in mergedHorizontalLines) {
|
||||||
|
drawHorizontalLine(mergedHorizontalLines[key]);
|
||||||
}
|
}
|
||||||
verticalLines.length = horizontalLines.length = 0;
|
verticalLines.length = horizontalLines.length = 0;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ function initAligningGuidelines(canvas) {
|
|||||||
|
|
||||||
if (!transform) return;
|
if (!transform) return;
|
||||||
|
|
||||||
|
// 清空辅助线数组,避免累积
|
||||||
|
verticalLines.length = 0;
|
||||||
|
horizontalLines.length = 0;
|
||||||
|
|
||||||
// It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions,
|
// It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions,
|
||||||
// but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move
|
// but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move
|
||||||
|
|
||||||
@@ -84,6 +88,9 @@ function initAligningGuidelines(canvas) {
|
|||||||
|
|
||||||
if (canvasObjects[i] === activeObject) continue;
|
if (canvasObjects[i] === activeObject) continue;
|
||||||
|
|
||||||
|
// 跳过辅助线对象,避免辅助线之间相互对齐产生重影
|
||||||
|
if (canvasObjects[i].isGuideLine) continue;
|
||||||
|
|
||||||
var objectCenter = canvasObjects[i].getCenterPoint(),
|
var objectCenter = canvasObjects[i].getCenterPoint(),
|
||||||
objectLeft = objectCenter.x,
|
objectLeft = objectCenter.x,
|
||||||
objectTop = objectCenter.y,
|
objectTop = objectCenter.y,
|
||||||
@@ -202,11 +209,40 @@ function initAligningGuidelines(canvas) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
canvas.on('after:render', function() {
|
canvas.on('after:render', function() {
|
||||||
|
// 合并相同 x 坐标的竖向辅助线(使用四舍五入处理浮点数精度问题)
|
||||||
|
var mergedVerticalLines = {};
|
||||||
for (var i = verticalLines.length; i--; ) {
|
for (var i = verticalLines.length; i--; ) {
|
||||||
drawVerticalLine(verticalLines[i]);
|
var line = verticalLines[i];
|
||||||
|
// 使用四舍五入到整数作为 key,避免浮点数精度问题
|
||||||
|
var key = Math.round(line.x);
|
||||||
|
if (!mergedVerticalLines[key]) {
|
||||||
|
mergedVerticalLines[key] = { x: line.x, y1: line.y1, y2: line.y2 };
|
||||||
|
} else {
|
||||||
|
// 合并 y 范围
|
||||||
|
mergedVerticalLines[key].y1 = Math.min(mergedVerticalLines[key].y1, line.y1);
|
||||||
|
mergedVerticalLines[key].y2 = Math.max(mergedVerticalLines[key].y2, line.y2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
for (var key in mergedVerticalLines) {
|
||||||
|
drawVerticalLine(mergedVerticalLines[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并相同 y 坐标的横向辅助线(使用四舍五入处理浮点数精度问题)
|
||||||
|
var mergedHorizontalLines = {};
|
||||||
for (var i = horizontalLines.length; i--; ) {
|
for (var i = horizontalLines.length; i--; ) {
|
||||||
drawHorizontalLine(horizontalLines[i]);
|
var line = horizontalLines[i];
|
||||||
|
// 使用四舍五入到整数作为 key,避免浮点数精度问题
|
||||||
|
var key = Math.round(line.y);
|
||||||
|
if (!mergedHorizontalLines[key]) {
|
||||||
|
mergedHorizontalLines[key] = { y: line.y, x1: line.x1, x2: line.x2 };
|
||||||
|
} else {
|
||||||
|
// 合并 x 范围
|
||||||
|
mergedHorizontalLines[key].x1 = Math.min(mergedHorizontalLines[key].x1, line.x1);
|
||||||
|
mergedHorizontalLines[key].x2 = Math.max(mergedHorizontalLines[key].x2, line.x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var key in mergedHorizontalLines) {
|
||||||
|
drawHorizontalLine(mergedHorizontalLines[key]);
|
||||||
}
|
}
|
||||||
verticalLines.length = horizontalLines.length = 0;
|
verticalLines.length = horizontalLines.length = 0;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
# 加密脚本使用说明
|
||||||
|
|
||||||
|
## 📁 文件说明
|
||||||
|
|
||||||
|
- `encrypt-electron.js` - 主加密脚本
|
||||||
|
- `encrypt-electron-win.bat` - Windows 批处理脚本
|
||||||
|
- `encrypt-electron.sh` - Linux/Mac Shell 脚本
|
||||||
|
- `cleanup-jsc.js` - 清理 .jsc 文件脚本
|
||||||
|
- `cleanup.js` - 清理源文件脚本(备份到 .backup)
|
||||||
|
- `restore.js` - 恢复源文件脚本(从 .backup)
|
||||||
|
- `module-map.json` - **模块文件名映射配置**(位于 `lib` 目录)
|
||||||
|
|
||||||
|
## 🔧 模块文件名映射配置
|
||||||
|
|
||||||
|
### 功能说明
|
||||||
|
|
||||||
|
`module-map.json` 允许你自定义加密后生成的文件名。这对于:
|
||||||
|
- 版本管理:不同版本使用不同的文件名
|
||||||
|
- 安全加固:使用不易猜测的文件名
|
||||||
|
- 多版本共存:同时保留多个版本的加密文件
|
||||||
|
|
||||||
|
### 配置文件结构
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "core", // 原文件名 → 加密后文件名(不含扩展名)
|
||||||
|
"output": "output",
|
||||||
|
"ui": "ui"
|
||||||
|
},
|
||||||
|
"design2": {
|
||||||
|
"core": "core",
|
||||||
|
"output": "output",
|
||||||
|
"ui": "ui"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"index": "index",
|
||||||
|
"design1": "design1",
|
||||||
|
"design2": "design2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用示例
|
||||||
|
|
||||||
|
#### 示例 1:添加版本号
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "core_v2",
|
||||||
|
"output": "output_v2",
|
||||||
|
"ui": "ui_v2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
加密后会生成:`core_v2.jsc`, `output_v2.jsc`, `ui_v2.jsc`
|
||||||
|
|
||||||
|
#### 示例 2:使用随机名称
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "a1b2c3",
|
||||||
|
"output": "x9y8z7",
|
||||||
|
"ui": "m5n6o4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
加密后会生成:`a1b2c3.jsc`, `x9y8z7.jsc`, `m5n6o4.jsc`
|
||||||
|
|
||||||
|
### 使用步骤
|
||||||
|
|
||||||
|
1. **修改配置文件**
|
||||||
|
```bash
|
||||||
|
# 编辑 lib/module-map.json
|
||||||
|
# 修改 mappings 中的值
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **运行加密脚本**
|
||||||
|
```bash
|
||||||
|
npm run encrypt:win # Windows
|
||||||
|
npm run encrypt:linux # Linux/Mac
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **验证结果**
|
||||||
|
- 检查 `lib/design1/` 和 `lib/design2/` 目录
|
||||||
|
- 确认生成了映射后的 `.jsc` 文件
|
||||||
|
|
||||||
|
### ⚠️ 注意事项
|
||||||
|
|
||||||
|
1. **唯一性**:确保映射值唯一,避免文件名冲突
|
||||||
|
2. **重新加密**:修改配置后必须重新运行加密脚本
|
||||||
|
3. **备份**:修改前建议备份配置文件
|
||||||
|
4. **兼容性**:映射后的文件名会在运行时自动识别,无需修改代码
|
||||||
|
5. **清理**:清理脚本会自动识别映射后的文件名
|
||||||
|
|
||||||
|
### 🔄 恢复默认
|
||||||
|
|
||||||
|
如果不想使用映射,将所有值改回原文件名即可:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mappings": {
|
||||||
|
"design1": {
|
||||||
|
"core": "core",
|
||||||
|
"output": "output",
|
||||||
|
"ui": "ui"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 获取项目根目录(脚本在 scripts/encrypt 目录下,需要向上两级)
|
||||||
|
const projectRoot = path.resolve(__dirname, '../..');
|
||||||
|
|
||||||
|
// 读取模块映射配置(从 lib 目录读取)
|
||||||
|
const moduleMapPath = path.join(projectRoot, 'lib', 'module-map.json');
|
||||||
|
let moduleMap = {};
|
||||||
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
try {
|
||||||
|
moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`⚠️ 读取模块映射配置失败: ${error.message},将清理所有 .jsc 文件\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件映射函数:根据配置返回加密后的文件名(跨平台兼容)
|
||||||
|
function getEncryptedFileName(originalPath) {
|
||||||
|
// 使用 path 模块处理路径,确保跨平台兼容
|
||||||
|
const normalizedPath = originalPath.replace(/\\/g, '/'); // 统一使用正斜杠
|
||||||
|
const parts = normalizedPath.split('/');
|
||||||
|
const fileName = parts[parts.length - 1].replace('.js', '');
|
||||||
|
const dirName = parts[parts.length - 2];
|
||||||
|
|
||||||
|
// 检查是否有映射配置
|
||||||
|
if (moduleMap.mappings) {
|
||||||
|
if (dirName === 'design1' && moduleMap.mappings.design1 && moduleMap.mappings.design1[fileName]) {
|
||||||
|
return moduleMap.mappings.design1[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'design2' && moduleMap.mappings.design2 && moduleMap.mappings.design2[fileName]) {
|
||||||
|
return moduleMap.mappings.design2[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'lib' && moduleMap.mappings.main && moduleMap.mappings.main[fileName]) {
|
||||||
|
return moduleMap.mappings.main[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认:原文件名 + 'c'
|
||||||
|
return fileName + '.jsc';
|
||||||
|
}
|
||||||
|
|
||||||
|
const filesToClean = [
|
||||||
|
'lib/index.js', 'lib/design1.js', 'lib/design2.js',
|
||||||
|
'lib/design1/core.js', 'lib/design1/output.js', 'lib/design1/ui.js',
|
||||||
|
'lib/design2/core.js', 'lib/design2/output.js', 'lib/design2/ui.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log('正在删除所有 .jsc 文件...\n');
|
||||||
|
|
||||||
|
let deletedCount = 0;
|
||||||
|
let notFoundCount = 0;
|
||||||
|
|
||||||
|
filesToClean.forEach(filePath => {
|
||||||
|
// 跨平台兼容的路径处理
|
||||||
|
const fullPath = path.join(projectRoot, filePath);
|
||||||
|
const dir = path.dirname(fullPath);
|
||||||
|
const encryptedFileName = getEncryptedFileName(filePath);
|
||||||
|
|
||||||
|
// 尝试删除映射后的文件名
|
||||||
|
const mappedJscPath = path.join(dir, encryptedFileName);
|
||||||
|
const defaultJscPath = fullPath + 'c';
|
||||||
|
|
||||||
|
// 使用 path.resolve 进行规范化比较,确保跨平台兼容
|
||||||
|
const normalizedDefault = path.resolve(defaultJscPath);
|
||||||
|
const normalizedMapped = path.resolve(mappedJscPath);
|
||||||
|
|
||||||
|
if (fs.existsSync(mappedJscPath)) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(mappedJscPath);
|
||||||
|
console.log(`✅ 已删除: ${mappedJscPath}`);
|
||||||
|
deletedCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ 删除失败: ${mappedJscPath} - ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 也尝试删除默认名称的 .jsc 文件(兼容旧版本)
|
||||||
|
if (fs.existsSync(defaultJscPath) && normalizedMapped !== normalizedDefault) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(defaultJscPath);
|
||||||
|
console.log(`✅ 已删除: ${defaultJscPath}`);
|
||||||
|
deletedCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ 删除失败: ${defaultJscPath} - ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(mappedJscPath) && !fs.existsSync(defaultJscPath)) {
|
||||||
|
notFoundCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n完成!已删除 ${deletedCount} 个文件,${notFoundCount} 个文件不存在`);
|
||||||
|
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* 清理脚本 - 删除源 JS 文件(保留 .jsc 文件)
|
||||||
|
*
|
||||||
|
* 使用方法:
|
||||||
|
* node cleanup.js
|
||||||
|
*
|
||||||
|
* 注意:此脚本会自动备份源文件到 .backup 目录
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 获取项目根目录(脚本在 scripts/encrypt 目录下,需要向上两级)
|
||||||
|
const projectRoot = path.resolve(__dirname, '../..');
|
||||||
|
|
||||||
|
// 读取模块映射配置(从 lib 目录读取,跨平台兼容)
|
||||||
|
const moduleMapPath = path.join(projectRoot, 'lib', 'module-map.json');
|
||||||
|
let moduleMap = {};
|
||||||
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
try {
|
||||||
|
moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`⚠️ 读取模块映射配置失败: ${error.message},将使用默认文件名\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件映射函数:根据配置返回加密后的文件名(跨平台兼容)
|
||||||
|
function getEncryptedFileName(originalPath) {
|
||||||
|
// 使用 path 模块处理路径,确保跨平台兼容
|
||||||
|
const normalizedPath = originalPath.replace(/\\/g, '/'); // 统一使用正斜杠
|
||||||
|
const parts = normalizedPath.split('/');
|
||||||
|
const fileName = parts[parts.length - 1].replace('.js', '');
|
||||||
|
const dirName = parts[parts.length - 2];
|
||||||
|
|
||||||
|
// 检查是否有映射配置
|
||||||
|
if (moduleMap.mappings) {
|
||||||
|
if (dirName === 'design1' && moduleMap.mappings.design1 && moduleMap.mappings.design1[fileName]) {
|
||||||
|
return moduleMap.mappings.design1[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'design2' && moduleMap.mappings.design2 && moduleMap.mappings.design2[fileName]) {
|
||||||
|
return moduleMap.mappings.design2[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'lib' && moduleMap.mappings.main && moduleMap.mappings.main[fileName]) {
|
||||||
|
return moduleMap.mappings.main[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认:原文件名 + 'c'
|
||||||
|
return fileName + '.jsc';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要删除的源文件列表(对应的 .jsc 文件会被保留)
|
||||||
|
const filesToDelete = [
|
||||||
|
'lib/index.js',
|
||||||
|
'lib/design1.js',
|
||||||
|
'lib/design2.js',
|
||||||
|
'lib/design1/core.js',
|
||||||
|
'lib/design1/output.js',
|
||||||
|
'lib/design1/ui.js',
|
||||||
|
'lib/design2/core.js',
|
||||||
|
'lib/design2/output.js',
|
||||||
|
'lib/design2/ui.js',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 备份目录
|
||||||
|
const backupDir = path.join(projectRoot, '.backup');
|
||||||
|
|
||||||
|
console.log('开始清理源文件...\n');
|
||||||
|
console.log('⚠️ 警告:此操作将删除源 JS 文件,只保留 .jsc 文件!\n');
|
||||||
|
|
||||||
|
// 创建备份目录
|
||||||
|
if (!fs.existsSync(backupDir)) {
|
||||||
|
fs.mkdirSync(backupDir, { recursive: true });
|
||||||
|
console.log(`✅ 已创建备份目录: ${backupDir}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let deletedCount = 0;
|
||||||
|
let notFoundCount = 0;
|
||||||
|
let errorCount = 0;
|
||||||
|
let backedUpCount = 0;
|
||||||
|
|
||||||
|
filesToDelete.forEach(filePath => {
|
||||||
|
try {
|
||||||
|
const fullPath = path.join(projectRoot, filePath);
|
||||||
|
const dir = path.dirname(fullPath);
|
||||||
|
|
||||||
|
// 检查默认名称的 .jsc 文件
|
||||||
|
const defaultJscPath = fullPath + 'c';
|
||||||
|
// 检查映射后的 .jsc 文件
|
||||||
|
const encryptedFileName = getEncryptedFileName(filePath);
|
||||||
|
const mappedJscPath = path.join(dir, encryptedFileName);
|
||||||
|
|
||||||
|
// 检查是否存在 .jsc 文件(默认或映射后的)
|
||||||
|
const jscExists = fs.existsSync(defaultJscPath) || fs.existsSync(mappedJscPath);
|
||||||
|
|
||||||
|
if (!jscExists) {
|
||||||
|
console.warn(`⚠️ 跳过: ${filePath} (对应的 .jsc 文件不存在)`);
|
||||||
|
notFoundCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 备份源文件
|
||||||
|
if (fs.existsSync(fullPath)) {
|
||||||
|
const backupPath = path.join(backupDir, filePath);
|
||||||
|
const backupDirPath = path.dirname(backupPath);
|
||||||
|
|
||||||
|
// 确保备份目录存在
|
||||||
|
if (!fs.existsSync(backupDirPath)) {
|
||||||
|
fs.mkdirSync(backupDirPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件到备份目录
|
||||||
|
fs.copyFileSync(fullPath, backupPath);
|
||||||
|
console.log(`📦 已备份: ${filePath} -> .backup/${filePath}`);
|
||||||
|
backedUpCount++;
|
||||||
|
|
||||||
|
// 删除源文件
|
||||||
|
fs.unlinkSync(fullPath);
|
||||||
|
console.log(`✅ 已删除: ${filePath}`);
|
||||||
|
deletedCount++;
|
||||||
|
} else {
|
||||||
|
console.log(`ℹ️ 不存在: ${filePath} (可能已删除)`);
|
||||||
|
notFoundCount++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ 处理失败: ${filePath}`);
|
||||||
|
console.error(` 错误: ${error.message}`);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建备份信息文件
|
||||||
|
const backupInfo = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
files: filesToDelete.filter((filePath, index) => {
|
||||||
|
const fullPath = path.join(projectRoot, filePath);
|
||||||
|
return fs.existsSync(path.join(backupDir, filePath));
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const backupInfoPath = path.join(backupDir, 'backup-info.json');
|
||||||
|
fs.writeFileSync(backupInfoPath, JSON.stringify(backupInfo, null, 2));
|
||||||
|
console.log(`\n📝 已创建备份信息文件: .backup/backup-info.json`);
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(50));
|
||||||
|
console.log(`清理完成!`);
|
||||||
|
console.log(` 已备份: ${backedUpCount}`);
|
||||||
|
console.log(` 已删除: ${deletedCount}`);
|
||||||
|
console.log(` 未找到: ${notFoundCount}`);
|
||||||
|
console.log(` 错误: ${errorCount}`);
|
||||||
|
console.log(` 备份位置: ${backupDir}`);
|
||||||
|
console.log('='.repeat(50));
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
console.log('\n⚠️ 有文件处理失败,请检查错误信息');
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
console.log('\n✅ 清理完成!源文件已备份到 .backup 目录');
|
||||||
|
console.log('\n💡 恢复方法:');
|
||||||
|
console.log(' 运行: node scripts/encrypt/restore.js');
|
||||||
|
console.log(' 或手动从 .backup 目录复制文件回原位置');
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
set ELECTRON_RUN_AS_NODE=true
|
||||||
|
set NODE_OPTIONS=--max-old-space-size=4096
|
||||||
|
cd /d "%~dp0\..\.."
|
||||||
|
electron scripts\encrypt\encrypt-electron.js
|
||||||
|
pause
|
||||||
|
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
// 设置输出编码为 UTF-8(修复 Windows 中文乱码问题)
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
process.stdout.setDefaultEncoding('utf8');
|
||||||
|
process.stderr.setDefaultEncoding('utf8');
|
||||||
|
// 设置环境变量确保中文正确显示
|
||||||
|
if (!process.env.CHCP) {
|
||||||
|
process.env.CHCP = '65001';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保在 Electron 环境中运行
|
||||||
|
if (!process.versions.electron) {
|
||||||
|
console.error('❌ 错误:此脚本必须在 Electron 环境中运行!');
|
||||||
|
console.error('请使用以下方式运行:');
|
||||||
|
console.error(' Windows: encrypt-electron-win.bat');
|
||||||
|
console.error(' Linux/Mac: ./encrypt-electron.sh');
|
||||||
|
console.error(' 或: npm run encrypt:win / npm run encrypt:linux');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytenode = require('bytenode');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 获取项目根目录(脚本在 scripts/encrypt 目录下,需要向上两级)
|
||||||
|
const projectRoot = path.resolve(__dirname, '../..');
|
||||||
|
|
||||||
|
// 读取模块映射配置(从 lib 目录读取)
|
||||||
|
const moduleMapPath = path.join(projectRoot, 'lib', 'module-map.json');
|
||||||
|
let moduleMap = {};
|
||||||
|
if (fs.existsSync(moduleMapPath)) {
|
||||||
|
try {
|
||||||
|
moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8'));
|
||||||
|
console.log('✅ 已加载模块映射配置\n');
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`⚠️ 读取模块映射配置失败: ${error.message},使用默认文件名\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件映射函数:根据配置返回加密后的文件名(跨平台兼容)
|
||||||
|
function getEncryptedFileName(originalPath) {
|
||||||
|
// 使用 path 模块处理路径,确保跨平台兼容
|
||||||
|
const normalizedPath = originalPath.replace(/\\/g, '/'); // 统一使用正斜杠
|
||||||
|
const parts = normalizedPath.split('/');
|
||||||
|
const fileName = parts[parts.length - 1].replace('.js', '');
|
||||||
|
const dirName = parts[parts.length - 2];
|
||||||
|
|
||||||
|
// 检查是否有映射配置
|
||||||
|
if (moduleMap.mappings) {
|
||||||
|
if (dirName === 'design1' && moduleMap.mappings.design1 && moduleMap.mappings.design1[fileName]) {
|
||||||
|
return moduleMap.mappings.design1[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'design2' && moduleMap.mappings.design2 && moduleMap.mappings.design2[fileName]) {
|
||||||
|
return moduleMap.mappings.design2[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
if (dirName === 'lib' && moduleMap.mappings.main && moduleMap.mappings.main[fileName]) {
|
||||||
|
return moduleMap.mappings.main[fileName] + '.jsc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认:原文件名 + 'c'
|
||||||
|
return fileName + '.jsc';
|
||||||
|
}
|
||||||
|
|
||||||
|
const filesToEncrypt = [
|
||||||
|
'lib/index.js', 'lib/design1.js', 'lib/design2.js',
|
||||||
|
'lib/design1/core.js', 'lib/design1/output.js', 'lib/design1/ui.js',
|
||||||
|
'lib/design2/core.js', 'lib/design2/output.js', 'lib/design2/ui.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 先删除所有旧的 .jsc 文件(包括映射后的文件名)
|
||||||
|
console.log('正在删除旧的 .jsc 文件...');
|
||||||
|
let deletedCount = 0;
|
||||||
|
filesToEncrypt.forEach(filePath => {
|
||||||
|
// 删除默认名称的 .jsc 文件(跨平台兼容)
|
||||||
|
const fullPath = path.join(projectRoot, filePath);
|
||||||
|
const defaultJscPath = fullPath + 'c';
|
||||||
|
if (fs.existsSync(defaultJscPath)) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(defaultJscPath);
|
||||||
|
deletedCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`⚠️ 删除失败: ${defaultJscPath} - ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除映射后的 .jsc 文件(跨平台兼容)
|
||||||
|
const dir = path.dirname(fullPath);
|
||||||
|
const encryptedFileName = getEncryptedFileName(filePath);
|
||||||
|
const mappedJscPath = path.join(dir, encryptedFileName);
|
||||||
|
// 使用 path.resolve 进行规范化比较,确保跨平台兼容
|
||||||
|
const normalizedDefault = path.resolve(defaultJscPath);
|
||||||
|
const normalizedMapped = path.resolve(mappedJscPath);
|
||||||
|
if (fs.existsSync(mappedJscPath) && normalizedMapped !== normalizedDefault) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(mappedJscPath);
|
||||||
|
deletedCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`⚠️ 删除失败: ${mappedJscPath} - ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(`已删除 ${deletedCount} 个旧的 .jsc 文件\n`);
|
||||||
|
|
||||||
|
// 开始编译
|
||||||
|
let successCount = 0, failCount = 0;
|
||||||
|
|
||||||
|
filesToEncrypt.forEach(filePath => {
|
||||||
|
try {
|
||||||
|
const fullPath = path.join(projectRoot, filePath);
|
||||||
|
if (!fs.existsSync(fullPath)) {
|
||||||
|
console.error(`❌ 文件不存在: ${filePath}`);
|
||||||
|
failCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编译文件(bytenode 会生成默认的 .jsc 文件)
|
||||||
|
bytenode.compileFile({ filename: fullPath });
|
||||||
|
|
||||||
|
// 检查默认的 .jsc 文件是否生成
|
||||||
|
const defaultJscPath = fullPath + 'c';
|
||||||
|
if (!fs.existsSync(defaultJscPath)) {
|
||||||
|
console.error(`❌ 编译失败: ${filePath}`);
|
||||||
|
failCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了映射,重命名文件(跨平台兼容)
|
||||||
|
const dir = path.dirname(fullPath);
|
||||||
|
const encryptedFileName = getEncryptedFileName(filePath);
|
||||||
|
const mappedJscPath = path.join(dir, encryptedFileName);
|
||||||
|
|
||||||
|
// 使用 path.resolve 进行规范化比较,确保跨平台兼容
|
||||||
|
const normalizedDefault = path.resolve(defaultJscPath);
|
||||||
|
const normalizedMapped = path.resolve(mappedJscPath);
|
||||||
|
|
||||||
|
if (normalizedMapped !== normalizedDefault) {
|
||||||
|
// 重命名文件
|
||||||
|
fs.renameSync(defaultJscPath, mappedJscPath);
|
||||||
|
console.log(`✅ ${filePath} → ${encryptedFileName}`);
|
||||||
|
} else {
|
||||||
|
console.log(`✅ ${filePath} → ${path.basename(defaultJscPath)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
successCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ 编译失败: ${filePath} - ${error.message}`);
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n编译完成!成功: ${successCount}, 失败: ${failCount}`);
|
||||||
|
process.exit(failCount > 0 ? 1 : 0);
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 设置 UTF-8 编码环境变量,确保中文正确显示
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
|
export LC_ALL=en_US.UTF-8
|
||||||
|
export LC_CTYPE=en_US.UTF-8
|
||||||
|
export ELECTRON_RUN_AS_NODE=true
|
||||||
|
export NODE_OPTIONS=--max-old-space-size=4096
|
||||||
|
|
||||||
|
# 切换到项目根目录
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
# 运行加密脚本
|
||||||
|
electron scripts/encrypt/encrypt-electron.js
|
||||||
|
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* 恢复脚本 - 从备份目录恢复源 JS 文件
|
||||||
|
*
|
||||||
|
* 使用方法:
|
||||||
|
* node restore.js
|
||||||
|
*
|
||||||
|
* 此脚本会从 .backup 目录恢复所有备份的源文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 获取项目根目录(脚本在 scripts/encrypt 目录下,需要向上两级)
|
||||||
|
const projectRoot = path.resolve(__dirname, '../..');
|
||||||
|
|
||||||
|
// 备份目录
|
||||||
|
const backupDir = path.join(projectRoot, '.backup');
|
||||||
|
const backupInfoPath = path.join(backupDir, 'backup-info.json');
|
||||||
|
|
||||||
|
console.log('开始恢复源文件...\n');
|
||||||
|
|
||||||
|
// 检查备份目录是否存在
|
||||||
|
if (!fs.existsSync(backupDir)) {
|
||||||
|
console.error('❌ 错误:备份目录不存在!');
|
||||||
|
console.error(` 路径: ${backupDir}`);
|
||||||
|
console.error('\n💡 提示:如果没有备份,请从 Git 仓库恢复文件');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查备份信息文件
|
||||||
|
if (!fs.existsSync(backupInfoPath)) {
|
||||||
|
console.warn('⚠️ 警告:备份信息文件不存在,将尝试恢复所有 .js 文件\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
let restoredCount = 0;
|
||||||
|
let notFoundCount = 0;
|
||||||
|
let errorCount = 0;
|
||||||
|
|
||||||
|
// 读取备份信息
|
||||||
|
let filesToRestore = [];
|
||||||
|
if (fs.existsSync(backupInfoPath)) {
|
||||||
|
try {
|
||||||
|
const backupInfo = JSON.parse(fs.readFileSync(backupInfoPath, 'utf8'));
|
||||||
|
filesToRestore = backupInfo.files || [];
|
||||||
|
console.log(`📋 从备份信息读取到 ${filesToRestore.length} 个文件\n`);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`⚠️ 无法读取备份信息文件: ${error.message}\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有备份信息,扫描备份目录
|
||||||
|
if (filesToRestore.length === 0) {
|
||||||
|
console.log('📂 扫描备份目录...\n');
|
||||||
|
function scanDir(dir, baseDir = '') {
|
||||||
|
const files = [];
|
||||||
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = path.join(dir, entry.name);
|
||||||
|
const relativePath = path.join(baseDir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
files.push(...scanDir(fullPath, relativePath));
|
||||||
|
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
||||||
|
files.push(relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesToRestore = scanDir(backupDir);
|
||||||
|
console.log(`📋 扫描到 ${filesToRestore.length} 个备份文件\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filesToRestore.length === 0) {
|
||||||
|
console.error('❌ 错误:没有找到任何备份文件!');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复文件
|
||||||
|
filesToRestore.forEach(filePath => {
|
||||||
|
try {
|
||||||
|
const backupPath = path.join(backupDir, filePath);
|
||||||
|
const restorePath = path.join(projectRoot, filePath);
|
||||||
|
|
||||||
|
// 检查备份文件是否存在
|
||||||
|
if (!fs.existsSync(backupPath)) {
|
||||||
|
console.warn(`⚠️ 备份文件不存在: ${filePath}`);
|
||||||
|
notFoundCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保目标目录存在
|
||||||
|
const restoreDir = path.dirname(restorePath);
|
||||||
|
if (!fs.existsSync(restoreDir)) {
|
||||||
|
fs.mkdirSync(restoreDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件
|
||||||
|
fs.copyFileSync(backupPath, restorePath);
|
||||||
|
console.log(`✅ 已恢复: ${filePath}`);
|
||||||
|
restoredCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ 恢复失败: ${filePath}`);
|
||||||
|
console.error(` 错误: ${error.message}`);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(50));
|
||||||
|
console.log(`恢复完成!`);
|
||||||
|
console.log(` 已恢复: ${restoredCount}`);
|
||||||
|
console.log(` 未找到: ${notFoundCount}`);
|
||||||
|
console.log(` 错误: ${errorCount}`);
|
||||||
|
console.log('='.repeat(50));
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
console.log('\n⚠️ 有文件恢复失败,请检查错误信息');
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
console.log('\n✅ 恢复完成!源文件已从备份目录恢复');
|
||||||
|
console.log('\n💡 提示:');
|
||||||
|
console.log(' - 备份文件仍保留在 .backup 目录');
|
||||||
|
console.log(' - 如需删除备份,请手动删除 .backup 目录');
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user