diff --git a/.gitignore b/.gitignore index aff3308..61ee0a4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ npm-debug.log npm-debug.log.* thumbs.db !.gitkeep + +# 加密相关文件(不要提交到 Git) +*.jsc +.backup/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..50e299e --- /dev/null +++ b/README.md @@ -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 diff --git a/design1.html b/design1.html index ba28595..4a81ded 100644 --- a/design1.html +++ b/design1.html @@ -870,15 +870,46 @@ diff --git a/design2.html b/design2.html index 72cf2f3..ab1bd05 100644 --- a/design2.html +++ b/design2.html @@ -659,15 +659,46 @@ diff --git a/index.html b/index.html index 7cc451b..b844285 100644 --- a/index.html +++ b/index.html @@ -216,13 +216,46 @@ \ No newline at end of file diff --git a/lib/cpp_draw.jsc b/lib/cpp_draw.jsc deleted file mode 100644 index f3ee29c..0000000 Binary files a/lib/cpp_draw.jsc and /dev/null differ diff --git a/lib/design1.js b/lib/design1.js index 2b89641..b998d09 100644 --- a/lib/design1.js +++ b/lib/design1.js @@ -5,7 +5,7 @@ require('./common/fabric-ext.js'); // 过滤 Canvas2D willReadFrequently 警告(不影响功能,只是性能提示) if (typeof console !== 'undefined' && console.warn) { const originalWarn = console.warn; - console.warn = function(...args) { + console.warn = function (...args) { const message = args.join(' '); // 过滤掉 willReadFrequently 相关的警告 if (message.includes('willReadFrequently') || message.includes('getImageData')) { @@ -17,117 +17,219 @@ if (typeof console !== 'undefined' && console.warn) { // Electron相关导入 const remote = require('@electron/remote'); - var path = require('path'); +var path = require('path'); const exePath = remote.app.getPath('userData'); const { ipcRenderer } = require('electron'); const { dialog } = require('@electron/remote'); - var jrQrcode = require('jr-qrcode'); - var JsBarcode = require('jsbarcode'); +var jrQrcode = require('jr-qrcode'); +var JsBarcode = require('jsbarcode'); const { clipboard } = require('electron'); const dpi = 600; // 发送IPC消息 - ipcRenderer.send('get-sys-fonts'); - ipcRenderer.send('get-scale-rate'); +ipcRenderer.send('get-sys-fonts'); +ipcRenderer.send('get-scale-rate'); // 使用layui - layui.use(['layer', 'slider', 'form', 'colorpicker'], function () { - let myDate = new Date(); - let s_lan = ""; - ipcRenderer.send('get-sys-language'); - +layui.use(['layer', 'slider', 'form', 'colorpicker'], function () { + let myDate = new Date(); + let s_lan = ""; + // 确保 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 layer = layui.layer; 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; + // 历史记录文件路径(供 output.js 使用) 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) + // 注意:所有函数都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 // ========================================== - + // 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") { - var keyHex = CryptoJS.enc.Utf8.parse(key); - var encrypted = CryptoJS.DES.encrypt(str, keyHex, { - mode: CryptoJS.mode.ECB, - padding: CryptoJS.pad.Pkcs7 - }); - return encrypted.toString(); + return window.desEncrypt(str, key); } - + // 多语言切换 - function langua_ge(lan = 'zh') { - $("[language='m']").each(function (i) { - $(this).html($(this).attr(lan)); + window.langua_ge = function langua_ge(lan = 'zh') { + $("[language='m']").each(function (i) { + $(this).html($(this).attr(lan)); }); - $("[language='t']").each(function (i) { - $(this).attr("title", $(this).attr(lan)); + $("[language='t']").each(function (i) { + $(this).attr("title", $(this).attr(lan)); }); - } - - // 多语言字符串获取 - function language_str(str) { - let t = { - "whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" }, - "save": { zh: "保存", ozh: "保存", en: "Save" }, - "noSave": { zh: "不保存", ozh: "不保存", en: "No saving" }, - "cancel": { zh: "取消", ozh: "取消", en: "Cancel" }, - "saveSucc": { zh: "保存成功至", ozh: "保存成功至", en: "Save successfully to" }, - "saveFile": { zh: "保存文件", ozh: "保存文件", en: "Save file" }, - "display": { zh: "预览", ozh: "預覽", en: "Display" }, - "output": { zh: "导出", ozh: "導出", en: "Export" }, - "bg": { zh: "背景", ozh: "背景", en: "Background" }, - "selectPic": { zh: "请选择图片", ozh: "請選擇圖片", en: "Please select a picture" }, - "img": { zh: "圖片", ozh: "圖片", en: "Image" }, - "simg": { zh: "合成圖片", ozh: "合成圖片", en: "Synthesized Image" }, - "text": { zh: "文本", ozh: "文本", en: "Text" }, - "ctext": { zh: "圆形文本", ozh: "圆形文本", en: "Circle Text" }, - "stext": { zh: "合成文本", ozh: "合成文本", en: "Synthesized Text" }, - "rect": { zh: "矩形", ozh: "矩形", en: "Rectangle" }, - "circ": { zh: "圓形", ozh: "圓形", en: "Circle" }, - "line": { zh: "直線", ozh: "直線", en: "Line" }, - "qrc": { zh: "二維碼", ozh: "二維碼", en: "QR code" }, - "barc": { zh: "條形碼", ozh: "條形碼", en: "Barcode" }, - "counter": { zh: "計數器", ozh: "计数器", en: "Counter" }, - "about": { zh: "关于Soon Design", ozh: "關於Soon Design", en: "About Soon Design" }, - "vers": { zh: "版本", ozh: "版本", en: "Version" }, - "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." } - }; - return t[str] ? t[str][s_lan] : str; + }; + // 向后兼容 + function langua_ge(lan = 'zh') { + return window.langua_ge(lan); } - + + // 多语言字符串获取 + window.language_str = function language_str(str) { + let t = { + "whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" }, + "save": { zh: "保存", ozh: "保存", en: "Save" }, + "noSave": { zh: "不保存", ozh: "不保存", en: "No saving" }, + "cancel": { zh: "取消", ozh: "取消", en: "Cancel" }, + "saveSucc": { zh: "保存成功至", ozh: "保存成功至", en: "Save successfully to" }, + "saveFile": { zh: "保存文件", ozh: "保存文件", en: "Save file" }, + "display": { zh: "预览", ozh: "預覽", en: "Display" }, + "output": { zh: "导出", ozh: "導出", en: "Export" }, + "bg": { zh: "背景", ozh: "背景", en: "Background" }, + "selectPic": { zh: "请选择图片", ozh: "請選擇圖片", en: "Please select a picture" }, + "img": { zh: "圖片", ozh: "圖片", en: "Image" }, + "simg": { zh: "合成圖片", ozh: "合成圖片", en: "Synthesized Image" }, + "text": { zh: "文本", ozh: "文本", en: "Text" }, + "ctext": { zh: "圆形文本", ozh: "圆形文本", en: "Circle Text" }, + "stext": { zh: "合成文本", ozh: "合成文本", en: "Synthesized Text" }, + "rect": { zh: "矩形", ozh: "矩形", en: "Rectangle" }, + "circ": { zh: "圓形", ozh: "圓形", en: "Circle" }, + "line": { zh: "直線", ozh: "直線", en: "Line" }, + "qrc": { zh: "二維碼", ozh: "二維碼", en: "QR code" }, + "barc": { zh: "條形碼", ozh: "條形碼", en: "Barcode" }, + "counter": { zh: "計數器", ozh: "计数器", en: "Counter" }, + "about": { zh: "关于Soon Design", ozh: "關於Soon Design", en: "About Soon Design" }, + "vers": { zh: "版本", ozh: "版本", en: "Version" }, + "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." } + }; + // 从全局作用域获取 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参数 - function GetFile() { + window.GetFile = function GetFile() { const params = new URLSearchParams(window.location.search); return params; + }; + // 向后兼容 + function GetFile() { + return window.GetFile(); } - + // 日期格式化 - function getDate() { - let date = new Date(); - return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); - } - - // 获取对象的绝对坐标 - function getAbsoluteXY(_obj) { - let coord = _obj.get("lineCoords"); - return [_obj.get("left"), _obj.get("top")]; + window.getDate = function getDate() { + let date = new Date(); + return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); + }; + // 向后兼容 + function getDate() { + return window.getDate(); } - + + // 获取对象的绝对坐标 + window.getAbsoluteXY = function getAbsoluteXY(_obj) { + let coord = _obj.get("lineCoords"); + 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 dy = Math.abs(y2 - y1); var distance = Math.sqrt(dx * dx + dy * dy); 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 centerY = canvas.height / 2; var mouseX = pointer.x; @@ -141,130 +243,169 @@ const dpi = 600; } angleDeg += 90; 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) { - for (let item of objs1) { - if (item.name == name) { - return false; - } - } - for (let item of objs2) { - if (item.name == name) { - return false; - } - } - return true; - } - + return window.checkName(name, objs1, objs2); + } + // 返回不重复的字段名 + 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) { - let num = (objs1.length + objs2.length) - 1; - do { - num++; - } - while (!checkName(pre_name + num, objs1, objs2)); - return pre_name + num; - } - + return window.resName(pre_name, objs1, objs2); + } + // 获取对象在画布中的索引 + 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) { - 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; - } - + return window.getIndex(target, canvas, _canvas); + } + // 获取对象类型 + 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) { - let temp_objs = canvas.getObjects(); - let i = 0; - for (let res of temp_objs) { - if (target == res) { - return objs[i].type; - } - i++; - } - } - + return window.getType(target, canvas, objs); + } + // 获取坐标的最小X值 - function getCoordsMinX(acoords) { + window.getCoordsMinX = function getCoordsMinX(acoords) { let x = acoords[0].x; - for (let item of acoords) { - if (item.x < x) { + for (let item of acoords) { + if (item.x < x) { x = item.x; - } - } - return x; - } - + } + } + return x; + }; + // 向后兼容 + function getCoordsMinX(acoords) { + return window.getCoordsMinX(acoords); + } + // 获取坐标的最大X值 - function getCoordsMaxX(acoords) { + window.getCoordsMaxX = function getCoordsMaxX(acoords) { let x = acoords[0].x; - for (let item of acoords) { - if (item.x > x) { + for (let item of acoords) { + if (item.x > x) { x = item.x; - } - } - return x; - } - + } + } + return x; + }; + // 向后兼容 + function getCoordsMaxX(acoords) { + return window.getCoordsMaxX(acoords); + } + // 获取坐标的最小Y值 - function getCoordsMinY(acoords) { + window.getCoordsMinY = function getCoordsMinY(acoords) { let y = acoords[0].y; - for (let item of acoords) { - if (item.y < y) { + for (let item of acoords) { + if (item.y < y) { y = item.y; - } - } - return y; - } - + } + } + return y; + }; + // 向后兼容 + function getCoordsMinY(acoords) { + return window.getCoordsMinY(acoords); + } + // 获取坐标的最大Y值 - function getCoordsMaxY(acoords) { + window.getCoordsMaxY = function getCoordsMaxY(acoords) { let y = acoords[0].y; - for (let item of acoords) { - if (item.y > y) { + for (let item of acoords) { + if (item.y > y) { y = item.y; - } - } - return y; - } + } + } + return y; + }; + // 向后兼容 + function getCoordsMaxY(acoords) { + return window.getCoordsMaxY(acoords); + } // ========================================== // 全局变量定义(所有模块共享) + // 注意:所有变量都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 // ========================================== - let addState = 0; // 0是不添加 - let background_image, background_image1, background_image2; - let bg_version = 1; // front_bg1.png front_bg2.png - var zoom = 1; - 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; // front_bg1.png front_bg2.png + window.zoom = 1; + window.pre_add_image = undefined; // 预添加的图片对象(用于addPic) + // 内部剪贴板 - let clipboardData = { + window.clipboardData = { data: null, offset: 10 // 粘贴位置偏移量 }; - + // 文件管理 - var openAs = { + window.openAs = { _name: "", set name(val) { if (val == "") { $("title").html('Soon Design'); - } else { + } else { $("title").html('Soon Design - ' + val); } this._name = val; @@ -273,48 +414,143 @@ const dpi = 600; return this._name }, }; - + // 对象数组和历史记录 - let objs1 = []; - let objs2 = []; - let step1 = { val: 0 }, step2 = { val: 0 }; - let step = step1; - let objs = objs1; - let recordJson1 = [], recordJson2 = [], recordJson = recordJson1, recordObjs1 = [], recordObjs2 = [], recordObjs = recordObjs1; - let pre_objs1 = [], pre_objs2 = [], next_objs1 = [], next_objs2 = [], pre_objs = pre_objs1, next_objs = next_objs1; - let pre_json1 = [], pre_json2 = [], next_json1 = [], next_json2 = [], pre_json = pre_json1, next_json = next_json1; - + window.objs1 = []; + window.objs2 = []; + window.step1 = { val: 0 }; + window.step2 = { val: 0 }; + window.step = window.step1; + window.objs = window.objs1; + window.recordJson1 = []; + 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中初始化) - var canvas1, canvas2; - var canvas; // 当前活动的画布(canvas1 或 canvas2) - var ctx1, ctx2; - let is_bgi_add = false; - + window.canvas1 = undefined; + window.canvas2 = undefined; + window.canvas = undefined; // 当前活动的画布(canvas1 或 canvas2) + 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模块 - // 由于模块代码需要在layui.use内部执行,我们通过动态加载的方式 const fs = require('fs'); - - // 加载core.js(核心功能) + let bytenode; + try { + bytenode = require('bytenode'); + require.extensions['.dl'] = require.extensions['.jsc']; + } catch (e) { + console.warn('[加载模块] bytenode 未安装,无法加载 .jsc 文件'); + } + + const appPath = (() => { try { return remote.app.getAppPath(); } catch (e) { return __dirname || process.cwd(); } })(); + + // 读取模块映射配置(从 lib 目录读取,跨平台兼容) + let moduleMap = {}; try { - const coreCode = fs.readFileSync(__dirname + '/design1/core.js', 'utf8'); - eval(coreCode); + const moduleMapPath = path.join(appPath, 'lib', 'module-map.json'); + if (fs.existsSync(moduleMapPath)) { + moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8')); + } } catch (e) { - console.error('加载core.js失败:', e); + console.warn('[加载模块] 无法读取模块映射配置,使用默认文件名'); } - // 加载output.js(输出功能,需要在ui.js之前加载,因为ui.js中的saveAs会调用output.js中的函数) - try { - const outputCode = fs.readFileSync(__dirname + '/design1/output.js', 'utf8'); - eval(outputCode); - } catch (e) { - console.error('加载output.js失败:', e); - } - - // 加载ui.js(UI控制) - try { - const uiCode = fs.readFileSync(__dirname + '/design1/ui.js', 'utf8'); - eval(uiCode); - } catch (e) { - console.error('加载ui.js失败:', e); + // 获取映射后的文件名(跨平台兼容) + function getMappedFileName(moduleName) { + if (moduleMap.mappings && moduleMap.mappings.design1 && moduleMap.mappings.design1[moduleName]) { + return moduleMap.mappings.design1[moduleName]; + } + 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'); }); diff --git a/lib/design1/core.js b/lib/design1/core.js index 7b5e0d6..04cbaea 100644 --- a/lib/design1/core.js +++ b/lib/design1/core.js @@ -33,11 +33,18 @@ try { // 初始化Canvas对象 canvas1 = new fabric.Canvas('canvas1'); canvas2 = new fabric.Canvas('canvas2'); +// 同步到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.canvas1 = canvas1; +window.canvas2 = canvas2; fabric.Object.prototype.objectCaching = false; ctx1 = canvas1.getSelectionContext(); ctx2 = canvas2.getSelectionContext(); is_bgi_add = false; +// 同步到 window 对象 +window.ctx1 = ctx1; +window.ctx2 = ctx2; +window.is_bgi_add = is_bgi_add; canvas1.zoomToPoint(new fabric.Point(0, 0), 1); canvas2.zoomToPoint(new fabric.Point(0, 0), 1); @@ -52,6 +59,7 @@ $(".canvas-container:eq(0)").css('width', 0) $(".canvas-container:eq(1)").hide(); canvas = canvas1; +window.canvas = canvas; fabric.Object.prototype.set({ borderColor: "#9013FE", cornerColor: "#9013FE", //激活状态角落图标的填充颜色 @@ -93,6 +101,13 @@ ipcRenderer.on('sys-lan', (event, data) => { let lang = localStorage.getItem("lang"); if (lang) { s_lan = lang; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge(lang); $("#language_select").val(lang); return; @@ -100,60 +115,130 @@ ipcRenderer.on('sys-lan', (event, data) => { switch (data) { case 'zh-CN': s_lan = "zh"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("zh"); $("#language_select").val("zh"); localStorage.setItem("lang", "zh"); break; case 'zh': s_lan = "zh"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("zh"); $("#language_select").val("zh"); localStorage.setItem("lang", "zh"); break; case 'zh-TW': s_lan = "ozh"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("ozh"); $("#language_select").val("ozh"); localStorage.setItem("lang", "ozh"); break; case 'en': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-AU': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-CA': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-GB': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-NZ': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-US': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); break; case 'en-ZA': s_lan = "en"; + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge("en"); $("#language_select").val("en"); localStorage.setItem("lang", "en"); @@ -168,14 +253,15 @@ ipcRenderer.on('close', (event, message) => { } }, function (index, layero) { - output(() => ipcRenderer.send('run-close')); + if (typeof window.output === 'function') { + window.output(() => ipcRenderer.send('run-close')); + } }, function (index) { ipcRenderer.send('run-close'); }); }) addBackground();//添加背景 白色卡片 - initAligningGuidelines(canvas1); initAligningGuidelines(canvas2); //canvas.setZoom(0.5) @@ -269,913 +355,6 @@ window.rotate = function (id) { $(`#${id}`).css("transform", `rotate(${angle}deg)`); $(`#${id}`).attr("angle", angle); } -$('#display').on('click', function () { - // 类型改变 - fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_1.png', function (i1) { - i1.left = background_image.left; - i1.top = background_image.top; - let img1 = i1; - - fabric.Image.fromURL('./public/images/back_bg_1.png', function (i2) { - i2.left = background_image.left; - i2.top = background_image.top; - let img2 = i2; - fabric.Image.fromURL('./public/images/op_1.png', function (i3) { - i2.left = background_image.left; - i2.top = background_image.top; - let img3 = i3; - display_func(img1, img2, img3); - }) - }) - }) -}); -// 导出文件 -async function saveImageAsPNG(buffer) { - let fs = require('fs'); - // 弹出保存对话框 - const { canceled, filePath } = await dialog.showSaveDialog({ - title: '保存图片', - defaultPath: path.join(exePath, 'output.png'), // 默认路径 - filters: [{ name: 'PNG Images', extensions: ['png'] }] // 文件过滤器 - }); - - if (canceled) { - console.log('用户取消了保存操作'); - return; - } - - // 将Buffer写入PNG文件到用户选择的路径 - fs.writeFile(filePath, buffer, (err) => { - if (err) { - console.error('写入文件失败:', err); - } else { - layer.msg(language_str("saveSucc") + filePath);//'保存成功至' - console.log('PNG文件已保存至:', filePath); - } - }); -} -function display_func(img1, img2, img3) { - $("#base_control").hide(); - $("#line_control").hide(); - $("#pic_control").hide(); - $("#out_pic_control").hide(); - $("#text_control").hide(); - $("#circle_text_control").hide(); - $("#out_text_control").hide(); - $("#rect_control").hide(); - $("#circle_control").hide(); - $("#counter_control").hide(); - $("#qrcode_Controll").hide(); - $("#barcode_controll").hide(); - $("#component_type").text(language_str("bg"));//"背景" - canvas1.discardActiveObject().renderAll(); - canvas2.discardActiveObject().renderAll(); - let _objs1 = canvas1.getObjects(); - let g1 = []; - let g3 = []; - let g5 = []; - let left = 0;//左裁剪 - let top = 0;//顶裁剪 - let black_left = 0;//黑色左裁剪 - let black_top = 0;//黑色顶裁剪 - let all_left = 0;//预览图左裁剪 - let all_top = 0;//预览图顶裁剪 - let list1 = [..._objs1] - for (let item of list1) { - let idx = getIndex(item, canvas1); - //console.log("------"); - //console.log(item.getCoords()); - //console.log(getCoordsMinX(background_image.getCoords())); - //console.log(getCoordsMinX(item.getCoords())); - //console.log(getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords())); - //console.log("------"); - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g3.push(fabric.util.object.clone(item)); - if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) { - continue;//计数器 或 合成文字 - } - if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) { - continue;//二维码 条形码 - } - if (idx != 0 && (objs1[idx - 1].type == 2)) { - continue;//合成图片 - } - if (idx != 0 && - ( - ( - objs1[idx - 1].type == 3 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //文字 && 黑色 - ) - || - ( - objs1[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) - || - ( - objs1[idx - 1].type == 5//矩形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs1[idx - 1].type == 6//圆形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs1[idx - 1].type == 7//直线 - && - (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff") - ) - || - objs1[idx - 1].black == true //勾选并入黑色图层 - // ( - // objs1[idx-1].type == 1//固定图片 - // && - // objs1[idx-1].black == true //勾选并入黑色图层 - // ) - ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g1.push(fabric.util.object.clone(item)); - continue;//黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g1.push(fabric.util.object.clone(item)); - } - - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g1.push(fabric.util.object.clone(item)); - } - let url1 = new fabric.Group(g1).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - - g3.push(img1); - let url3 = new fabric.Group(g3).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - let url5 = new fabric.Group(g5).toDataURL({ - height: 2787, - width: 2787, - top: black_top, - left: black_left - }); - let _objs2 = canvas2.getObjects(); - let g2 = []; - let g4 = []; - let g6 = []; - left = 0; - top = 0; - black_top = 0; - black_left = 0; - all_top = 0; - all_left = 0; - for (let item of _objs2) { - let idx = getIndex(item, canvas2); - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g4.push(fabric.util.object.clone(item)); - if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) { - continue;//黑色字或计数器 或 合成文字 - } - if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) { - continue;//二维码 条形码 - } - if (idx != 0 && (objs2[idx - 1].type == 2)) { - continue;//合成图片 - } - if (idx != 0 && (objs2[idx - 1].type == 10)) { - continue;//合成图片 - } - if (idx != 0 && - ( - ( - objs2[idx - 1].type == 3 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //文字 && 黑色 - ) - || - ( - objs2[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) - || - ( - objs2[idx - 1].type == 5//矩形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs2[idx - 1].type == 6//圆形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs2[idx - 1].type == 7//直线 - && - (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff") - ) - || - objs2[idx - 1].black == true //勾选并入黑色图层 - // ( - // objs2[idx-1].type == 1//固定图片 - // && - // objs2[idx-1].black == true //勾选并入黑色图层 - // ) - ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g2.push(fabric.util.object.clone(item)); - continue;//黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g2.push(fabric.util.object.clone(item)); - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g2.push(fabric.util.object.clone(item)); - - } - let url2 = new fabric.Group(g2).toDataURL({ - height: 2787, - width: 2787, - top: top, - left: left - }); - let white_url1 = canvas1.getObjects()[0].toDataURL({ - height: 2787, - width: 2787, - }); - g4.push(img2); - let url4 = new fabric.Group(g4).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - let url6 = new fabric.Group(g6).toDataURL({ - height: 2787, - width: 2787, - top: black_top, - left: black_left - }); - - let w = document.body.clientWidth * 0.7 + "px"; - let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + "px"; - let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + "px"; - - if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) { - //高度超出,则按高度计算 - h = document.body.clientHeight * 0.8 + "px"; - h1 = document.body.clientHeight * 0.8 - 150 + "px"; - w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94 - } - - let fs = require('fs'); - const Buffer = require('buffer').Buffer; - const buffer = Buffer.from(url3.replace(/^data:image\/\w+;base64,/, ""), 'base64'); - const printPath = path.join(exePath, 'print.png'); - fs.writeFileSync(printPath, buffer); - - layer.open({ - type: 1, - area: [w, h], - title: language_str("display"), //不显示标题栏"预览" - shadeClose: true, //点击遮罩关闭 - content: ` -
-
-
- -
- -
-
-
-
`, - btn: [language_str("output"), "打印"],//'导出' - btn1: function (index, layero) { - saveImageAsPNG(buffer) - - printJS({ printable: printPath, type: 'image', style: 'img { width: 100%; height: auto; }' }) - } - }); -} -function output(callback = null, _save = save) { - // 类型改变 - fabric.Image.fromURL('./public/images/op_1.png', function (i1) { - i1.left = background_image.left; - i1.top = background_image.top; - let img1 = i1; - fabric.Image.fromURL('./public/images/op_1.png', function (i2) { - i2.left = background_image.left; - i2.top = background_image.top; - let img2 = i2; - - $("#base_control").hide(); - $("#line_control").hide(); - $("#pic_control").hide(); - $("#out_pic_control").hide(); - $("#text_control").hide(); - $("#circle_text_control").hide(); - $("#out_text_control").hide(); - $("#rect_control").hide(); - $("#circle_control").hide(); - $("#counter_control").hide(); - $("#qrcode_Controll").hide(); - $("#barcode_controll").hide(); - $("#component_type").text(language_str("bg"));//"背景" - canvas1.discardActiveObject().renderAll(); - canvas2.discardActiveObject().renderAll(); - let _objs1 = canvas1.getObjects(); - let g1 = []; - let g3 = []; - let g5 = [];//黑色图层 - let left = 0;//左裁剪 - let top = 0;//顶裁剪 - let black_left = 0;//黑色左裁剪 - let black_top = 0;//黑色顶裁剪 - let all_left = 0;//预览图左裁剪 - let all_top = 0;//预览图顶裁剪 - for (let item of _objs1) { - let idx = getIndex(item, canvas1); - - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g3.push(fabric.util.object.clone(item)); - if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) { - continue;//计数器 或 合成文字 - } - if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) { - continue;//二维码 条形码 - } - if (idx != 0 && (objs1[idx - 1].type == 2)) { - continue;//合成图片 - } - if (idx != 0 && - ( - ( - objs1[idx - 1].type == 3 - && - item.get("fill") == "#000000" - //文字 && 黑色 - ) - || - ( - objs1[idx - 1].type == 11 - && - item.get("fill") == "#000000" - //圆形文字 && 黑色 - ) - || - ( - objs1[idx - 1].type == 5//矩形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs1[idx - 1].type == 6//圆形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs1[idx - 1].type == 7//直线 - && - (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff") - ) - || - objs1[idx - 1].black == true //勾选并入黑色图层 - - ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g1.push(fabric.util.object.clone(item)); - continue;//黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g1.push(fabric.util.object.clone(item)); - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g1.push(fabric.util.object.clone(item)); - } - let url1 = new fabric.Group(g1).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - g3.push(img1); - let url3 = new fabric.Group(g3).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - let url5 = new fabric.Group(g5).toDataURL({ - height: 2787, - width: 2787, - top: black_top, - left: black_left - }); - let _objs2 = canvas2.getObjects(); - let g2 = []; - let g4 = []; - let g6 = [];//黑色图层 - left = 0; - top = 0; - black_left = 0;//黑色左裁剪 - black_top = 0;//黑色顶裁剪 - all_left = 0;//黑色左裁剪 - all_top = 0;//黑色顶裁剪 - for (let item of _objs2) { - let idx = getIndex(item, canvas2); - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g4.push(fabric.util.object.clone(item)); - if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) { - continue;//计数器 或 合成文字 - } - if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) { - continue;//二维码 条形码 - } - if (idx != 0 && (objs2[idx - 1].type == 2)) { - continue;//合成图片 - } - if (idx != 0 && - ( - ( - objs2[idx - 1].type == 3 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //文字 && 黑色 - ) - || - ( - objs2[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) - || - ( - objs2[idx - 1].type == 5//矩形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs2[idx - 1].type == 6//圆形 - && - ( - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框 - || - (item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框 - || - ((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框 - ) - ) - || - ( - objs2[idx - 1].type == 7//直线 - && - (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff") - ) - || - objs2[idx - 1].black == true //勾选并入黑色图层 - // ( - // objs2[idx-1].type == 1//固定图片 - // && - // objs2[idx-1].black == true //勾选并入黑色图层 - // ) - ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g2.push(fabric.util.object.clone(item)); - continue;//黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g2.push(fabric.util.object.clone(item)); - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); - } - g2.push(fabric.util.object.clone(item)); - - } - let url2 = new fabric.Group(g2).toDataURL({ - height: 2787, - width: 2787, - top: top, - left: left - }); - let white_url1 = canvas1.getObjects()[0].toDataURL({ - height: 2787, - width: 2787, - }); - g4.push(img2); - let url4 = new fabric.Group(g4).toDataURL({ - height: 2787, - width: 2787, - top: all_top, - left: all_left - }); - let url6 = new fabric.Group(g6).toDataURL({ - height: 2787, - width: 2787, - top: black_top, - left: black_left - }); - // let white_url2 = canvas2.getObjects()[0].toDataURL({ - // height: 2787, - // width: 2787, - // }); - //console.log(canvas.getObjects()) - let w = document.body.clientWidth * 0.7 + "px"; - let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + "px"; - let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + "px"; - - if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) { - //高度超出,则按高度计算 - h = document.body.clientHeight * 0.8 + "px"; - h1 = document.body.clientHeight * 0.8 - 150 + "px"; - w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94 - } - - let op = { frontColorPic: "", backColorPic: "", frontBlackPic: "", backBlackPic: "", frontData: [], backData: [], flag: 1, frontDisplayPic: url3, backDisplayPic: '' }; - if (objs1.length != 0 & objs2.length == 0) { - op.flag = 2; - } else if (objs1.length == 0 & objs2.length != 0) { - op.flag = 3; - } - op.frontColorPic = desEncrypt(url1); - op.backColorPic = ''; - //op.frontBlPic = url5; - //op.backBlPic = url6; - op.frontBlackPic = ''; - op.backBlackPic = ''; - for (let item of _objs1) { - let idx = getIndex(item, canvas1); - if (idx == 0) continue;//background-image - let type = objs1[idx - 1].type; - if (type == 2) { - //out_pic - let xy = getAbsoluteXY(item); - op.frontData.push({ - "type": 1, - "name": objs1[idx - 1].name, - "FontColor": objs1[idx - 1].black ? "#000000" : "@", - "transparency": item.get("opacity"), - "x": parseInt((xy[0] - background_image1.left).toFixed(0)), - "y": parseInt((xy[1] - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 3) { - - } else if (type == 11) { - - op.frontData.push({ - "type": 2, - "Text": item.get("text"), - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": "#000000", - "FontBackgroudColor": item.get("textBackgroundColor"), - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((item.get("left") - background_image1.left).toFixed(0)), - "y": parseInt((item.get("top") - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - "circleCenter": objs1[idx - 1].circleCenter - }); - } else if (type == 4) { - //out_text - let xy = getAbsoluteXY(item); - op.frontData.push({ - "type": 3, - "name": objs1[idx - 1].name, - "FontFamily": item.get("fontFamily"), - "DefaultText": item.get("text"), - "FontBackgroudColor": item.get("textBackgroundColor"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": item.get("fill"), - "Exceed": objs1[idx - 1].exceed, - "AutoWrap": objs1[idx - 1].autoWrap, - "FixSize": objs1[idx - 1].fixSize, - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((xy[0] - background_image1.left).toFixed(0)), - "y": parseInt((xy[1] - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - align: objs1[idx - 1].align - }); - } else if (type == 8) { - //二维码 - let xy = getAbsoluteXY(item); - op.frontData.push({ - "type": 4, - "name": objs1[idx - 1].name, - "FontColor": objs1[idx - 1].color, - "DefaultText": objs1[idx - 1].val, - "x": parseInt((xy[0] - background_image1.left).toFixed(0)), - "y": parseInt((xy[1] - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 9) { - //条形码 - let xy = getAbsoluteXY(item); - op.frontData.push({ - "type": 5, - "name": objs1[idx - 1].name, - "FontSize": parseInt(objs1[idx - 1].fontSize), - "DefaultText": objs1[idx - 1].val, - "HideText": objs1[idx - 1].show, - "FontFamily": objs1[idx - 1].font, - "FontColor": objs1[idx - 1].color, - "x": parseInt((xy[0] - background_image1.left).toFixed(0)), - "y": parseInt((xy[1] - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 10) { - let xy = getAbsoluteXY(item); - op.frontData.push({ - "type": 6, - "name": objs1[idx - 1].name, - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": item.get("fill"), - "start": objs1[idx - 1].start, - "add": parseInt(objs1[idx - 1].add), - "x": parseInt((xy[0] - background_image1.left).toFixed(0)), - "y": parseInt((xy[1] - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } - } - //obj2 - for (let item of _objs2) { - let idx = getIndex(item, canvas2); - if (idx == 0) continue;//background-image - let type = objs2[idx - 1].type; - if (type == 2) { - //out_pic - let xy = getAbsoluteXY(item); - op.backData.push({ - "type": 1, - "name": objs2[idx - 1].name, - "FontColor": objs2[idx - 1].black ? "#000000" : "@", - "transparency": item.get("opacity"), - "x": parseInt((xy[0] - background_image2.left).toFixed(0)), - "y": parseInt((xy[1] - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 3) { - - } else if (type == 11) { - - op.frontData.push({ - "type": 2, - "Text": item.get("text"), - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": "#000000", - "FontBackgroudColor": item.get("textBackgroundColor"), - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((item.get("left") - background_image1.left).toFixed(0)), - "y": parseInt((item.get("top") - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - "circleCenter": objs2[idx - 1].circleCenter - }); - } else if (type == 4) { - let xy = getAbsoluteXY(item); - op.backData.push({ - "type": 3, - "name": objs2[idx - 1].name, - "FontFamily": item.get("fontFamily"), - "DefaultText": item.get("text"), - "FontSize": parseInt(item.get("fontSize")), - "FontBackgroudColor": item.get("textBackgroundColor"), - "FontColor": item.get("fill"), - "Exceed": objs2[idx - 1].exceed, - "AutoWrap": objs2[idx - 1].autoWrap, - "FixSize": objs2[idx - 1].fixSize, - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((xy[0] - background_image2.left).toFixed(0)), - "y": parseInt((xy[1] - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - align: objs2[idx - 1].align - }); - } else if (type == 8) { - //二维码 - let xy = getAbsoluteXY(item); - op.backData.push({ - "type": 4, - "name": objs2[idx - 1].name, - "FontColor": objs2[idx - 1].color, - "DefaultText": objs2[idx - 1].val, - "x": parseInt((xy[0] - background_image2.left).toFixed(0)), - "y": parseInt((xy[1] - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 9) { - let xy = getAbsoluteXY(item); - op.backData.push({ - "type": 5, - "name": objs2[idx - 1].name, - "DefaultText": objs2[idx - 1].val, - "HideText": objs1[idx - 1].show, - "FontSize": parseInt(objs2[idx - 1].fontSize), - "FontFamily": objs2[idx - 1].font, - "FontColor": objs2[idx - 1].color, - "x": parseInt((xy[0] - background_image2.left).toFixed(0)), - "y": parseInt((xy[1] - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } else if (type == 10) { - let xy = getAbsoluteXY(item); - op.backData.push({ - "type": 6, - "name": objs2[idx - 1].name, - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": item.get("fill"), - "start": parseInt(objs2[idx - 1].start), - "add": parseInt(objs2[idx - 1].add), - "x": parseInt((xy[0] - background_image2.left).toFixed(0)), - "y": parseInt((xy[1] - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)) - }); - } - } - _save(op, callback); - //return false 开启该代码可禁止点击该按钮关闭 - }) - }) -} -$('#output').on('click', function () { - output(null, saveAs); -}); function addBackground() { // 类型改变 @@ -1192,6 +371,8 @@ function addBackground() { image.scale(1, 1); background_image1 = image; background_image = background_image1; + window.background_image1 = background_image1; + window.background_image = background_image; canvas.add(image); canvas.renderAll(); //pre_objs1.push(JSON.stringify(objs1)); @@ -1211,6 +392,7 @@ function addBackground() { image.setSrc(image.toDataURL(), function (image) { background_image2 = image; + window.background_image2 = background_image2; canvas2.add(image); canvas2.renderAll(); //pre_objs2.push(JSON.stringify(objs2)); @@ -1220,9 +402,8 @@ function addBackground() { recordJson2.push(canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"])); let file = GetFile().get('file') - console.log(file) if (file && file != 'empty') { - open(file) + window.openFile(file) } }); }); @@ -1230,18 +411,27 @@ function addBackground() { }); } -function updateControls() { - if (!canvas.getActiveObject()) return; - $("#text_r").val(canvas.getActiveObject().get("angle").toFixed(0)); - $("#text_x").val((canvas.getActiveObject().get("left") - background_image.left).toFixed(0)); - $("#text_y").val((canvas.getActiveObject().get("top") - background_image.top).toFixed(0)); - $("#text_h").val((canvas.getActiveObject().get("scaleY") * canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("scaleX") * canvas.getActiveObject().get("width")).toFixed(0)); - if (canvas.getActiveObject().get("selectable")) { - $("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解锁 +// 将 updateControls 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.updateControls = function updateControls() { + // 使用 window.canvas 和 window.background_image 作为后备,确保在 eval() 执行时也能访问 + const currentCanvas = window.canvas || canvas; + const currentBackgroundImage = window.background_image || background_image; + if (!currentCanvas || !currentCanvas.getActiveObject()) return; + $("#text_r").val(currentCanvas.getActiveObject().get("angle").toFixed(0)); + $("#text_x").val((currentCanvas.getActiveObject().get("left") - currentBackgroundImage.left).toFixed(0)); + $("#text_y").val((currentCanvas.getActiveObject().get("top") - currentBackgroundImage.top).toFixed(0)); + $("#text_h").val((currentCanvas.getActiveObject().get("scaleY") * currentCanvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((currentCanvas.getActiveObject().get("scaleX") * currentCanvas.getActiveObject().get("width")).toFixed(0)); + // 根据锁定状态显示图标(使用lockMovementX判断,因为锁定时会设置所有lock属性) + if (currentCanvas.getActiveObject().get("lockMovementX")) { + $("#lock_img").attr("src", "public/images/lock20.png")//已锁定 } else { - $("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁 + $("#lock_img").attr("src", "public/images/unlock20.png")//未锁定 } +}; +// 向后兼容 +function updateControls() { + return window.updateControls(); } function selectObject(target, index) { updateControls(); @@ -1264,7 +454,7 @@ function addPic(pointer) { objs.push({ type: 1, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); //OpenDialog(); //function OpenDialog() //{ @@ -1285,7 +475,7 @@ function addPic(pointer) { // objs.push({type: 1}); // canvas.renderAll(); // updateList(); - // recordState(); + // window.recordState(); // } ); // }).catch(err => { // console.log(err) @@ -1337,7 +527,7 @@ function addOutPic(pointer) { objs.push({ type: 2, name: resName("OUT_PIC_"), black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); }); }); } @@ -1390,7 +580,7 @@ function addText(pointer) { objs.push({ type: 3, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectText(target, index) { @@ -1470,7 +660,7 @@ function addCircleText(pointer) { objs.push({ type: 11, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectCircleText(target, index) { @@ -1568,7 +758,7 @@ function addOutText(pointer) { objs.push({ type: 4, name: resName("OUT_TEXT_"), exceed: false, autoWrap: false, fixSize: false, black: false, align: 'center' }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectOutText(target, index) { @@ -1644,7 +834,7 @@ function addRect(pointer) { objs.push({ type: 5, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectRect(target, index) { @@ -1689,7 +879,7 @@ function addCircle(pointer) { objs.push({ type: 6, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectCircle(target, index) { @@ -1737,7 +927,7 @@ function addLine(pointer) { objs.push({ type: 7, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); } function selectLine(target, index) { @@ -1775,7 +965,7 @@ function addQrCode(pointer) { objs.push({ type: 8, name: resName("QR_CODE_"), color: "#000000", val: "https://www.cardsoon.com", black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); }); } @@ -1813,7 +1003,7 @@ function addBarCode(pointer) { objs.push({ type: 9, name: resName("BAR_CODE_"), val: "123456789", color: "#000000", fontSize: 18, font: "Arial", show: false, black: false });//show是取消文字显示 canvas.renderAll(); updateList(); - recordState(); + window.recordState(); }); } @@ -1854,7 +1044,7 @@ function addCounter(pointer) { objs.push({ type: 10, name: resName("COUNTER_"), start: 0, add: 1, black: false }); canvas.renderAll(); updateList(); - recordState(); + window.recordState(); console.log(canvas.getObjects()) } @@ -1888,7 +1078,8 @@ function selectCounter(target, index) { } -function updateList() { +// 将 updateList 附加到 window 对象,确保全局可访问 +window.updateList = function updateList() { let str = ""; let i = 0; @@ -1923,11 +1114,25 @@ function updateList() { (item.type === 3 ? "TEXT_" + displayIndex : (item.type === 1 ? "IMG_" + displayIndex : "OBJ_" + displayIndex)); + // 检查锁定状态(通过lockMovementX判断,因为锁定时会设置所有lock属性) + // 注意:索引0是背景图,objs数组是从下标0开始存第1个对象的,所以是 i+1 + let isLocked = false; + if (canvas.getObjects()[i + 1]) { + let canvasObj = canvas.getObjects()[i + 1]; + isLocked = canvasObj.get('lockMovementX') === true; + } + + // 锁定状态图标 + const lockIcon = isLocked ? + '' : + ''; + // 组装 HTML str = `
${nameText} + ${lockIcon}
${displayIndex}
` + str; @@ -1945,7 +1150,8 @@ function updateList() { }); } -function selectObj(objIndices, isFromCanvas = false) { +// 将 selectObj 附加到 window 对象,确保全局可访问 +window.selectObj = function selectObj(objIndices, isFromCanvas = false) { let indicesArray = (Array.isArray(objIndices)) ? objIndices : ((typeof objIndices === 'number' && objIndices >= 0) ? [objIndices] : []); // 清除所有高亮 @@ -1960,6 +1166,16 @@ function selectObj(objIndices, isFromCanvas = false) { if (indicesArray.includes(idIndex)) { $(this).css("background-color", "#6F7A84"); + // 如果对象被锁定,临时允许选中以便解锁 + if (idIndex >= 0 && canvas.getObjects()[idIndex + 1]) { + let obj = canvas.getObjects()[idIndex + 1]; + if (obj && obj.get('lockMovementX') === true) { + obj.set({ + selectable: true, + evented: true + }) + } + } // 自动滚动到可视区域 if (isFromCanvas && indicesArray[0] === idIndex) { @@ -1972,6 +1188,13 @@ function selectObj(objIndices, isFromCanvas = false) { if (!isFromCanvas && indicesArray.length === 1) { let target = canvas.getObjects()[indicesArray[0] + 1]; if (target) { + // 如果对象被锁定,临时允许选中以便解锁 + if (target.get('lockMovementX') === true) { + target.set({ + selectable: true, + evented: true + }) + } canvas.setActiveObject(target); canvas.requestRenderAll(); handleObjectSelected(); @@ -1979,7 +1202,7 @@ function selectObj(objIndices, isFromCanvas = false) { } } -function recordState() { +window.recordState = function recordState() { //pre_objs.push(JSON.stringify(objs)); //pre_json.push(canvas.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"])); //next_json = []; @@ -1999,13 +1222,16 @@ function recordState() { recordJson.push(j); } -function getIndex(target, _canvas = null) { +// 将 getIndex 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.getIndex = function getIndex(target, _canvas = null) { let temp_objs; - if (_canvas == null) { - temp_objs = canvas.getObjects(); - } else { - temp_objs = _canvas.getObjects(); + // 使用 window.canvas 作为默认值,确保在 eval() 执行时也能访问 + const currentCanvas = _canvas || window.canvas || canvas; + if (!currentCanvas) { + console.error('getIndex: canvas is undefined'); + return 0; } + temp_objs = currentCanvas.getObjects(); let i = 0; for (let res of temp_objs) { @@ -2015,6 +1241,10 @@ function getIndex(target, _canvas = null) { i++; } return 0; +}; +// 向后兼容 +function getIndex(target, _canvas = null) { + return window.getIndex(target, _canvas); } function getType(target) { @@ -2131,6 +1361,8 @@ function handleObjectSelected(e) { if (currentCanvas === canvas1 || currentCanvas === canvas2) { canvas = currentCanvas; objs = (currentCanvas === canvas1) ? objs1 : objs2; + window.canvas = canvas; + window.objs = objs; } let select_obj = canvas.getActiveObject(); @@ -2218,9 +1450,20 @@ function handleObjectMoving(e) { updateControls(); } -function initCanvasEvents() { - [canvas1, canvas2].forEach(currentCanvas => { +// 将 handleObjectSelected 附加到 window 对象,确保全局可访问 +window.handleObjectSelected = handleObjectSelected; +// 防止重复初始化事件监听器 +var _canvasEventsInitialized = false; + +function initCanvasEvents() { + // 如果已经初始化过,直接返回 + if (_canvasEventsInitialized) { + return; + } + _canvasEventsInitialized = true; + + [canvas1, canvas2].forEach(currentCanvas => { // 1. 鼠标移动 currentCanvas.on("mouse:move", (e) => { let offsetX = 0, offsetY = 0; @@ -2260,7 +1503,24 @@ function initCanvasEvents() { currentCanvas.on('object:selected', (e) => { canvas = currentCanvas; objs = (currentCanvas === canvas1) ? objs1 : objs2; + + // 阻止背景图(索引0)被选中(如果已锁定) + let selectedObj = e.target; + let idx = getIndex(selectedObj); + if (idx === 0) { + let bgObj = currentCanvas.getObjects()[0]; + if (bgObj && (bgObj.get('lockMovementX') === true || bgObj.get('selectable') === false)) { + currentCanvas.discardActiveObject(); + currentCanvas.renderAll(); + return; + } + } + handleObjectSelected(e); + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } }); // 4. 鼠标松开 (添加对象) @@ -2288,13 +1548,24 @@ function initCanvasEvents() { // 5. 对象移动 (只保留圆形文本逻辑,去掉了 checkOutOfBounds) currentCanvas.on("object:moving", (e) => { + // 阻止背景图(索引0)被移动(如果已锁定) + let movingObj = e.target; + let idx = getIndex(movingObj); + if (idx === 0) { + let bgObj = currentCanvas.getObjects()[0]; + if (bgObj && bgObj.get('lockMovementX') === true) { + e.e.preventDefault(); + e.e.stopPropagation(); + return false; + } + } handleObjectMoving(e); }); // 6. 变换事件 currentCanvas.on("object:rotating", updateControls); currentCanvas.on("object:scaling", updateControls); - currentCanvas.on("object:rotated", () => { recordState(); }); + currentCanvas.on("object:rotated", () => { window.recordState(); }); currentCanvas.on('text:editing:entered', () => { _textEdit = true; }); currentCanvas.on('text:editing:exited', () => { _textEdit = false; }); currentCanvas.on("text:changed", (e) => { $("#text_text").val(e.target.get("text")); }); @@ -2307,6 +1578,10 @@ function initCanvasEvents() { let objData = objs[idx - 1]; // 安全检查:确保 objData 存在且有 type 属性 if (!objData || typeof objData.type === 'undefined') { + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } console.warn('objData is undefined or missing type at index', idx - 1); return; } @@ -2326,7 +1601,11 @@ function initCanvasEvents() { target.scaleX = 1; target.scaleY = 1; updateControls(); } - recordState(); + window.recordState(); + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } }); // ================================================== // 8. 【完美修复版】渲染后绘制:外部蒙版 + 中心圆孔 (修复三角形Bug) @@ -2776,7 +2055,7 @@ function updateRulerGuides(nativeEvent) { $("#ruler-guide-v").css({ top: (nativeEvent.pageY - offset.top) + 'px', display: 'block' }); } -function copySelection() { +window.copySelection = function copySelection() { const activeObjects = canvas.getActiveObjects(); if (!activeObjects || activeObjects.length === 0) { @@ -2806,7 +2085,7 @@ function copySelection() { layer.msg("已复制"); } -function pasteFromClipboard() { +window.pasteFromClipboard = function pasteFromClipboard() { // 检查是否有数据 if (!clipboardData.data || clipboardData.data.length === 0) { // layer.msg("剪贴板为空"); @@ -2858,7 +2137,7 @@ function pasteFromClipboard() { // 4. 刷新列表和历史记录 updateList(); - recordState(); + window.recordState(); // 5. 高亮左侧列表最后一项 (即新粘贴的项) if (objs.length > 0) selectObj(objs.length - 1); @@ -2868,12 +2147,14 @@ function pasteFromClipboard() { }); } -function onStateRestored() { +// 将 onStateRestored 附加到 window 对象,确保全局可访问 +window.onStateRestored = function onStateRestored() { // 1. 重新获取背景图引用 (因为旧对象被销毁了) // 注意:canvas 是全局变量,指向当前激活的画板 if (canvas.getObjects().length > 0) { background_image = canvas.getObjects()[0]; background_image.selectable = false; // 确保背景不可选 + window.background_image = background_image; background_image.evented = false; } @@ -2881,11 +2162,15 @@ function onStateRestored() { canvas.requestRenderAll(); // 3. 取消选中状态 - selectObj(-1); + if (typeof window.selectObj === 'function') { + window.selectObj(-1); + } // 4. 隐藏所有属性面板 $("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide(); // 5. 刷新左侧列表 - updateList(); + if (typeof window.updateList === 'function') { + window.updateList(); + } } diff --git a/lib/design1/output.js b/lib/design1/output.js index 2e3e51d..751e54f 100644 --- a/lib/design1/output.js +++ b/lib/design1/output.js @@ -1,4 +1,47 @@ -function display_func(img1, img2, img3) { +// openAs 对象用于跟踪当前打开的文件路径 +var openAs = { + _name: "", + set name(val) { + if (val == "") { + $("title").html('Soon Design'); + } else { + $("title").html('Soon Design - ' + val); + } + this._name = val; + }, + get name() { + return this._name; + } +}; + +// 导出文件 +async function saveImageAsPNG(buffer) { + let fs = require('fs'); + // 弹出保存对话框 + const { canceled, filePath } = await dialog.showSaveDialog({ + title: '保存图片', + defaultPath: path.join(exePath, 'output.png'), // 默认路径 + filters: [{ name: 'PNG Images', extensions: ['png'] }] // 文件过滤器 + }); + + if (canceled) { + console.log('用户取消了保存操作'); + return; + } + + // 将Buffer写入PNG文件到用户选择的路径 + fs.writeFile(filePath, buffer, (err) => { + if (err) { + console.error('写入文件失败:', err); + } else { + layer.msg(language_str("saveSucc") + filePath);//'保存成功至' + console.log('PNG文件已保存至:', filePath); + } + }); +} + +// 将 display_func 附加到 window 对象,确保全局可访问 +window.display_func = function display_func(img1, img2, img3) { $("#base_control").hide(); $("#line_control").hide(); $("#pic_control").hide(); @@ -14,6 +57,27 @@ function display_func(img1, img2, img3) { $("#component_type").text(language_str("bg"));//"背景" canvas1.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 g1 = []; @@ -29,12 +93,12 @@ function display_func(img1, img2, img3) { let list1 = _objs1.filter(obj => !obj.isGuideLine); for (let item of list1) { let idx = getIndex(item, canvas1); - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { continue; } - + //console.log("------"); //console.log(item.getCoords()); //console.log(getCoordsMinX(background_image.getCoords())); @@ -143,11 +207,9 @@ function display_func(img1, img2, img3) { }); g3.push(img1); - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 - // 原始尺寸 2787x2787,缩小到 512x512,比例约为 0.184 let url3 = new fabric.Group(g3).toDataURL({ - format: 'png', - multiplier: 512 / 2787, // 约 0.184,缩小到 512x512,保持宽高比和所有内容 + height: 2787, + width: 2787, top: all_top, left: all_left }); @@ -169,14 +231,14 @@ function display_func(img1, img2, img3) { all_top = 0; all_left = 0; for (let item of _objs2) { - + let idx = getIndex(item, canvas2); - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { continue; } - + if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); } @@ -285,11 +347,9 @@ function display_func(img1, img2, img3) { width: 2787, }); g4.push(img2); - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 - // 原始尺寸 2787x2787,缩小到 512x512,比例约为 0.184 let url4 = new fabric.Group(g4).toDataURL({ - format: 'png', - multiplier: 512 / 2787, // 约 0.184,缩小到 512x512,保持宽高比和所有内容 + height: 2787, + width: 2787, top: all_top, left: all_left }); @@ -323,26 +383,51 @@ function display_func(img1, img2, img3) { title: language_str("display"), //不显示标题栏"预览" shadeClose: true, //点击遮罩关闭 content: ` -
-
-
- -
- -
-
-
-
`, +
+
+
+ +
+ +
+
+
+
`, btn: [language_str("output"), "打印"],//'导出' btn1: function (index, layero) { + // 只处理导出(保存PNG) saveImageAsPNG(buffer) - + }, + btn2: function () { + // 只处理打印 printJS({ printable: printPath, 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_1.png', function (i1) { i1.left = background_image.left; @@ -390,12 +475,12 @@ function output(callback = null, _save = save) { all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())); } g3.push(fabric.util.object.clone(item)); - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { continue; } - + if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) { continue;//计数器 或 合成文字 } @@ -485,11 +570,9 @@ function output(callback = null, _save = save) { left: all_left }); g3.push(img1); - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 - // 原始尺寸 2787x2787,缩小到 512x512,比例约为 0.184 let url3 = new fabric.Group(g3).toDataURL({ - format: 'png', - multiplier: 512 / 2787, // 约 0.184,缩小到 512x512,保持宽高比和所有内容 + height: 2787, + width: 2787, top: all_top, left: all_left }); @@ -513,12 +596,12 @@ function output(callback = null, _save = save) { let filteredObjs2 = _objs2.filter(obj => !obj.isGuideLine); for (let item of filteredObjs2) { let idx = getIndex(item, canvas2); - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { continue; } - + if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())); } @@ -624,11 +707,9 @@ function output(callback = null, _save = save) { width: 2787, }); g4.push(img2); - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 - // 原始尺寸 2787x2787,缩小到 512x512,比例约为 0.184 let url4 = new fabric.Group(g4).toDataURL({ - format: 'png', - multiplier: 512 / 2787, // 约 0.184,缩小到 512x512,保持宽高比和所有内容 + height: 2787, + width: 2787, top: all_top, left: all_left }); @@ -671,15 +752,15 @@ function output(callback = null, _save = save) { if (item.isGuideLine) { continue; } - + let idx = getIndex(item, canvas1); if (idx == 0) continue;//background-image - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined') { continue; } - + let type = objs1[idx - 1].type; if (type == 2) { //out_pic @@ -797,15 +878,15 @@ function output(callback = null, _save = save) { if (item.isGuideLine) { continue; } - + let idx = getIndex(item, canvas2); if (idx == 0) continue;//background-image - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined') { continue; } - + let type = objs2[idx - 1].type; if (type == 2) { //out_pic @@ -922,51 +1003,184 @@ 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; - + const objects = canvas.getObjects(); - + // 遍历对象(跳过背景图片,索引 0) for (let i = 1; i < objects.length; i++) { const obj = objects[i]; if (!obj || obj.type !== 'image') continue; - + const objIndex = i - 1; if (objIndex >= objsArray.length) continue; - + const objMeta = objsArray[objIndex]; if (!objMeta || (objMeta.type !== 8 && objMeta.type !== 9)) continue; - + // type == 8: 二维码 - 复用 ui.js 中的生成逻辑 if (objMeta.type === 8) { - const qr = jrQrcode.getQrBase64(objMeta.val || 'https://www.cardsoon.com', { - padding: 0, - foreground: objMeta.color || '#000000' + const qr = jrQrcode.getQrBase64(objMeta.val || 'https://www.cardsoon.com', { + padding: 0, + foreground: objMeta.color || '#000000' }); - obj.setSrc(qr, function(img) { + obj.setSrc(qr, function (img) { canvas.renderAll(); }); } // type == 9: 条形码 - 复用 ui.js 中的生成逻辑 else if (objMeta.type === 9) { - JsBarcode("#barcode", objMeta.val || '123456789', { - margin: 0, - lineColor: objMeta.color || '#000000', - fontSize: objMeta.fontSize || 18, - font: objMeta.font || 'Arial' + JsBarcode("#barcode", objMeta.val || '123456789', { + margin: 0, + lineColor: objMeta.color || '#000000', + fontSize: objMeta.fontSize || 18, + font: objMeta.font || 'Arial' }); const barcode = document.getElementById('barcode'); const bar = barcode.toDataURL("image/png"); - obj.setSrc(bar, function(img) { + obj.setSrc(bar, function (img) { canvas.renderAll(); }); } } } +// open() 函数在 output.js 中定义,因为 output.js 先于 core.js 加载 +// 使用 window.openFile 避免与浏览器原生的 window.open 冲突 +window.openFile = function open(file) { + try { + let fs = require('fs'); + if (!fs.existsSync(file)) { + return; + } + var fsData = fs.readFileSync(file); + openAs.name = file; + let j; + try { + j = JSON.parse(fsData.toString()); + } catch (e) { + return; + } + + if (!background_image) { + return; + } + if (!j.f || !j.f.objects || !Array.isArray(j.f.objects) || j.f.objects.length === 0) { + return; + } + if (!j.b || !j.b.objects || !Array.isArray(j.b.objects) || j.b.objects.length === 0) { + j.b = { + version: '4.6.0', + objects: [], + hoverCursor: 'move' + }; + } + + let left = background_image.left; + let top = background_image.top; + let new_left = j.f.objects[0].left; + let new_top = j.f.objects[0].top; + for (let o of j.f.objects) { + o.left = o.left - new_left + left; + o.top = o.top - new_top + top; + } + if (j.f.objects[0] && !j.f.objects[0].src) { + j.f.objects[0].src = './public/images/bg_front_1.png' + } + if (j.b.objects && j.b.objects.length > 0 && j.b.objects[0] && !j.b.objects[0].src) { + j.b.objects[0].src = './public/images/bg_back.png' + } + + const fo = j.fo || []; + const bo = j.bo || []; + const placeholder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; + + fo.forEach((objMeta, idx) => { + if ((objMeta.type === 8 || objMeta.type === 9) && j.f.objects[idx + 1] && !j.f.objects[idx + 1].src) { + j.f.objects[idx + 1].src = placeholder; + } + }); + + bo.forEach((objMeta, idx) => { + if ((objMeta.type === 8 || objMeta.type === 9) && j.b.objects && j.b.objects[idx + 1] && !j.b.objects[idx + 1].src) { + j.b.objects[idx + 1].src = placeholder; + } + }); + + canvas1.loadFromJSON(j.f, function () { + if (typeof window.regenerateQrCodesAndBarcodes === 'function') { + window.regenerateQrCodesAndBarcodes(canvas1, fo); + } + canvas1.renderAll(); + }); + canvas2.loadFromJSON(j.b, function () { + if (typeof window.regenerateQrCodesAndBarcodes === 'function') { + window.regenerateQrCodesAndBarcodes(canvas2, bo); + } + canvas2.renderAll(); + }); + + let objects1 = canvas1.getObjects(); + let objects2 = canvas2.getObjects(); + if (!objects1 || objects1.length === 0) { + return; + } + background_image1 = objects1[0]; + background_image2 = objects2 && objects2.length > 0 ? objects2[0] : null; + + objs2 = j.bo || []; + objs1 = j.fo || []; + step1.val = 0; + step2.val = 0; + recordJson1 = []; + recordJson2 = []; + recordObjs1 = []; + recordObjs2 = []; + if ($("#front_side").hasClass("ui-button-active")) { + objs = objs1; + recordObjs = recordObjs1; + recordJson = recordJson1; + step = step1; + background_image = background_image1; + } else if ($("#back_side").hasClass("ui-button-active")) { + objs = objs2; + recordObjs = recordObjs2; + recordJson = recordJson2; + background_image = background_image2 || background_image1; + step = step2; + } + canvas1.renderAll(); + canvas2.renderAll(); + // 调用 updateList,现在它已附加到 window 对象 + if (typeof window.updateList === 'function') { + window.updateList(); + } else { + setTimeout(() => { + if (typeof window.updateList === 'function') { + window.updateList(); + } + }, 100); + } + setTimeout(() => { + recordObjs1.push(JSON.stringify(objs1)) + let j1 = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + j1.objects[0].hoverCursor = "default"; + recordJson1.push(j1); + + recordObjs2.push(JSON.stringify(objs2)) + let j2 = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + recordJson2.push(j2); + }, 0); + } catch (e) { + // 静默处理错误 + } +} + // 清理不需要的 src 字段(保留自定义图片的 src) -function cleanupSrcFields(jsonObjects, objsArray) { +// 将 cleanupSrcFields 附加到 window 对象,确保在 ui.js 中的 saveAs 函数也能访问 +window.cleanupSrcFields = function cleanupSrcFields(jsonObjects, objsArray) { if (!jsonObjects || !Array.isArray(jsonObjects)) return; if (!objsArray || !Array.isArray(objsArray)) return; @@ -992,6 +1206,10 @@ function cleanupSrcFields(jsonObjects, objsArray) { } } } +}; +// 向后兼容 +function cleanupSrcFields(jsonObjects, objsArray) { + return window.cleanupSrcFields(jsonObjects, objsArray); } function saveAs(op1, callback) { @@ -1010,7 +1228,7 @@ function saveAs(op1, callback) { canvas2.remove(obj); } }); - + let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); @@ -1030,15 +1248,22 @@ function saveAs(op1, callback) { title: language_str("saveFile"),//'保存文件' filters: [ { name: 'Soon File Type', extensions: ['soon'] }, - ] + ], + defaultPath: openAs.name || undefined }).then(result => { if (result.filePath == "") { return; } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon'; + if (result.filePath == null || result.filePath == undefined) { 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') con_o.soonType = 1 - fs.writeFileSync(result.filePath, JSON.stringify(con_o)) + fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8') openAs.name = result.filePath; layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); @@ -1066,7 +1291,7 @@ function save(op1, callback) { canvas2.remove(obj); } }); - + let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); @@ -1086,7 +1311,7 @@ function save(op1, callback) { //打开的文件 let fs = require('fs') con_o.soonType = 1 - fs.writeFileSync(openAs.name, JSON.stringify(con_o)) + fs.writeFileSync(openAs.name, JSON.stringify(con_o), 'utf8') layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); if (callback && typeof callback === 'function') { @@ -1098,15 +1323,22 @@ function save(op1, callback) { title: language_str("saveFile"),//'保存文件' filters: [ { name: 'Soon File Type', extensions: ['soon'] }, - ] + ], + defaultPath: openAs.name || undefined }).then(result => { if (result.filePath == "") { return; } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon'; + if (result.filePath == null || result.filePath == undefined) { 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') con_o.soonType = 1 - fs.writeFileSync(result.filePath, JSON.stringify(con_o)) + fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8') openAs.name = result.filePath; layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); @@ -1118,7 +1350,8 @@ function save(op1, callback) { }) } -function saveHistory() { +// 将 saveHistory 附加到 window 对象,确保在 ui.js 中也能访问 +window.saveHistory = function saveHistory() { let fs = require('fs'); let j = { history: [] }; // 默认结构必须是数组 @@ -1163,136 +1396,17 @@ function saveHistory() { // 5. 统一写入 try { - fs.writeFileSync(fullPath, JSON.stringify(j)); + fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8'); } catch (e) { console.error("写入历史记录失败:", e); } +}; +// 向后兼容 +function saveHistory() { + return window.saveHistory(); } -function open(file) { - console.log(file) - let fs = require('fs') - var fsData = fs.readFileSync(file) - openAs.name = file; - let j = JSON.parse(fsData.toString()); - // 安全检查:确保 background_image 已初始化 - if (!background_image) { - console.error('background_image 未初始化,无法打开文件'); - return; - } - // 安全检查:确保 JSON 中有 objects 数组 - if (!j.f || !j.f.objects || !Array.isArray(j.f.objects) || j.f.objects.length === 0) { - console.error('JSON 格式错误:缺少 f.objects'); - return; - } - // design1 的背面数据是可选的(type 1 可能只有正面) - // 如果没有 b 或 b.objects,创建一个空的 canvas - if (!j.b || !j.b.objects || !Array.isArray(j.b.objects) || j.b.objects.length === 0) { - // 创建空的背面数据 - j.b = { - version: '4.6.0', - objects: [], - hoverCursor: 'move' - }; - } - let left = background_image.left; - let top = background_image.top; - let new_left = j.f.objects[0].left; - let new_top = j.f.objects[0].top; - for (let o of j.f.objects) { - o.left = o.left - new_left + left; - o.top = o.top - new_top + top; - } - // for (let o of j.b.objects) { - // o.left = o.left - new_left + left; - // o.top = o.top - new_top + top; - // } - // 如果背景图片没有src,从路径恢复(因为保存时删除了src以减小文件大小) - if (j.f.objects[0] && !j.f.objects[0].src) { - j.f.objects[0].src = './public/images/bg_front_1.png' - } - if (j.b.objects && j.b.objects.length > 0 && j.b.objects[0] && !j.b.objects[0].src) { - j.b.objects[0].src = './public/images/bg_back.png' - } - - // 为二维码和条形码对象创建临时的 src(Fabric.js 需要 src 来创建 Image 对象) - // 加载完成后会重新生成,所以这里只需要一个占位符 - const fo = j.fo || []; - const bo = j.bo || []; - const placeholder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; - - // 为正面二维码和条形码创建临时 src - fo.forEach((objMeta, idx) => { - if ((objMeta.type === 8 || objMeta.type === 9) && j.f.objects[idx + 1] && !j.f.objects[idx + 1].src) { - j.f.objects[idx + 1].src = placeholder; - } - }); - - // 为背面二维码和条形码创建临时 src - bo.forEach((objMeta, idx) => { - if ((objMeta.type === 8 || objMeta.type === 9) && j.b.objects && j.b.objects[idx + 1] && !j.b.objects[idx + 1].src) { - j.b.objects[idx + 1].src = placeholder; - } - }); - - console.log(j.f) - - // 加载 JSON,并在回调中重新生成二维码和条形码 - canvas1.loadFromJSON(j.f, function() { - regenerateQrCodesAndBarcodes(canvas1, fo); - canvas1.renderAll(); - }); - canvas2.loadFromJSON(j.b, function() { - regenerateQrCodesAndBarcodes(canvas2, bo); - canvas2.renderAll(); - }); - // 安全检查:确保加载后 canvas 中有对象 - let objects1 = canvas1.getObjects(); - let objects2 = canvas2.getObjects(); - if (!objects1 || objects1.length === 0) { - console.error('canvas1 加载失败:没有对象'); - return; - } - background_image1 = objects1[0]; - // canvas2 可能为空(type 1 文件) - background_image2 = objects2 && objects2.length > 0 ? objects2[0] : null; - - objs2 = j.bo || []; - objs1 = j.fo || []; - step1.val = 0; - step2.val = 0; - recordJson1 = []; - recordJson2 = []; - recordObjs1 = []; - recordObjs2 = []; - if ($("#front_side").hasClass("ui-button-active")) { - objs = objs1; - recordObjs = recordObjs1; - recordJson = recordJson1; - step = step1; - background_image = background_image1; - } else if ($("#back_side").hasClass("ui-button-active")) { - objs = objs2; - recordObjs = recordObjs2; - recordJson = recordJson2; - background_image = background_image2 || background_image1; // 如果背面为空,使用正面 - step = step2; - } - canvas1.renderAll(); - canvas2.renderAll(); - updateList(); //修复打开新文件后无法撤销的bug - setTimeout(() => { - recordObjs1.push(JSON.stringify(objs1)) - let j1 = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); - j1.objects[0].hoverCursor = "default"; - recordJson1.push(j1); - - recordObjs2.push(JSON.stringify(objs2)) - let j2 = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); - // j2.objects[0].hoverCursor = "default"; - recordJson2.push(j2); - }, 0); -} +// open() 函数已移至 core.js,因为它在 core.js 的 addBackground() 中被调用 function clearAll() { //let blank = "{\"f\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"#000000\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"b\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"rgb(0,0,0)\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"fo\":[],\"bo\":[]}"; @@ -1331,7 +1445,12 @@ function clearAll() { openAs.name = ""; canvas1.renderAll(); canvas2.renderAll(); - updateList(); + if (typeof window.updateList === 'function') { + window.updateList(); + } console.log(); } +// 将 clearAll 附加到 window 对象,确保全局可访问 +window.clearAll = clearAll; + diff --git a/lib/design1/ui.js b/lib/design1/ui.js index f7a8492..a795d54 100644 --- a/lib/design1/ui.js +++ b/lib/design1/ui.js @@ -1,2092 +1,2338 @@ -var _keyctrl = false, _keyc = false, _textEdit = false, _inputEdit = false; -$("input").focus(function () { - console.log(1) - _inputEdit = true -}) -$("input").blur(function () { - _inputEdit = false -}) -$("textarea").focus(function () { - console.log(1) - _inputEdit = true -}) -$("textarea").blur(function () { - _inputEdit = false -}) -$("body").keyup(function (event) { - // 兼容三端�?modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta�? - if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释�? - _keyctrl = false; - }; - if (event.keyCode == 67) { - _keyc = false; - }; -}) -$("body").keydown(function (event) { - // 统一的快捷键处理(兼�?Windows/Linux: Ctrl, Mac: Cmd/Meta�? - const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端 - - // 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的�? - if (!_inputEdit && !_textEdit) { - // CTRL/CMD+N - 新建 - if (isModifierKey && event.keyCode == 78) { - event.preventDefault(); - $("#new").click(); - return; - } - // CTRL/CMD+O - 打开 - if (isModifierKey && event.keyCode == 79) { - event.preventDefault(); - $("#open").click(); - return; - } - // CTRL/CMD+S - 保存 - if (isModifierKey && !event.shiftKey && event.keyCode == 83) { - event.preventDefault(); - $("#save").click(); - return; - } - // CTRL/CMD+SHIFT+S - 保存副本 - if (isModifierKey && event.shiftKey && event.keyCode == 83) { - event.preventDefault(); - output(null, saveAs); - return; - } - // CTRL/CMD+Z - 还原 - if (isModifierKey && !event.shiftKey && event.keyCode == 90) { - event.preventDefault(); - $("#previous").click(); - return; - } - // CTRL/CMD+Y - 重做 - if (isModifierKey && !event.shiftKey && event.keyCode == 89) { - event.preventDefault(); - $("#next").click(); - return; - } - // CTRL/CMD+C - 复制 - if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { - event.preventDefault(); - copySelection(); - return; - } - // CTRL/CMD+V - 粘贴 - if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { - event.preventDefault(); - pasteFromClipboard(); - return; - } - - // CTRL/CMD + SHIFT + DEL (Windows) �?CMD + SHIFT + Backspace (Mac) - 清空 - if (isModifierKey && event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) { - event.preventDefault(); - $("#clean").click(); - return; - } - - // CTRL/CMD + DEL (Windows) �?CMD + Backspace (Mac) - 删除 - if (isModifierKey && !event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) { - event.preventDefault(); - $("#delete").click(); - return; - } - - } - // 兼容三端�?modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta�? - if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd�? - _keyctrl = true; - if (_keyc && _textEdit) { - //同时按下且在编辑状�? - setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) - //clipboard.writeText((clipboard.readText()+' ')) - } - } - if (event.keyCode == 67) { - _keyc = true; - if (_keyctrl & _textEdit) { - //同时按下且在编辑状�? - setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) - //clipboard.writeText((clipboard.readText()+' ')) - } - } - if (event.keyCode == 37) { - //left - let v = -1; - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = -5; - } - let x = canvas.getActiveObject().get("left"); - x += v; - canvas.getActiveObject().set("left", x); - canvas.renderAll(); - recordState(); - updateControls(); - } - if (event.keyCode == 38) { - //up - let v = -1; - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = -5; - } - let y = canvas.getActiveObject().get("top"); - y += v; - canvas.getActiveObject().set("top", y); - canvas.renderAll(); - recordState(); - updateControls(); - } - if (event.keyCode == 39) { - //right - let v = 1; - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = 5; - } - let x = canvas.getActiveObject().get("left"); - x += v; - canvas.getActiveObject().set("left", x); - canvas.renderAll(); - recordState(); - updateControls(); - } - if (event.keyCode == 40) { - //down - let v = +1; - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = 5; - } - let y = canvas.getActiveObject().get("top"); - y += v; - canvas.getActiveObject().set("top", y); - canvas.renderAll(); - recordState(); - updateControls(); - } - // 普通删除键(DEL键,没有按CTRL/CMD�? - if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) { - let actObjs = canvas.getActiveObjects(); - let allObjs = canvas.getObjects(); - let flag = 0; - for (let item of actObjs) { - if (item != allObjs[0]) { - let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 - objs.splice(i - 1, 1); - canvas.remove(item); - flag = 1; - - } - } - updateList(); - canvas.discardActiveObject(); - if (flag == 1) { - recordState(); - canvas.renderAll(); - handleObjectSelected() - } - } -}); -// pre_add_image 已在 design1.js 中定义为全局变量 -$("#addPic").click(function () { - OpenDialog(); - function OpenDialog() { - dialog.showOpenDialog({ - title: language_str("selectPic"),//请选择图片 - buttonLabel: language_str("comf"),//"确认" - filters: [ - { name: 'Image File Type', extensions: ['png', 'jpg', 'jpeg'] }, - ] - }).then(result => { - if (result.canceled) return; - //console.log(result.filePaths) - fabric.Image.fromURL(result.filePaths[0], function (image) { - //image.left = pointer.x; - image.setSrc(image.toDataURL(), function (image) { - pre_add_image = image; - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 1; - }); - //canvas.add(image); - }); - }).catch(err => { - console.log(err) - }) - } -}); -$("#addOutPic").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 2; -}); -$("#addText").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 3; -}); - -$("#addCircleText").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 11; -}); -$("#addOutText").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 4; -}); -$("#addRect").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 5; -}); -$("#addCircle").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 6; -}); -$("#addLine").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 7; -}); -$("#addQrCode").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 8; -}); -$("#addBarCode").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 9; -}); -$("#addCounter").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addCircleText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - addState = 10; -}); -$("#version_change").click(function () { - if (bg_version == 1) { - bg_version = 2; - } else { - bg_version = 1; - } - // 类型改变 - $("#source_front").attr("src", "./public/images/front_bg" + bg_version + "_1.png"); - canvas.renderAll(); - -}); -$("#front_side").click(function () { - $(this).addClass("ui-button-active"); - $("#back_side").removeClass("ui-button-active"); - $(".canvas-container:eq(0)").show(); - $(".canvas-container:eq(1)").hide(); - console.log("------"); - console.log(recordObjs1); - console.log("------"); - canvas = canvas1; - objs = objs1; - background_image = background_image1; - next_objs = next_objs1; - pre_objs = pre_objs1; - next_json = next_json1; - pre_json = pre_json1; - recordObjs = recordObjs1; - recordJson = recordJson1; - step = step1; - updateList(); - - $("#line_control").hide(); - $("#base_control").hide(); - $("#pic_control").hide(); - $("#out_pic_control").hide(); - $("#text_control").hide(); - $("#circle_text_control").hide(); - $("#out_text_control").hide(); - $("#rect_control").hide(); - $("#circle_control").hide(); - $("#counter_control").hide(); - $("#qrcode_Controll").hide(); - $("#barcode_controll").hide(); - $("#component_type").text(language_str("bg"));//背景 -}); -$("#back_side").click(function () { - $(this).addClass("ui-button-active"); - $("#front_side").removeClass("ui-button-active"); - $(".canvas-container:eq(0)").hide(); - $(".canvas-container:eq(1)").show(); - canvas = canvas2; - objs = objs2; - background_image = background_image2; - next_objs = next_objs2; - pre_objs = pre_objs2; - next_json = next_json2; - pre_json = pre_json2; - recordObjs = recordObjs2; - recordJson = recordJson2; - step = step2; - updateList(); - $("#line_control").hide(); - $("#base_control").hide(); - $("#pic_control").hide(); - $("#out_pic_control").hide(); - $("#text_control").hide(); - $("#circle_text_control").hide(); - $("#out_text_control").hide(); - $("#rect_control").hide(); - $("#circle_control").hide(); - $("#counter_control").hide(); - $("#qrcode_Controll").hide(); - $("#barcode_controll").hide(); - $("#component_type").text(language_str("bg"));//"背景" -}); -$("#top_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - _objs[0].set("top", background_image.get("top")); - canvas.renderAll(); - return; - } - let top = 0; - for (let item of _objs) { - let t_top = item.get("top"); - if (t_top < top) { - top = t_top; - } - } - groupItems = []; - for (let item of _objs) { - item.set("top", top); - groupItems.push(item); - } - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); - -}); -$("#bottom_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - let idx = getIndex(_objs[0]); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get("strokeWidth") - } - _objs[0].set("top", background_image.get("top") + background_image.get("height") - _objs[0].get("height") * _objs[0].get("scaleY") - other); - canvas.renderAll(); - return; - } - let bottom = 0; - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - let t_b = item.get("top") + item.get("height") * item.get("scaleY") + other; - if (t_b > bottom) { - bottom = t_b; - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - item.set("top", bottom - item.get("height") * item.get("scaleY") - other); - groupItems.push(item) - } - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); - -}); -$("#center_y_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - let idx = getIndex(_objs[0]); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get("strokeWidth") - } - _objs[0].set("top", background_image.get("top") + (background_image.get("height") - (_objs[0].get("height") + other) * _objs[0].get("scaleY")) / 2); - canvas.renderAll(); - return; - } - let top = 0; - for (let item of _objs) { - let t_top = item.get("top"); - if (t_top < top) { - top = t_top; - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - item.set("top", top + (item.group.height - (item.get("height") + other) * item.get("scaleY")) / 2); - groupItems.push(item) - } - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); -}); -$("#left_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - _objs[0].set("left", background_image.get("left")); - canvas.renderAll(); - return; - } - let left = 0; - for (let item of _objs) { - let t_left = item.get("left"); - if (t_left < left) { - left = t_left; - } - } - groupItems = [] - for (let item of _objs) { - item.set("left", left); - groupItems.push(item) - } - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); -}); -$("#right_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - let idx = getIndex(_objs[0]); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - _objs[0].set("left", background_image.get("left") + background_image.get("width") - _objs[0].get("width") * _objs[0].get("scaleX") - other); - canvas.renderAll(); - return; - } - let right = 0; - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - let t_r = item.get("left") + item.get("width") * item.get("scaleX") + other; - if (t_r > right) { - right = t_r; - } - } - let groupItems = [] - - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - item.set("left", right - item.get("width") * item.get("scaleX") - other); - groupItems.push(item) - } - //BUG1 - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); -}); -$("#center_x_alignment").click(function () { - let _objs = canvas.getActiveObjects(); - if (_objs.length == 1) { - //只选中了一�? - let idx = getIndex(_objs[0]); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get("strokeWidth") - } - _objs[0].set("left", background_image.get("left") + (background_image.get("width") - (_objs[0].get("width") + other) * _objs[0].get("scaleX")) / 2); - canvas.renderAll(); - return; - } - let left = 0; - for (let item of _objs) { - let t_left = item.get("left"); - if (t_left < left) { - left = t_left; - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item); - let type = objs[idx - 1].type; - let other = 0;//strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get("strokeWidth") - } - item.set("left", left + (item.group.width - (item.get("width") + other) * item.get("scaleX")) / 2); - groupItems.push(item) - } - canvas.discardActiveObject(); - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas, - }); - canvas.setActiveObject(sel); - canvas.requestRenderAll(); - canvas.renderAll(); -}); -$("#up_obj").click(function () {//上移,放到前�?数组中在后面 - let idx = getIndex(canvas.getActiveObject()); - if (idx + 1 != canvas.getObjects().length) { - canvas.bringForward(canvas.getActiveObject()); - canvas.renderAll(); - let temp = objs[idx - 1]; - objs[idx - 1] = objs[idx]; - objs[idx] = temp; - //console.log(objs); - - recordState(); - updateList(); - selectObj(idx); - } -}); -$("#down_obj").click(function () {//下移,放到后�?数组中在前面 - let idx = getIndex(canvas.getActiveObject()); - if (idx != 1) { - canvas.sendBackwards(canvas.getActiveObject()); - canvas.renderAll(); - //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; - - let temp = objs[idx - 1]; - objs[idx - 1] = objs[idx - 2]; - objs[idx - 2] = temp; - recordState(); - updateList(); - selectObj(idx - 2); - } -}); -$("#set_bg").click(function () {//设置为背�? - let obj = canvas.getActiveObject(); - console.log(obj, obj.get("selectable")) - let idx = getIndex(obj); - const scaleX = 2787 / obj.width - const scaleY = 2787 / obj.height - obj.set({ - scaleX: scaleX, - scaleY: scaleY, - left: ($('#canvas1').width() - 2787) / 2, - top: ($('#canvas1').height() - 2787) / 2, - }); - $('#text_w').val(2787) - $('#text_h').val(2787) - $('#text_x').val(0) - $('#text_y').val(0) - if (obj.get("selectable")) { - obj.set("selectable", false); - $("#lock_img").attr("src", "public/images/lock20.png") - } - canvas.sendToBack(obj); - canvas.bringForward(obj); - canvas.renderAll(); - let objItem = objs.splice(idx - 1, 1)[0] - objs.unshift(objItem) - recordState(); - updateList(); - selectObj(0); -}); - -// ========================================== -function onStateRestored() { - // 1. 重新获取背景图引�?(因为旧对象被销毁了) - if (canvas.getObjects().length > 0) { - background_image = canvas.getObjects()[0]; - background_image.selectable = false; // 确保背景不可�? - background_image.evented = false; - } - - // 2. 渲染画布 - canvas.requestRenderAll(); - - // 3. 取消选中状�? - selectObj(-1); - - // 4. 隐藏所有属性面�? - $("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide(); - - // 5. 刷新左侧列表 - updateList(); -} -// ========================================== -$("#previous").click(function () { - if (step.val == 0) return; - - step.val--; - - // 判断当前是正面还是背�? - if ($("#front_side").hasClass("ui-button-active")) { - // 1. 恢复业务数据 - objs1 = JSON.parse(recordObjs1[step.val]); - objs = objs1; - - // 2. 恢复画布 (使用回调函数�? - canvas.loadFromJSON(recordJson1[step.val], function () { - onStateRestored(); // 图片加载完才执行这一�? - }); - } else { - // 背面逻辑 - objs2 = JSON.parse(recordObjs2[step.val]); - objs = objs2; - - canvas.loadFromJSON(recordJson2[step.val], function () { - onStateRestored(); - }); - } -}); -// ========================================== -$("#next").click(function () { - // 获取当前历史记录的最大长�? - let maxLen = $("#front_side").hasClass("ui-button-active") ? recordObjs1.length : recordObjs2.length; - - if (step.val >= maxLen - 1) return; - - step.val++; - - if ($("#front_side").hasClass("ui-button-active")) { - objs1 = JSON.parse(recordObjs1[step.val]); - objs = objs1; - - canvas.loadFromJSON(recordJson1[step.val], function () { - onStateRestored(); // 图片加载完才执行这一�? - }); - } else { - objs2 = JSON.parse(recordObjs2[step.val]); - objs = objs2; - - canvas.loadFromJSON(recordJson2[step.val], function () { - onStateRestored(); - }); - } -}); - -$("#clean").click(function () { - objs.splice(0, objs.length); - - let allObjs = canvas.getObjects(); - for (let item of allObjs) { - if (item != allObjs[0]) { - canvas.remove(item); - } - } - updateList(); - recordState(); -}); -$("#rotate").click(function () { - let obj = canvas.getActiveObject(); - obj.rotate(Math.round((obj.get("angle") + 90) % 360)); - $("#text_r").val(obj.get("angle")); - canvas.renderAll(); - updateControls(); - recordState(); -}); -$('#vertical_obj').click(function () { - let obj = canvas.getActiveObject(); - obj.set("flipY", !obj.get("flipY")); - canvas.renderAll(); - updateControls(); - recordState(); -}); -$('#align_obj').click(function () { - let obj = canvas.getActiveObject(); - obj.set("flipX", !obj.get("flipX")); - canvas.renderAll(); - updateControls(); - recordState(); -}); -$("#text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�?恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_underline").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("underline", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("underline", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_linethrough").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("linethrough", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("linethrough", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); - -$("#circle_text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#circle_text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�?恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); - -$('#out_left_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_left_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'left') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'left' - recordState() - canvas.renderAll() -}) -$('#out_right_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_right_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'right') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'right' - recordState() - canvas.renderAll() -}) -$('#out_center_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_center_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'center') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'center' - recordState() - canvas.renderAll() -}) - -$("#out_text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�?恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_underline").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("underline", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("underline", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_linethrough").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已�? - canvas.getActiveObject().set("linethrough", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未�? - canvas.getActiveObject().set("linethrough", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#lock").click(function () { - canvas.getActiveObject().set("selectable", !canvas.getActiveObject().get("selectable")); - if (canvas.getActiveObject().get("selectable")) { - $("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解�? - } else { - $("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁 - } - recordState(); - canvas.renderAll(); -}); -$("#text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#circle_text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#out_text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#out_text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#rect_transparent").click(function () { - canvas.getActiveObject().set("fill", ""); - $("#rect_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#rect_stroke_transparent").click(function () { - canvas.getActiveObject().set("stroke", ""); - $("#rect_stroke").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_transparent").click(function () { - canvas.getActiveObject().set("fill", ""); - $("#circle_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_stroke_transparent").click(function () { - canvas.getActiveObject().set("stroke", ""); - $("#circle_stroke").val("#ffffff"); - canvas.renderAll(); -}); - -// saveAs 函数保留,因为它被作为回调传递给 output 函数(第52行) -function saveAs(op1, callback) { - let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); - let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); - - // 清理不需要的 src 字段 - cleanupSrcFields(j.objects, objs1); - cleanupSrcFields(b.objects, objs2); - - let o = { f: j, b: {}, fo: objs1, bo: objs2 }; - let con_o = Object.assign(o, op1); - dialog.showSaveDialog({ - title: language_str("saveFile"),//'保存文件' - filters: [ - { name: 'Soon File Type', extensions: ['soon'] }, - ] - }).then(result => { - if (result.filePath == "") { return; } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon'; - } - let fs = require('fs') - con_o.soonType = 1 - fs.writeFileSync(result.filePath, JSON.stringify(con_o)) - openAs.name = result.filePath; - layer.msg(language_str("saveSucc") + openAs.name);//'保存成功�? - saveHistory(); - if (callback && typeof callback === 'function') { - callback(); - } - }).catch(err => { - console.log() - }) -} -// save 函数已在 output.js 中定义 -$("#copy").click(function () { - copySelection(); -}) -// 粘贴 -$("#paste").click(function () { - pasteFromClipboard(); -}) - -// 保存 (保持你原有的保存逻辑不变) -$("#save").click(function () { - output(); // 这里调用你的 output 函数 - return; - // ... (下面是你原有的被 return 截断的代码,建议以后清理掉,但这里我按要求保�? - let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); - // ... (省略你原来那段很长的保存代码) ... -}); - -function getDate() { - let date = new Date(); - return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); -} -function getAbsoluteXY(_obj) { - let coord = _obj.get("lineCoords"); - return [_obj.get("left"), _obj.get("top")] -} -// fullPath 和 saveHistory 已在 output.js 中定义 -$("#open").click(function () { - if (step.val == 0) { - OpenDialog(); - return; - } - layer.confirm('' + language_str("whetherSave") + '', function (index) {//confirm 是否保存当前文件�? - output(OpenDialog); - layer.close(index); - - }, function (index) { - OpenDialog(); - }); - function OpenDialog() { - dialog.showOpenDialog({ - title: "请选择文件", - buttonLabel: language_str("comf"), - filters: [ - { name: 'Soon File Type', extensions: ['soon'] }, - ] - }).then(result => { - if (result.canceled) return; - let filePath = result.filePaths[0]; - let fs = require('fs'); - let fsData = fs.readFileSync(filePath); - let j = JSON.parse(fsData.toString()); - let type = j.soonType ? j.soonType : j.backBlackPic ? 2 : 1; - - if (type == 2) { - ipcRenderer.send('open-design-page', filePath, type); - return; - } - - // 调用 output.js 中的 open 函数 - open(filePath); - }).catch(err => { - console.log(err) - }) - } -}); -function clearAll() { - //let blank = "{\"f\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"#000000\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAX2YPDVmXlAHjVBgAABAgQIECBAgAABAgQIlAh8bQ8Gt83MQ0oWtiYBAgQIECBAgAABAgQIECCQBW7fg8GtM/OoPGuCAAECBAgQIECAAAECBAgQKBG4dQ8GN8zMdSULW5MAAQIECBAgQIAAAQIECBDIAjfuweADM/OsPGuCAAECBAgQIECAAAECBAgQKBH44B4M3jIzLy9Z2JoECBAgQIAAAQIECBAgQIBAFnjrHgxeMDPvzrMmCBAgQIAAAQIECBAgQIAAgRKBn9uDwYmZ+UTJwtYkQIAAAQIECBAgQIAAAQIEssCJPRg8cGa+ODNX5XkTBAgQIECAAAECBAgQIECAwGUucMfMPGztS27b9qGZedplvrD1CBAgQIAAAQIECBAgQIAAgSzw4bXW008Gg/1LD/cvP/QgQIAAAQIECBAgQIAAAQIEugVevtb6zZPB4JqZuanbw/YECBAgQIAAAQIECBAgQIDAzFy71rr568Fgf2zbdv3MPBENAQIECBAgQIAAAQIECBAgUCtw/VrrSfv2pwaDF8/Mb9eSWJwAAQIECBAgQIAAAQIECBB48VrrHXcPBg+dmc/OzLfwIUCAAAECBAgQIECAAAECBOoE/ntmrl5r3fYNwWD/H9u2vW1mXlJHYmECBAgQIECAAAECBAgQIEDg7Wutl55kuOufJByCwWNm5p9n5kGcCBAgQIAAAQIECBAgQIAAgRqB/5uZ711r3XKPweAQDd41Mz9fQ2JRAgQIECBAgAABAgQIECBA4HfXWi88leEbPmFwCAaPPHzK4CpeBAgQIECAAAECBAgQIECAwGUvcMfMPHattX+v4V2P04LBIRq8embecNmTWJAAAQIECBAgQIAAAQIECBB47VrrtAZwpmCwf4fBDTPzeG4ECBAgQIAAAQIECBAgQIDAZSvwqZk5sdb6yt03vMdgsA9t23ZiZj42M1dctiwWI0CAAAECBAgQIECAAAECvQJ3zsxT1lr7BwZOe5wxGByiwS/OzK/32tmcAAECBAgQIECAAAECBAhctgKvWmv92pm2S8Fg//M/nplnX7Y8FiNAgAABAgQIECBAgAABAn0C75uZ56y1tnMKBvsPbdv2rTPz5zPz5D4/GxMgQIAAAQIECBAgQIAAgctO4OMz87S11u1n2+ysnzA4+YPbtj388H0G1152TBYiQIAAAQIECBAgQIAAAQI9AjcdvrfgC2nlIwWD/Um2bXvMzHx0Zh6VntSfEyBAgAABAgQIECBAgAABAvc7gc/MzFPXWjcf5Z0dORgcosE1M/ORmfmuozy5GQIECBAgQIAAAQIECBAgQOB+IfDpmfnxtdb+CYMjPY4VDA7RYP+EwZ/MzBOO9AqGCBAgQIAAAQIECBAgQIAAgftS4JMz88y11v4JgyM/jh0MDtHgwTPzhzPzk0d+JYMECBAgQIAAAQIECBAgQIDAxRZ4/8w8f631peO+8DkFg0M02H/2lTPzKzNzxXFf2DwBAgQIECBAgAABAgQIECBwwQTunJlfnpk3ne1XJ57t1c85GJx80m3bThw+bfC4C7amJyZAgAABAgQIECBAgAABAgSOKvCPM/O8tdaNR/2Be5q718Fgf9Jt2/ZPGOyfNnj1zFx1b96QnyVAgAABAgQIECBAgAABAgTOSeCOmXnj4VMF+ycM7tXjvASDk+9g27ZHzMzrZuZnZ+ab7tU788MECBAgQIAAAQIECBAgQIDAUQT+d2Z+b2Zev9b6/FF+4Cgz5zUYnBIOrp6ZV8zMi2bmyqO8ETMECBAgQIAAAQIECBAgQIDAsQS+PDPvnJk3r7U+d6yfPMLwBQkGp4SDh87Mc/d/OzEzP3iE92OEAAECBAgQIECAAAECBAgQOLvA9TPznpl571rrtguFdUGDwalvetu2x8zMM2bmR2bmqTPzsAu1lOclQIAAAQIECBAgQIAAAQKXkcAXZ+avZ+avZubP1lo3X4zdLlowuFs8eMDMPGFmrpuZ75uZa2bmO2fm2w9fmrh/MsGDAAECBAgQIECAAAECBAi0COyfFNi/tPDfZ+bWmbllZvbfdrD/poNPrrW+drEh/h+5oaPdsxLhuQAAAABJRU5ErkJggg==\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"b\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"rgb(0,0,0)\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"fo\":[],\"bo\":[]}"; - let t_objs1 = canvas1.getObjects(); - let t_objs2 = canvas2.getObjects(); - for (let i = 1; i < t_objs1.length; i++) { - canvas1.remove(t_objs1[i]); - } - for (let i = 1; i < t_objs2.length; i++) { - canvas2.remove(t_objs2[i]); - } - objs2 = []; - objs1 = []; - step1.val = 0; - step2.val = 0; - recordJson1 = []; - recordJson2 = []; - recordObjs1 = []; - recordObjs2 = []; - if ($("#front_side").hasClass("ui-button-active")) { - objs = objs1; - recordObjs = recordObjs1; - recordJson = recordJson1; - step = step1; - } else if ($("#back_side").hasClass("ui-button-active")) { - objs = objs2; - recordObjs = recordObjs2; - recordJson = recordJson2; - step = step2; - } - openAs.name = ""; - canvas1.renderAll(); - canvas2.renderAll(); - updateList(); - console.log(); -} -$("#new").click(function () { - if (step.val == 0) { - ipcRenderer.send('open-first-page'); - return; - } - layer.confirm('' + language_str("whetherSave") + '', function (index) {//confirm 是否保存当前文件�? - output(() => ipcRenderer.send('open-first-page')); - }, function (index) { - ipcRenderer.send('open-first-page'); - }); -}); - -// =========================================================== -$("#text_y").bind('input propertychange', function () { - if (!canvas.getActiveObject()) return; - if ($("#text_y").val() == "") { - $("#text_y").val(0) - } - let val = background_image.top; - if ($("#text_y").val() != "") { - val = background_image.top + parseInt($("#text_y").val()); - } - canvas.getActiveObject().set("top", val) - canvas.renderAll(); - recordState(); -}) -$("#text_x").bind('input propertychange', function () { - if (!canvas.getActiveObject()) return; - if ($("#text_x").val() == "") { - $("#text_x").val(0) - } - let val = background_image.left; - if ($("#text_x").val() != "") { - val = background_image.left + parseInt($("#text_x").val()); - } - canvas.getActiveObject().set("left", val) - canvas.renderAll(); - recordState(); -}) -$("#text_w").bind('input propertychange', function () { - if (!canvas.getActiveObject()) return; - let val = "0"; - if ($("#text_w").val() != "") { - val = $("#text_w").val(); - } - let idx = getIndex(canvas.getActiveObject()); - if (idx <= 0 || !objs[idx - 1]) return; - let type = objs[idx - 1].type; - if (type == 3 || type == 4) { - canvas.getActiveObject().set("width", parseInt(val)) - } else { - canvas.getActiveObject().set("scaleX", parseInt(val) / canvas.getActiveObject().get("width")) - } - - canvas.renderAll(); - recordState(); -}) -$("#text_h").bind('input propertychange', function () { - if (!canvas.getActiveObject()) return; - let idx = getIndex(canvas.getActiveObject()); - if (idx <= 0 || !objs[idx - 1]) return; - if (objs[idx - 1].type == 7) { - if ($("#text_h").val() == "") { - $("#text_h").val(canvas.getActiveObject().get("strokeWidth")); - } - canvas.getActiveObject().set("strokeWidth", parseInt($("#text_h").val())); - canvas.renderAll(); - return; - } - let val = "0"; - if ($("#text_h").val() != "") { - val = $("#text_h").val(); - } - let type = objs[idx - 1].type; - if (type == 3 || type == 4) { - canvas.getActiveObject().set("height", parseInt(val)) - } else { - canvas.getActiveObject().set("scaleY", parseInt(val) / canvas.getActiveObject().get("height")) - } - - canvas.renderAll(); - recordState(); -}) -$("#text_r").bind('input propertychange', function () { - if (!canvas.getActiveObject()) return; - if ($("#text_r").val() == "") { - $("#text_r").val("0") - } - $("#text_r").val(parseInt($("#text_r").val()) % 360) - //canvas.getActiveObject().set("rotate", val) - canvas.getActiveObject().rotate(parseInt($("#text_r").val())) - canvas.renderAll(); - recordState(); -}) -$("#out_pic_field_name").bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()); - objs[idx - 1].name = $("#out_pic_field_name").val(); - updateList(); - recordState(); -}) - -$("#text_black").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - objs[idx - 1].black = true; - } else { - objs[idx - 1].black = false; - } - recordState(); -}); -$("#out_text_field_name").bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()); - objs[idx - 1].name = $("#out_text_field_name").val(); - updateList(); - recordState(); -}) -$("#qrcode_field_name").bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()); - objs[idx - 1].name = $("#qrcode_field_name").val(); - updateList(); - recordState(); -}) -$("#qrcode_color").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let qr = jrQrcode.getQrBase64($("#qrcode_val").val(), { padding: 0, foreground: $(this).val() }); - let idx = getIndex(item); - objs[idx - 1].color = $(this).val(); - item.setSrc(qr, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$("#qrcode_val").bind('change', function () { - let val = $(this).val() ? $(this).val() : 'https://www.cardsoon.com' - let item = canvas.getActiveObject(); - let qr = jrQrcode.getQrBase64(val, { padding: 0, foreground: $("#qrcode_color").val() }); - let idx = getIndex(item); - objs[idx - 1].val = val; - item.setSrc(qr, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$("#barcode_color").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - objs[idx - 1].color = $(this).val(); - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$("#barcode_field_name").bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()); - objs[idx - 1].name = $("#barcode_field_name").val(); - updateList(); - recordState(); -}) -$("#text_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#text_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#text_back_color").bind('input propertychange', function () { - canvas.getActiveObject().set("textBackgroundColor", $("#text_back_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#text_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#text_size").val())) { - val = parseFloat($("#text_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#text_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -$("#circle_text_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#circle_text_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#circle_text_back_color").bind('input propertychange', function () { - canvas.getActiveObject().set("textBackgroundColor", $("#circle_text_back_color").val()); - - canvas.renderAll(); - recordState(); -}) -$("#circle_text_text").bind('input propertychange', function () { - let val = $("#circle_text_text").val().trim() - canvas.getActiveObject().set("text", ` ${val} `); - canvas.renderAll(); - updateList(); - recordState(); -}) -$("#out_text_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#out_text_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#out_text_back_color").bind('input propertychange', function () { - canvas.getActiveObject().set("textBackgroundColor", $("#out_text_back_color").val()); - - canvas.renderAll(); - recordState(); -}) -$("#out_text_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#out_text_size").val())) { - val = parseFloat($("#out_text_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#out_text_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -// 监听合成文本输入框 (占位符) -$("#out_text_text").on('input propertychange', function () { - let val = $(this).val(); - - // 【核心修改】如果值为空,强制给 2 个空格 - if (val === "") { - val = " "; - } - - let obj = canvas.getActiveObject(); - if (obj) { - obj.set("text", val); - obj.setCoords(); - canvas.requestRenderAll(); - updateList(); - recordState(); - } -}); -$("#rect_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#rect_color").val()); - - canvas.renderAll(); - recordState(); -}) -$("#rect_stroke").bind('input propertychange', function () { - canvas.getActiveObject().set("stroke", $("#rect_stroke").val()); - - canvas.renderAll(); - recordState(); -}) -$("#rect_stroke_width").bind('input propertychange', function () { - if ($("#rect_stroke_width").val() == "") { - $("#rect_stroke_width").val("0") - } else { - $("#rect_stroke_width").val(parseInt($("#rect_stroke_width").val())) - } - canvas.getActiveObject().set("strokeWidth", parseInt($("#rect_stroke_width").val())); - canvas.renderAll(); - recordState(); -}) -$("#rect_radius").bind('input propertychange', function () { - if ($("#rect_radius").val() == "") { - $("#rect_radius").val("0") - } else { - $("#rect_radius").val(parseInt($("#rect_radius").val())) - } - canvas.getActiveObject().set("rx", parseInt($("#rect_radius").val())); - canvas.getActiveObject().set("ry", parseInt($("#rect_radius").val())); - canvas.renderAll(); - recordState(); -}) -$("#circle_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#circle_color").val()); - - canvas.renderAll(); - recordState(); -}) -$("#circle_stroke").bind('input propertychange', function () { - canvas.getActiveObject().set("stroke", $("#circle_stroke").val()); - - canvas.renderAll(); - recordState(); -}) -$("#circle_stroke_width").bind('input propertychange', function () { - if ($("#circle_stroke_width").val() == "") { - $("#circle_stroke_width").val("0") - } else { - $(this).val(parseInt($(this).val())) - } - canvas.getActiveObject().set("strokeWidth", parseInt($("#circle_stroke_width").val())); - canvas.renderAll(); - recordState(); -}) -$("#counter_start").bind('input propertychange', function () { - canvas.getActiveObject().set("text", $("#counter_start").val()); - let item = canvas.getActiveObject(); - let idx = getIndex(item); - objs[idx - 1].start = $(this).val(); - canvas.renderAll(); - recordState(); -}) -$("#counter_add").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - objs[idx - 1].add = $(this).val(); - canvas.renderAll(); - recordState(); -}) -$("#counter_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#counter_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#count_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#count_size").val())) { - val = parseFloat($("#count_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#count_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -$("#line_color").bind('input propertychange', function () { - canvas.getActiveObject().set("stroke", $("#line_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#line_dist").bind('input propertychange', function () { - if ($("#line_dist").val() == "") { - $("#line_dist").val(0) - } - canvas.getActiveObject().set("strokeDashArray", [parseInt($("#line_dist").val()), parseInt($("#line_dist").val())]) - canvas.renderAll(); - recordState(); -}) -// 监听普通文本输入 (占位符) -$("#text_text").on('input propertychange', function () { - // 1. 获取输入框的值,不要用 trim(),否则无法输入空格 - let val = $(this).val(); - - // 2. 核心修改:只有当删光时,才给 4 个空格作为占位符 - if (val === "") { - val = " "; // 4个空格,比原来的2个更宽,更好点 - } - // 3. 更新对象 - canvas.getActiveObject().set("text", val); - canvas.requestRenderAll(); // 使用 requestRenderAll 性能更好 - updateList(); - recordState(); -}); -$("#barcode_val").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - objs[idx - 1].val = $(this).val(); - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); - - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}) -$("#barcode_show").click(function () { - let item = canvas.getActiveObject(); - let idx = getIndex(canvas.getActiveObject()); - let val = $("#barcode_size").val() - if ($(this).prop("checked")) { - objs[idx - 1].show = true; - val = 0 - } else { - objs[idx - 1].show = false; - } - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: val * dpi / 72, font: objs[idx - 1].font }); - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$("#barcode_size").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - let val = 1 - if (parseFloat($(this).val())) { - val = parseFloat($(this).val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#barcode_size").val(val) - objs[idx - 1].fontSize = val * dpi / 72; - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); - - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}) -$('#count_font_family').on('change', function () { - canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) - canvas.renderAll() - recordState(); -}); -$('#text_font_family').on('change', function () { - canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) - canvas.renderAll() - recordState(); -}); - -$('#circle_text_font_family').on('change', function () { - canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) - canvas.renderAll() - recordState(); -}); - -$('#language_select').on('change', function () {//语言选择 - langua_ge($(this).find('option:selected').val()); - s_lan = $(this).find('option:selected').val(); - localStorage.setItem("lang", s_lan); -}); -$('#barcode_font_family').on('change', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - objs[idx - 1].font = $(this).find('option:selected').text(); - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); - - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); - //recordState(); -}); -$('#out_text_font_family').on('change', function () { - canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) - canvas.renderAll() - recordState(); -}); -$(".obj_list").on("click", "div", function () { - let idx = objs.length - 1 - $(this).index(); - selectObj(idx); -}); -$("#exceed").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - objs[idx - 1].exceed = true; - } else { - objs[idx - 1].exceed = false; - } - recordState(); -}); -$("#autoWrap").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - - objs[idx - 1].autoWrap = true; - } else { - objs[idx - 1].autoWrap = false; - } - recordState(); -}); -$("#fixSize").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - - objs[idx - 1].fixSize = true; - } else { - objs[idx - 1].fixSize = false; - } - recordState(); -}); -$("#circle_text_center").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - objs[idx - 1].circleCenter = 1; - } else { - objs[idx - 1].circleCenter = 0; - } - recordState(); -}); - -// =========================================================== -$("#text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选,恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_underline").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("underline", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("underline", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#text_linethrough").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("linethrough", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("linethrough", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); - -$("#circle_text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#circle_text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选,恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); - -$('#out_left_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_left_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'left') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'left' - recordState() - canvas.renderAll() -}) -$('#out_right_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_right_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'right') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'right' - recordState() - canvas.renderAll() -}) -$('#out_center_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_center_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'center') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'center' - recordState() - canvas.renderAll() -}) - -$("#out_text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选,恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_underline").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("underline", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("underline", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#out_text_linethrough").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("linethrough", false) - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("linethrough", true) - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); - -// =========================================================== -$("#delete").click(function () { - let actObjs = canvas.getActiveObjects(); - let allObjs = canvas.getObjects(); - let flag = 0; - for (let item of actObjs) { - if (item != allObjs[0]) { - let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 - objs.splice(i - 1, 1); - canvas.remove(item); - flag = 1; - - } - } - updateList(); - canvas.discardActiveObject(); - if (flag == 1) { - recordState(); - canvas.renderAll(); - } -}); -$("#up_obj").click(function () {//上移,放到前面 数组中在后面 - let idx = getIndex(canvas.getActiveObject()); - if (idx + 1 != canvas.getObjects().length) { - canvas.bringForward(canvas.getActiveObject()); - canvas.renderAll(); - let temp = objs[idx - 1]; - objs[idx - 1] = objs[idx]; - objs[idx] = temp; - //console.log(objs); - - recordState(); - updateList(); - selectObj(idx); - } -}); -$("#down_obj").click(function () {//下移,放到后面 数组中在前面 - let idx = getIndex(canvas.getActiveObject()); - if (idx != 1) { - canvas.sendBackwards(canvas.getActiveObject()); - canvas.renderAll(); - //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; - - let temp = objs[idx - 1]; - objs[idx - 1] = objs[idx - 2]; - objs[idx - 2] = temp; - recordState(); - updateList(); - selectObj(idx - 2); - } -}); -$("#set_bg").click(function () {//设置为背景 - let obj = canvas.getActiveObject(); - console.log(obj, obj.get("selectable")) - let idx = getIndex(obj); - const scaleX = 2787 / obj.width - const scaleY = 2787 / obj.height - obj.set({ - scaleX: scaleX, - scaleY: scaleY, - left: ($('#canvas1').width() - 2787) / 2, - top: ($('#canvas1').height() - 2787) / 2, - }); - $('#text_w').val(2787) - $('#text_h').val(2787) - $('#text_x').val(0) - $('#text_y').val(0) - if (obj.get("selectable")) { - obj.set("selectable", false); - $("#lock_img").attr("src", "public/images/lock20.png") - } - canvas.sendToBack(obj); - canvas.bringForward(obj); - canvas.renderAll(); - let objItem = objs.splice(idx - 1, 1)[0] - objs.unshift(objItem) - recordState(); - updateList(); - selectObj(0); -}); -$("#lock").click(function () { - canvas.getActiveObject().set("selectable", !canvas.getActiveObject().get("selectable")); - if (canvas.getActiveObject().get("selectable")) { - $("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解锁 - } else { - $("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁 - } - recordState(); - canvas.renderAll(); -}); -$("#text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#circle_text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#out_text_back_transparent").click(function () { - canvas.getActiveObject().set("textBackgroundColor", ""); - $("#out_text_back_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#rect_transparent").click(function () { - canvas.getActiveObject().set("fill", ""); - $("#rect_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#rect_stroke_transparent").click(function () { - canvas.getActiveObject().set("stroke", ""); - $("#rect_stroke").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_transparent").click(function () { - canvas.getActiveObject().set("fill", ""); - $("#circle_color").val("#ffffff"); - canvas.renderAll(); -}); -$("#circle_stroke_transparent").click(function () { - canvas.getActiveObject().set("stroke", ""); - $("#circle_stroke").val("#ffffff"); - canvas.renderAll(); -}); - -// =========================================================== -$("#about").click(async function () { - // 1. 先异步获取版本号 - let version = "0.0.0"; // 默认值,防止获取失败 - try { - if (window.sysAPI && window.sysAPI.getAppVersion) { - const v = await window.sysAPI.getAppVersion(); - version = "v" + v; // 拼接一个 v,变成 v2.3.017 - } - } catch (e) { - console.error("获取版本号失败", e); - } - - // 2. 获取成功后再弹出窗口 - layer.open({ - type: 1 - , title: language_str("about") - , area: '450px;' - , id: 'LAY_layuipro' - , moveType: 1 - , content: '
' + - '
' + - '
Soon Design
' + - // 【修改点】这里使用了刚才获取到的 version 变量 - '
' + language_str("vers") + ' ' + version + '
' + - '
' + language_str("copyright") + '
' + - '
' - }); -}) -$("#help").click(() => { - ipcRenderer.send('open-help-file'); -}); - -// =========================================================== -$('#display').on('click', function () { - // 类型改变 - fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_1.png', function (i1) { - i1.left = background_image.left; - i1.top = background_image.top; - let img1 = i1; - - fabric.Image.fromURL('./public/images/back_bg_1.png', function (i2) { - i2.left = background_image.left; - i2.top = background_image.top; - let img2 = i2; - fabric.Image.fromURL('./public/images/op_1.png', function (i3) { - i2.left = background_image.left; - i2.top = background_image.top; - let img3 = i3; - display_func(img1, img2, img3); - }) - }) - }) -}); -$("#output").click(function () { - output(); // 调用output函数(在output.js中定义) -}); +var _keyctrl = false, _keyc = false, _textEdit = false, _inputEdit = false; +$("input").focus(function () { + console.log(1) + _inputEdit = true +}) +$("input").blur(function () { + _inputEdit = false +}) +$("textarea").focus(function () { + console.log(1) + _inputEdit = true +}) +$("textarea").blur(function () { + _inputEdit = false +}) +$("body").keyup(function (event) { + // 兼容三端�?modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta�? + if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释�? + _keyctrl = false; + }; + if (event.keyCode == 67) { + _keyc = false; + }; +}) +$("body").keydown(function (event) { + // 统一的快捷键处理(兼�?Windows/Linux: Ctrl, Mac: Cmd/Meta�? + const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端 + + // 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的�? + if (!_inputEdit && !_textEdit) { + // CTRL/CMD+N - 新建 + if (isModifierKey && event.keyCode == 78) { + event.preventDefault(); + $("#new").click(); + return; + } + // CTRL/CMD+O - 打开 + if (isModifierKey && event.keyCode == 79) { + event.preventDefault(); + $("#open").click(); + return; + } + // CTRL/CMD+S - 保存 + if (isModifierKey && !event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + $("#save").click(); + return; + } + // CTRL/CMD+SHIFT+S - 保存副本 + if (isModifierKey && event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + if (typeof window.output === 'function') { + window.output(null, saveAs); + } + return; + } + // CTRL/CMD+Z - 还原 + if (isModifierKey && !event.shiftKey && event.keyCode == 90) { + event.preventDefault(); + $("#previous").click(); + return; + } + // CTRL/CMD+Y - 重做 + if (isModifierKey && !event.shiftKey && event.keyCode == 89) { + event.preventDefault(); + $("#next").click(); + return; + } + // CTRL/CMD+C - 复制 + if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { + event.preventDefault(); + window.copySelection(); + return; + } + // CTRL/CMD+V - 粘贴 + if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { + event.preventDefault(); + window.pasteFromClipboard(); + return; + } + + // CTRL/CMD + SHIFT + DEL (Windows) �?CMD + SHIFT + Backspace (Mac) - 清空 + if (isModifierKey && event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) { + event.preventDefault(); + $("#clean").click(); + return; + } + + // CTRL/CMD + DEL (Windows) �?CMD + Backspace (Mac) - 删除 + if (isModifierKey && !event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) { + event.preventDefault(); + $("#delete").click(); + return; + } + + } + // 兼容三端�?modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta�? + if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd�? + _keyctrl = true; + if (_keyc && _textEdit) { + //同时按下且在编辑状�? + setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) + //clipboard.writeText((clipboard.readText()+' ')) + } + } + if (event.keyCode == 67) { + _keyc = true; + if (_keyctrl & _textEdit) { + //同时按下且在编辑状�? + setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) + //clipboard.writeText((clipboard.readText()+' ')) + } + } + if (event.keyCode == 37) { + //left + let v = -1; + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = -5; + } + let x = canvas.getActiveObject().get("left"); + x += v; + canvas.getActiveObject().set("left", x); + canvas.renderAll(); + window.recordState(); + updateControls(); + } + if (event.keyCode == 38) { + //up + let v = -1; + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = -5; + } + let y = canvas.getActiveObject().get("top"); + y += v; + canvas.getActiveObject().set("top", y); + canvas.renderAll(); + window.recordState(); + updateControls(); + } + if (event.keyCode == 39) { + //right + let v = 1; + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = 5; + } + let x = canvas.getActiveObject().get("left"); + x += v; + canvas.getActiveObject().set("left", x); + canvas.renderAll(); + window.recordState(); + updateControls(); + } + if (event.keyCode == 40) { + //down + let v = +1; + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = 5; + } + let y = canvas.getActiveObject().get("top"); + y += v; + canvas.getActiveObject().set("top", y); + canvas.renderAll(); + window.recordState(); + updateControls(); + } + // 普通删除键(DEL键,没有按CTRL/CMD�? + if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) { + // 使用 window.canvas 作为后备,确保在 eval() 加载 .jsc 时也能访问 + const currentCanvas = window.canvas || canvas; + const currentObjs = window.objs || objs; + if (!currentCanvas) { + console.error('canvas is undefined in delete handler'); + return; + } + let actObjs = currentCanvas.getActiveObjects(); + let allObjs = currentCanvas.getObjects(); + let flag = 0; + for (let item of actObjs) { + if (item != allObjs[0]) { + let i = getIndex(item, currentCanvas);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 + currentObjs.splice(i - 1, 1); + currentCanvas.remove(item); + flag = 1; + + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + currentCanvas.discardActiveObject(); + if (flag == 1) { + window.recordState(); + canvas.renderAll(); + handleObjectSelected() + } + } +}); +// pre_add_image 已在 design1.js 中定义为全局变量 +$("#addPic").click(function () { + OpenDialog(); + function OpenDialog() { + dialog.showOpenDialog({ + title: language_str("selectPic"),//请选择图片 + buttonLabel: language_str("comf"),//"确认" + filters: [ + { name: 'Image File Type', extensions: ['png', 'jpg', 'jpeg'] }, + ] + }).then(result => { + if (result.canceled) return; + //console.log(result.filePaths) + fabric.Image.fromURL(result.filePaths[0], function (image) { + //image.left = pointer.x; + image.setSrc(image.toDataURL(), function (image) { + pre_add_image = image; + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 1; + }); + //canvas.add(image); + }); + }).catch(err => { + console.log(err) + }) + } +}); +$("#addOutPic").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 2; +}); +$("#addText").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 3; +}); + +$("#addCircleText").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 11; +}); +$("#addOutText").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 4; +}); +$("#addRect").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 5; +}); +$("#addCircle").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 6; +}); +$("#addLine").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 7; +}); +$("#addQrCode").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 8; +}); +$("#addBarCode").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 9; +}); +$("#addCounter").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addCircleText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + addState = 10; +}); +$("#version_change").click(function () { + if (bg_version == 1) { + bg_version = 2; + } else { + bg_version = 1; + } + // 类型改变 + $("#source_front").attr("src", "./public/images/front_bg" + bg_version + "_1.png"); + canvas.renderAll(); + +}); +$("#front_side").click(function () { + $(this).addClass("ui-button-active"); + $("#back_side").removeClass("ui-button-active"); + $(".canvas-container:eq(0)").show(); + $(".canvas-container:eq(1)").hide(); + console.log("------"); + console.log(recordObjs1); + console.log("------"); + canvas = canvas1; + objs = objs1; + background_image = background_image1; + window.canvas = canvas; + window.objs = objs; + window.background_image = background_image; + next_objs = next_objs1; + pre_objs = pre_objs1; + next_json = next_json1; + pre_json = pre_json1; + recordObjs = recordObjs1; + recordJson = recordJson1; + step = step1; + if (typeof window.updateList === 'function') { + window.updateList(); + } + + $("#line_control").hide(); + $("#base_control").hide(); + $("#pic_control").hide(); + $("#out_pic_control").hide(); + $("#text_control").hide(); + $("#circle_text_control").hide(); + $("#out_text_control").hide(); + $("#rect_control").hide(); + $("#circle_control").hide(); + $("#counter_control").hide(); + $("#qrcode_Controll").hide(); + $("#barcode_controll").hide(); + $("#component_type").text(language_str("bg"));//背景 +}); +$("#back_side").click(function () { + $(this).addClass("ui-button-active"); + $("#front_side").removeClass("ui-button-active"); + $(".canvas-container:eq(0)").hide(); + $(".canvas-container:eq(1)").show(); + canvas = canvas2; + objs = objs2; + background_image = background_image2; + window.canvas = canvas; + window.objs = objs; + window.background_image = background_image; + next_objs = next_objs2; + pre_objs = pre_objs2; + next_json = next_json2; + pre_json = pre_json2; + recordObjs = recordObjs2; + recordJson = recordJson2; + step = step2; + if (typeof window.updateList === 'function') { + window.updateList(); + } + $("#line_control").hide(); + $("#base_control").hide(); + $("#pic_control").hide(); + $("#out_pic_control").hide(); + $("#text_control").hide(); + $("#circle_text_control").hide(); + $("#out_text_control").hide(); + $("#rect_control").hide(); + $("#circle_control").hide(); + $("#counter_control").hide(); + $("#qrcode_Controll").hide(); + $("#barcode_controll").hide(); + $("#component_type").text(language_str("bg"));//"背景" +}); +$("#top_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMinY = getCoordsMinY(coords); + let bgMinY = getCoordsMinY(background_image.getCoords(true)); + let deltaY = bgMinY - objMinY; + obj.set("top", obj.get("top") + deltaY); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的最小Y值 + let minTop = Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinY = getCoordsMinY(coords); + if (itemMinY < minTop) { + minTop = itemMinY; + } + } + // 将所有对象对齐到最小Y值 + groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinY = getCoordsMinY(coords); + let deltaY = minTop - itemMinY; + item.set("top", item.get("top") + deltaY); + item.setCoords(); + groupItems.push(item); + } + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + +}); +$("#bottom_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let idx = getIndex(_objs[0]); + let type = objs[idx - 1].type; + let other = 0;//strokeWidth + if (type == 5 || type == 6 || type == 7) { + other = _objs[0].get("strokeWidth") + } + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMaxY = getCoordsMaxY(coords); + let bgMaxY = getCoordsMaxY(background_image.getCoords(true)); + let deltaY = bgMaxY - objMaxY; + obj.set("top", obj.get("top") + deltaY); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的最大Y值 + let maxBottom = -Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMaxY = getCoordsMaxY(coords); + if (itemMaxY > maxBottom) { + maxBottom = itemMaxY; + } + } + // 将所有对象对齐到最大Y值 + groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMaxY = getCoordsMaxY(coords); + let deltaY = maxBottom - itemMaxY; + item.set("top", item.get("top") + deltaY); + item.setCoords(); + groupItems.push(item); + } + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + +}); +$("#center_y_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let idx = getIndex(_objs[0]); + let type = objs[idx - 1].type; + let other = 0;//strokeWidth + if (type == 5 || type == 6 || type == 7) { + other = _objs[0].get("strokeWidth") + } + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMinY = getCoordsMinY(coords); + let objMaxY = getCoordsMaxY(coords); + let objCenterY = (objMinY + objMaxY) / 2; + let bgCoords = background_image.getCoords(true); + let bgMinY = getCoordsMinY(bgCoords); + let bgMaxY = getCoordsMaxY(bgCoords); + let bgCenterY = (bgMinY + bgMaxY) / 2; + let deltaY = bgCenterY - objCenterY; + obj.set("top", obj.get("top") + deltaY); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的中心Y值 + let minTop = Infinity; + let maxBottom = -Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinY = getCoordsMinY(coords); + let itemMaxY = getCoordsMaxY(coords); + if (itemMinY < minTop) minTop = itemMinY; + if (itemMaxY > maxBottom) maxBottom = itemMaxY; + } + let groupCenterY = (minTop + maxBottom) / 2; + // 将所有对象对齐到中心Y值 + groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinY = getCoordsMinY(coords); + let itemMaxY = getCoordsMaxY(coords); + let itemCenterY = (itemMinY + itemMaxY) / 2; + let deltaY = groupCenterY - itemCenterY; + item.set("top", item.get("top") + deltaY); + item.setCoords(); + groupItems.push(item); + } + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + window.recordState(); +}); +$("#left_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMinX = getCoordsMinX(coords); + let bgMinX = getCoordsMinX(background_image.getCoords(true)); + let deltaX = bgMinX - objMinX; + obj.set("left", obj.get("left") + deltaX); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的最小X值 + let minLeft = Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinX = getCoordsMinX(coords); + if (itemMinX < minLeft) { + minLeft = itemMinX; + } + } + // 将所有对象对齐到最小X值 + groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinX = getCoordsMinX(coords); + let deltaX = minLeft - itemMinX; + item.set("left", item.get("left") + deltaX); + item.setCoords(); + groupItems.push(item); + } + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + window.recordState(); +}); +$("#right_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let idx = getIndex(_objs[0]); + let type = objs[idx - 1].type; + let other = 0;//strokeWidth + if (type == 5 || type == 6 || type == 7) { + other = item.get("strokeWidth") + } + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMaxX = getCoordsMaxX(coords); + let bgMaxX = getCoordsMaxX(background_image.getCoords(true)); + let deltaX = bgMaxX - objMaxX; + obj.set("left", obj.get("left") + deltaX); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的最大X值 + let maxRight = -Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMaxX = getCoordsMaxX(coords); + if (itemMaxX > maxRight) { + maxRight = itemMaxX; + } + } + // 将所有对象对齐到最大X值 + let groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMaxX = getCoordsMaxX(coords); + let deltaX = maxRight - itemMaxX; + item.set("left", item.get("left") + deltaX); + item.setCoords(); + groupItems.push(item); + } + //BUG1 + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + window.recordState(); +}); +$("#center_x_alignment").click(function () { + let _objs = canvas.getActiveObjects(); + if (_objs.length == 1) { + //只选中了一�? + let idx = getIndex(_objs[0]); + let type = objs[idx - 1].type; + let other = 0;//strokeWidth + if (type == 5 || type == 6 || type == 7) { + other = _objs[0].get("strokeWidth") + } + let obj = _objs[0]; + obj.setCoords(); + let coords = obj.getCoords(true); + let objMinX = getCoordsMinX(coords); + let objMaxX = getCoordsMaxX(coords); + let objCenterX = (objMinX + objMaxX) / 2; + let bgCoords = background_image.getCoords(true); + let bgMinX = getCoordsMinX(bgCoords); + let bgMaxX = getCoordsMaxX(bgCoords); + let bgCenterX = (bgMinX + bgMaxX) / 2; + let deltaX = bgCenterX - objCenterX; + obj.set("left", obj.get("left") + deltaX); + obj.setCoords(); + canvas.renderAll(); + window.recordState(); + return; + } + // 多个对象对齐:找到所有对象边界框的中心X值 + let minLeft = Infinity; + let maxRight = -Infinity; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinX = getCoordsMinX(coords); + let itemMaxX = getCoordsMaxX(coords); + if (itemMinX < minLeft) minLeft = itemMinX; + if (itemMaxX > maxRight) maxRight = itemMaxX; + } + let groupCenterX = (minLeft + maxRight) / 2; + // 将所有对象对齐到中心X值 + groupItems = []; + for (let item of _objs) { + item.setCoords(); + let coords = item.getCoords(true); + let itemMinX = getCoordsMinX(coords); + let itemMaxX = getCoordsMaxX(coords); + let itemCenterX = (itemMinX + itemMaxX) / 2; + let deltaX = groupCenterX - itemCenterX; + item.set("left", item.get("left") + deltaX); + item.setCoords(); + groupItems.push(item); + } + canvas.discardActiveObject(); + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas, + }); + canvas.setActiveObject(sel); + canvas.requestRenderAll(); + canvas.renderAll(); + window.recordState(); +}); +$("#up_obj").click(function () {//上移,放到前�?数组中在后面 + let idx = getIndex(canvas.getActiveObject()); + if (idx + 1 != canvas.getObjects().length) { + canvas.bringForward(canvas.getActiveObject()); + canvas.renderAll(); + let temp = objs[idx - 1]; + objs[idx - 1] = objs[idx]; + objs[idx] = temp; + //console.log(objs); + + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx); + } + } +}); +$("#down_obj").click(function () {//下移,放到后�?数组中在前面 + let idx = getIndex(canvas.getActiveObject()); + if (idx != 1) { + canvas.sendBackwards(canvas.getActiveObject()); + canvas.renderAll(); + //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; + + let temp = objs[idx - 1]; + objs[idx - 1] = objs[idx - 2]; + objs[idx - 2] = temp; + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx - 2); + } + } +}); +$("#set_bg").click(function () {//设置为背�? + let obj = canvas.getActiveObject(); + console.log(obj, obj.get("selectable")) + let idx = getIndex(obj); + const scaleX = 2787 / obj.width + const scaleY = 2787 / obj.height + // 使用缩放后的实际尺寸计算位置,确保与初始背景图片位置一致 + const scaledWidth = obj.width * scaleX; + const scaledHeight = obj.height * scaleY; + obj.set({ + scaleX: scaleX, + scaleY: scaleY, + left: ($('#canvas1').width() - scaledWidth) / 2, + top: ($('#canvas1').height() - scaledHeight) / 2, + }); + $('#text_w').val(2787) + $('#text_h').val(2787) + $('#text_x').val(0) + $('#text_y').val(0) + if (obj.get("selectable")) { + obj.set("selectable", false); + $("#lock_img").attr("src", "public/images/lock20.png") + } + canvas.sendToBack(obj); + canvas.bringForward(obj); + canvas.renderAll(); + let objItem = objs.splice(idx - 1, 1)[0] + objs.unshift(objItem) + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(0); + } +}); + +// ========================================== +// onStateRestored 函数在 core.js 中定义并附加到 window 对象 +// ========================================== +$("#previous").click(function () { + if (step.val == 0) return; + + step.val--; + + // 判断当前是正面还是背面 + if ($("#front_side").hasClass("ui-button-active")) { + // 1. 恢复业务数据 + objs1 = JSON.parse(recordObjs1[step.val]); + objs = objs1; + + // 2. 恢复画布 (使用回调函数) + canvas.loadFromJSON(recordJson1[step.val], function () { + if (typeof window.onStateRestored === 'function') { + window.onStateRestored(); // 图片加载完才执行这一行 + } + }); + } else { + // 背面逻辑 + objs2 = JSON.parse(recordObjs2[step.val]); + objs = objs2; + + canvas.loadFromJSON(recordJson2[step.val], function () { + if (typeof window.onStateRestored === 'function') { + window.onStateRestored(); + } + }); + } +}); +// ========================================== +$("#next").click(function () { + // 获取当前历史记录的最大长度 + let maxLen = $("#front_side").hasClass("ui-button-active") ? recordObjs1.length : recordObjs2.length; + + if (step.val >= maxLen - 1) return; + + step.val++; + + if ($("#front_side").hasClass("ui-button-active")) { + objs1 = JSON.parse(recordObjs1[step.val]); + objs = objs1; + + canvas.loadFromJSON(recordJson1[step.val], function () { + if (typeof window.onStateRestored === 'function') { + window.onStateRestored(); // 图片加载完才执行这一行 + } + }); + } else { + objs2 = JSON.parse(recordObjs2[step.val]); + objs = objs2; + + canvas.loadFromJSON(recordJson2[step.val], function () { + if (typeof window.onStateRestored === 'function') { + window.onStateRestored(); + } + }); + } +}); + +$("#clean").click(function () { + objs.splice(0, objs.length); + + let allObjs = canvas.getObjects(); + for (let item of allObjs) { + if (item != allObjs[0]) { + canvas.remove(item); + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}); +$("#rotate").click(function () { + let obj = canvas.getActiveObject(); + obj.rotate(Math.round((obj.get("angle") + 90) % 360)); + $("#text_r").val(obj.get("angle")); + canvas.renderAll(); + updateControls(); + window.recordState(); +}); +$('#vertical_obj').click(function () { + let obj = canvas.getActiveObject(); + obj.set("flipY", !obj.get("flipY")); + canvas.renderAll(); + updateControls(); + window.recordState(); +}); +$('#align_obj').click(function () { + let obj = canvas.getActiveObject(); + obj.set("flipX", !obj.get("flipX")); + canvas.renderAll(); + updateControls(); + window.recordState(); +}); +$("#text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�?恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_underline").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("underline", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("underline", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_linethrough").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("linethrough", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("linethrough", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); + +$("#circle_text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�?恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); + +$('#out_left_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_left_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'left') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'left' + window.recordState(); + canvas.renderAll(); +}) +$('#out_right_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_right_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'right') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'right' + window.recordState(); + canvas.renderAll(); +}) +$('#out_center_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_center_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'center') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'center' + window.recordState(); + canvas.renderAll(); +}) + +$("#out_text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�?恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_underline").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("underline", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("underline", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_linethrough").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已�? + canvas.getActiveObject().set("linethrough", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未�? + canvas.getActiveObject().set("linethrough", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#lock").off('click').on('click', function (e) { + e.stopPropagation(); + if (!canvas.getActiveObject()) return; + let obj = canvas.getActiveObject(); + // 检查是否已锁定(通过lockMovementX判断,因为锁定时会设置所有lock属性) + let isLocked = obj.get("lockMovementX") === true; + let shouldLock = !isLocked; + + // 锁定/解锁所有编辑操作,锁定后不可选中 + obj.set({ + lockMovementX: shouldLock, + lockMovementY: shouldLock, + lockRotation: shouldLock, + lockScalingX: shouldLock, + lockScalingY: shouldLock, + lockSkewingX: shouldLock, + lockSkewingY: shouldLock, + // 锁定时不可选中,解锁时可选中 + selectable: !shouldLock, + evented: !shouldLock + }); + if (shouldLock) { + $("#lock_img").attr("src", "public/images/lock20.png")//已锁定//已经上锁,需要解�? + // 锁定后取消选中 + canvas.discardActiveObject(); + } else { + $("#lock_img").attr("src", "public/images/unlock20.png")//已解锁 + } + updateControls(); + window.recordState(); + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } + canvas.renderAll(); + window.recordState(); +}); +$("#text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#circle_text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#out_text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#rect_transparent").click(function () { + canvas.getActiveObject().set("fill", ""); + $("#rect_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#rect_stroke_transparent").click(function () { + canvas.getActiveObject().set("stroke", ""); + $("#rect_stroke").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_transparent").click(function () { + canvas.getActiveObject().set("fill", ""); + $("#circle_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_stroke_transparent").click(function () { + canvas.getActiveObject().set("stroke", ""); + $("#circle_stroke").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); + +// saveAs 函数保留,因为它被作为回调传递给 output 函数(第52行) +function saveAs(op1, callback) { + let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + + // 清理不需要的 src 字段(使用 window.cleanupSrcFields,在 output.js 中定义) + if (typeof window.cleanupSrcFields === 'function') { + window.cleanupSrcFields(j.objects, objs1); + window.cleanupSrcFields(b.objects, objs2); + } + + let o = { f: j, b: {}, fo: objs1, bo: objs2 }; + let con_o = Object.assign(o, op1); + dialog.showSaveDialog({ + title: language_str("saveFile"),//'保存文件' + filters: [ + { name: 'Soon File Type', extensions: ['soon'] }, + ] + }).then(result => { + if (result.filePath == "") { return; } + if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { + result.filePath += '.soon'; + } + let fs = require('fs') + con_o.soonType = 1 + fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8') + openAs.name = result.filePath; + layer.msg(language_str("saveSucc") + openAs.name);//'保存成功�? + if (typeof window.saveHistory === 'function') { + window.saveHistory(); + } + if (callback && typeof callback === 'function') { + callback(); + } + }).catch(err => { + console.log() + }) +} +// save 函数已在 output.js 中定义 +$("#copy").click(function () { + window.copySelection(); +}) +// 粘贴 +$("#paste").click(function () { + window.pasteFromClipboard(); +}) + +// 保存 (保持你原有的保存逻辑不变) +$("#save").click(function () { + if (typeof window.output === 'function') { + window.output(); // 这里调用你的 output 函数 + } + return; + // ... (下面是你原有的被 return 截断的代码,建议以后清理掉,但这里我按要求保�? + let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + // ... (省略你原来那段很长的保存代码) ... +}); + +function getDate() { + let date = new Date(); + return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); +} +function getAbsoluteXY(_obj) { + let coord = _obj.get("lineCoords"); + return [_obj.get("left"), _obj.get("top")] +} +// fullPath 和 saveHistory 已在 output.js 中定义 +$("#open").click(function () { + if (step.val == 0) { + OpenDialog(); + return; + } + layer.confirm('' + language_str("whetherSave") + '', function (index) {//confirm 是否保存当前文件�? + if (typeof window.output === 'function') { + window.output(OpenDialog); + } + layer.close(index); + + }, function (index) { + OpenDialog(); + }); + function OpenDialog() { + dialog.showOpenDialog({ + title: "请选择文件", + buttonLabel: language_str("comf"), + filters: [ + { name: 'Soon File Type', extensions: ['soon'] }, + ] + }).then(result => { + if (result.canceled) return; + let filePath = result.filePaths[0]; + let fs = require('fs'); + let fsData = fs.readFileSync(filePath); + let j = JSON.parse(fsData.toString()); + let type = j.soonType ? j.soonType : j.backBlackPic ? 2 : 1; + + if (type == 2) { + ipcRenderer.send('open-design-page', filePath, type); + return; + } + + // 调用 output.js 中的 openFile 函数 + if (typeof window.openFile === 'function') { + window.openFile(filePath); + } else { + console.error('openFile 函数未定义!'); + } + }).catch(err => { + console.log(err) + }) + } +}); + //let blank = "{\"f\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"#000000\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"b\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"rgb(0,0,0)\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"fo\":[],\"bo\":[]}"; + let t_objs1 = canvas1.getObjects(); + let t_objs2 = canvas2.getObjects(); + for (let i = 1; i < t_objs1.length; i++) { + canvas1.remove(t_objs1[i]); + } + for (let i = 1; i < t_objs2.length; i++) { + canvas2.remove(t_objs2[i]); + } + objs2 = []; + objs1 = []; + step1.val = 0; + step2.val = 0; + recordJson1 = []; + recordJson2 = []; + recordObjs1 = []; + recordObjs2 = []; + if ($("#front_side").hasClass("ui-button-active")) { + objs = objs1; + recordObjs = recordObjs1; + recordJson = recordJson1; + step = step1; + } else if ($("#back_side").hasClass("ui-button-active")) { + objs = objs2; + recordObjs = recordObjs2; + recordJson = recordJson2; + step = step2; + } + openAs.name = ""; + canvas1.renderAll(); + canvas2.renderAll(); + if (typeof window.updateList === 'function') { + window.updateList(); + } +$("#new").click(function () { + if (step.val == 0) { + ipcRenderer.send('open-first-page'); + return; + } + layer.confirm('' + language_str("whetherSave") + '', function (index) {//confirm 是否保存当前文件�? + if (typeof window.output === 'function') { + window.output(() => ipcRenderer.send('open-first-page')); + } + }, function (index) { + ipcRenderer.send('open-first-page'); + }); +}); + +// =========================================================== +$("#text_y").bind('input propertychange', function () { + if (!canvas.getActiveObject()) return; + if ($("#text_y").val() == "") { + $("#text_y").val(0) + } + let val = background_image.top; + if ($("#text_y").val() != "") { + val = background_image.top + parseInt($("#text_y").val()); + } + canvas.getActiveObject().set("top", val) + canvas.renderAll(); + window.recordState(); +}) +$("#text_x").bind('input propertychange', function () { + if (!canvas.getActiveObject()) return; + if ($("#text_x").val() == "") { + $("#text_x").val(0) + } + let val = background_image.left; + if ($("#text_x").val() != "") { + val = background_image.left + parseInt($("#text_x").val()); + } + canvas.getActiveObject().set("left", val) + canvas.renderAll(); + window.recordState(); +}) +$("#text_w").bind('input propertychange', function () { + if (!canvas.getActiveObject()) return; + let val = "0"; + if ($("#text_w").val() != "") { + val = $("#text_w").val(); + } + let idx = getIndex(canvas.getActiveObject()); + if (idx <= 0 || !objs[idx - 1]) return; + let type = objs[idx - 1].type; + if (type == 3 || type == 4) { + canvas.getActiveObject().set("width", parseInt(val)) + } else { + canvas.getActiveObject().set("scaleX", parseInt(val) / canvas.getActiveObject().get("width")) + } + + canvas.renderAll(); + window.recordState(); +}) +$("#text_h").bind('input propertychange', function () { + if (!canvas.getActiveObject()) return; + let idx = getIndex(canvas.getActiveObject()); + if (idx <= 0 || !objs[idx - 1]) return; + if (objs[idx - 1].type == 7) { + if ($("#text_h").val() == "") { + $("#text_h").val(canvas.getActiveObject().get("strokeWidth")); + } + canvas.getActiveObject().set("strokeWidth", parseInt($("#text_h").val())); + canvas.renderAll(); + return; + } + let val = "0"; + if ($("#text_h").val() != "") { + val = $("#text_h").val(); + } + let type = objs[idx - 1].type; + if (type == 3 || type == 4) { + canvas.getActiveObject().set("height", parseInt(val)) + } else { + canvas.getActiveObject().set("scaleY", parseInt(val) / canvas.getActiveObject().get("height")) + } + + canvas.renderAll(); + window.recordState(); +}) +$("#text_r").bind('input propertychange', function () { + if (!canvas.getActiveObject()) return; + if ($("#text_r").val() == "") { + $("#text_r").val("0") + } + $("#text_r").val(parseInt($("#text_r").val()) % 360) + //canvas.getActiveObject().set("rotate", val) + canvas.getActiveObject().rotate(parseInt($("#text_r").val())) + canvas.renderAll(); + window.recordState(); +}) +$("#out_pic_field_name").bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()); + objs[idx - 1].name = $("#out_pic_field_name").val(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}) + +$("#text_black").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + objs[idx - 1].black = true; + } else { + objs[idx - 1].black = false; + } + window.recordState(); +}); +$("#out_text_field_name").bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()); + objs[idx - 1].name = $("#out_text_field_name").val(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}) +$("#qrcode_field_name").bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()); + objs[idx - 1].name = $("#qrcode_field_name").val(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}) +$("#qrcode_color").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let qr = jrQrcode.getQrBase64($("#qrcode_val").val(), { padding: 0, foreground: $(this).val() }); + let idx = getIndex(item); + objs[idx - 1].color = $(this).val(); + item.setSrc(qr, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}); +$("#qrcode_val").bind('change', function () { + let val = $(this).val() ? $(this).val() : 'https://www.cardsoon.com' + let item = canvas.getActiveObject(); + let qr = jrQrcode.getQrBase64(val, { padding: 0, foreground: $("#qrcode_color").val() }); + let idx = getIndex(item); + objs[idx - 1].val = val; + item.setSrc(qr, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}); +$("#barcode_color").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + objs[idx - 1].color = $(this).val(); + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}); +$("#barcode_field_name").bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()); + objs[idx - 1].name = $("#barcode_field_name").val(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}) +$("#text_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#text_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#text_back_color").bind('input propertychange', function () { + canvas.getActiveObject().set("textBackgroundColor", $("#text_back_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#text_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#text_size").val())) { + val = parseFloat($("#text_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#text_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + window.recordState(); +}) +$("#circle_text_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#circle_text_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#circle_text_back_color").bind('input propertychange', function () { + canvas.getActiveObject().set("textBackgroundColor", $("#circle_text_back_color").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#circle_text_text").bind('input propertychange', function () { + let val = $("#circle_text_text").val().trim() + canvas.getActiveObject().set("text", ` ${val} `); + canvas.renderAll(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}) +$("#out_text_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#out_text_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#out_text_back_color").bind('input propertychange', function () { + canvas.getActiveObject().set("textBackgroundColor", $("#out_text_back_color").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#out_text_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#out_text_size").val())) { + val = parseFloat($("#out_text_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#out_text_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + window.recordState(); +}) +// 监听合成文本输入框 (占位符) +$("#out_text_text").on('input propertychange', function () { + let val = $(this).val(); + + // 【核心修改】如果值为空,强制给 2 个空格 + if (val === "") { + val = " "; + } + + let obj = canvas.getActiveObject(); + if (obj) { + obj.set("text", val); + obj.setCoords(); + canvas.requestRenderAll(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); + } +}); +$("#rect_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#rect_color").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#rect_stroke").bind('input propertychange', function () { + canvas.getActiveObject().set("stroke", $("#rect_stroke").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#rect_stroke_width").bind('input propertychange', function () { + if ($("#rect_stroke_width").val() == "") { + $("#rect_stroke_width").val("0") + } else { + $("#rect_stroke_width").val(parseInt($("#rect_stroke_width").val())) + } + canvas.getActiveObject().set("strokeWidth", parseInt($("#rect_stroke_width").val())); + canvas.renderAll(); + window.recordState(); +}) +$("#rect_radius").bind('input propertychange', function () { + if ($("#rect_radius").val() == "") { + $("#rect_radius").val("0") + } else { + $("#rect_radius").val(parseInt($("#rect_radius").val())) + } + canvas.getActiveObject().set("rx", parseInt($("#rect_radius").val())); + canvas.getActiveObject().set("ry", parseInt($("#rect_radius").val())); + canvas.renderAll(); + window.recordState(); +}) +$("#circle_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#circle_color").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#circle_stroke").bind('input propertychange', function () { + canvas.getActiveObject().set("stroke", $("#circle_stroke").val()); + + canvas.renderAll(); + window.recordState(); +}) +$("#circle_stroke_width").bind('input propertychange', function () { + if ($("#circle_stroke_width").val() == "") { + $("#circle_stroke_width").val("0") + } else { + $(this).val(parseInt($(this).val())) + } + canvas.getActiveObject().set("strokeWidth", parseInt($("#circle_stroke_width").val())); + canvas.renderAll(); + window.recordState(); +}) +$("#counter_start").bind('input propertychange', function () { + canvas.getActiveObject().set("text", $("#counter_start").val()); + let item = canvas.getActiveObject(); + let idx = getIndex(item); + objs[idx - 1].start = $(this).val(); + canvas.renderAll(); + window.recordState(); +}) +$("#counter_add").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + objs[idx - 1].add = $(this).val(); + canvas.renderAll(); + window.recordState(); +}) +$("#counter_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#counter_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#count_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#count_size").val())) { + val = parseFloat($("#count_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#count_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + window.recordState(); +}) +$("#line_color").bind('input propertychange', function () { + canvas.getActiveObject().set("stroke", $("#line_color").val()); + canvas.renderAll(); + window.recordState(); +}) +$("#line_dist").bind('input propertychange', function () { + if ($("#line_dist").val() == "") { + $("#line_dist").val(0) + } + canvas.getActiveObject().set("strokeDashArray", [parseInt($("#line_dist").val()), parseInt($("#line_dist").val())]) + canvas.renderAll(); + window.recordState(); +}) +// 监听普通文本输入 (占位符) +$("#text_text").on('input propertychange', function () { + // 1. 获取输入框的值,不要用 trim(),否则无法输入空格 + let val = $(this).val(); + + // 2. 核心修改:只有当删光时,才给 4 个空格作为占位符 + if (val === "") { + val = " "; // 4个空格,比原来的2个更宽,更好点 + } + // 3. 更新对象 + canvas.getActiveObject().set("text", val); + canvas.requestRenderAll(); // 使用 requestRenderAll 性能更好 + if (typeof window.updateList === 'function') { + window.updateList(); + } + window.recordState(); +}); +$("#barcode_val").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + objs[idx - 1].val = $(this).val(); + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); + + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}) +$("#barcode_show").click(function () { + let item = canvas.getActiveObject(); + let idx = getIndex(canvas.getActiveObject()); + let val = $("#barcode_size").val() + if ($(this).prop("checked")) { + objs[idx - 1].show = true; + val = 0 + } else { + objs[idx - 1].show = false; + } + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: val * dpi / 72, font: objs[idx - 1].font }); + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}); +$("#barcode_size").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + let val = 1 + if (parseFloat($(this).val())) { + val = parseFloat($(this).val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#barcode_size").val(val) + objs[idx - 1].fontSize = val * dpi / 72; + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); + + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + window.recordState(); + }); +}) +$('#count_font_family').on('change', function () { + canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) + canvas.renderAll() + window.recordState(); +}); +$('#text_font_family').on('change', function () { + canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) + canvas.renderAll() + window.recordState(); +}); + +$('#circle_text_font_family').on('change', function () { + canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) + canvas.renderAll() + window.recordState(); +}); + +$('#language_select').on('change', function () {//语言选择 + langua_ge($(this).find('option:selected').val()); + s_lan = $(this).find('option:selected').val(); + localStorage.setItem("lang", s_lan); +}); +$('#barcode_font_family').on('change', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + objs[idx - 1].font = $(this).find('option:selected').text(); + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); + + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + window.recordState(); + }); + //window.recordState(); +}); +$('#out_text_font_family').on('change', function () { + canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) + canvas.renderAll() + window.recordState(); +}); +$(".obj_list").on("click", "div", function () { + let idx = objs.length - 1 - $(this).index(); + if (typeof window.selectObj === 'function') { + window.selectObj(idx); + } +}); +$("#exceed").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + objs[idx - 1].exceed = true; + } else { + objs[idx - 1].exceed = false; + } + window.recordState(); +}); +$("#autoWrap").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + + objs[idx - 1].autoWrap = true; + } else { + objs[idx - 1].autoWrap = false; + } + window.recordState(); +}); +$("#fixSize").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + + objs[idx - 1].fixSize = true; + } else { + objs[idx - 1].fixSize = false; + } + window.recordState(); +}); +$("#circle_text_center").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + objs[idx - 1].circleCenter = 1; + } else { + objs[idx - 1].circleCenter = 0; + } + window.recordState(); +}); + +// =========================================================== +$("#text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选,恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_underline").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("underline", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("underline", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#text_linethrough").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("linethrough", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("linethrough", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); + +$("#circle_text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选,恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); + +$('#out_left_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_left_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'left') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'left' + window.recordState(); + canvas.renderAll() +}) +$('#out_right_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_right_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'right') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'right' + window.recordState(); + canvas.renderAll() +}) +$('#out_center_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_center_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'center') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'center' + window.recordState(); + canvas.renderAll() +}) + +$("#out_text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选,恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_underline").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("underline", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("underline", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_linethrough").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("linethrough", false) + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("linethrough", true) + $(this).addClass("ui-radio-acitve") + } + window.recordState(); + canvas.renderAll(); + window.recordState(); +}); + +// =========================================================== +$("#delete").click(function () { + let actObjs = canvas.getActiveObjects(); + let allObjs = canvas.getObjects(); + let flag = 0; + for (let item of actObjs) { + if (item != allObjs[0]) { + let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 + objs.splice(i - 1, 1); + canvas.remove(item); + flag = 1; + + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + canvas.discardActiveObject(); + if (flag == 1) { + window.recordState(); + canvas.renderAll(); + } +}); +$("#up_obj").click(function () {//上移,放到前面 数组中在后面 + let idx = getIndex(canvas.getActiveObject()); + if (idx + 1 != canvas.getObjects().length) { + canvas.bringForward(canvas.getActiveObject()); + canvas.renderAll(); + let temp = objs[idx - 1]; + objs[idx - 1] = objs[idx]; + objs[idx] = temp; + //console.log(objs); + + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx); + } + } +}); +$("#down_obj").click(function () {//下移,放到后面 数组中在前面 + let idx = getIndex(canvas.getActiveObject()); + if (idx != 1) { + canvas.sendBackwards(canvas.getActiveObject()); + canvas.renderAll(); + //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; + + let temp = objs[idx - 1]; + objs[idx - 1] = objs[idx - 2]; + objs[idx - 2] = temp; + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx - 2); + } + } +}); +$("#set_bg").click(function () {//设置为背景 + let obj = canvas.getActiveObject(); + console.log(obj, obj.get("selectable")) + let idx = getIndex(obj); + const scaleX = 2787 / obj.width + const scaleY = 2787 / obj.height + // 使用缩放后的实际尺寸计算位置,确保与初始背景图片位置一致 + const scaledWidth = obj.width * scaleX; + const scaledHeight = obj.height * scaleY; + obj.set({ + scaleX: scaleX, + scaleY: scaleY, + left: ($('#canvas1').width() - scaledWidth) / 2, + top: ($('#canvas1').height() - scaledHeight) / 2, + }); + $('#text_w').val(2787) + $('#text_h').val(2787) + $('#text_x').val(0) + $('#text_y').val(0) + // 设为背景时,锁定所有编辑操作,并设置为不可选中 + obj.set({ + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockSkewingX: true, + lockSkewingY: true, + selectable: false, + evented: false + }); + $("#lock_img").attr("src", "public/images/lock20.png") + canvas.sendToBack(obj); + canvas.bringForward(obj); + canvas.renderAll(); + let objItem = objs.splice(idx - 1, 1)[0] + objs.unshift(objItem) + + // 确保背景图(索引0)的锁定属性被正确设置 + setTimeout(() => { + let bgObj = canvas.getObjects()[0]; + if (bgObj) { + bgObj.set({ + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockSkewingX: true, + lockSkewingY: true, + selectable: false, + evented: false + }); + canvas.renderAll(); + } + }, 100); + + window.recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(0); + } +}); +// 重复的lock点击事件已移除,使用第一处的绑定 +$("#text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#circle_text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#out_text_back_transparent").click(function () { + canvas.getActiveObject().set("textBackgroundColor", ""); + $("#out_text_back_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#rect_transparent").click(function () { + canvas.getActiveObject().set("fill", ""); + $("#rect_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#rect_stroke_transparent").click(function () { + canvas.getActiveObject().set("stroke", ""); + $("#rect_stroke").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_transparent").click(function () { + canvas.getActiveObject().set("fill", ""); + $("#circle_color").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); +$("#circle_stroke_transparent").click(function () { + canvas.getActiveObject().set("stroke", ""); + $("#circle_stroke").val("#ffffff"); + canvas.renderAll(); + window.recordState(); +}); + +// =========================================================== +$("#about").click(async function () { + // 1. 先异步获取版本号 + let version = "0.0.0"; // 默认值,防止获取失败 + try { + if (window.sysAPI && window.sysAPI.getAppVersion) { + const v = await window.sysAPI.getAppVersion(); + version = "v" + v; // 拼接一个 v,变成 v2.3.017 + } + } catch (e) { + console.error("获取版本号失败", e); + } + + // 2. 获取成功后再弹出窗口 + layer.open({ + type: 1 + , title: language_str("about") + , area: '450px;' + , id: 'LAY_layuipro' + , moveType: 1 + , content: '
' + + '
' + + '
Soon Design
' + + // 【修改点】这里使用了刚才获取到的 version 变量 + '
' + language_str("vers") + ' ' + version + '
' + + '
' + language_str("copyright") + '
' + + '
' + }); +}) +$("#help").click(() => { + ipcRenderer.send('open-help-file'); +}); + +// =========================================================== +$('#display').on('click', function () { + // 类型改变 + fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_1.png', function (i1) { + i1.left = background_image.left; + i1.top = background_image.top; + let img1 = i1; + + fabric.Image.fromURL('./public/images/back_bg_1.png', function (i2) { + i2.left = background_image.left; + i2.top = background_image.top; + let img2 = i2; + fabric.Image.fromURL('./public/images/op_1.png', function (i3) { + i3.left = background_image.left; + i3.top = background_image.top; + let img3 = i3; + if (typeof window.display_func === 'function') { + window.display_func(img1, img2, img3); + } + }) + }) + }) +}); +$("#output").click(function () { + // 另存为:传递 saveAs 函数作为第二个参数 + if (typeof window.output === 'function') { + window.output(null, saveAs); // 调用output函数,使用saveAs进行另存为 + } +}); diff --git a/lib/design2.js b/lib/design2.js index d6615fd..fad71b9 100644 --- a/lib/design2.js +++ b/lib/design2.js @@ -38,17 +38,67 @@ ipcRenderer.send('get-scale-rate'); var $ = layui.$; var layer = layui.layer; 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; // 历史记录文件路径(供 output.js 使用) 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) + // 注意:所有函数都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 // ========================================== // DES加密函数 - function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") { + window.desEncrypt = function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") { var APIFMS; try { var keyHex_encrypt = CryptoJS.enc.Utf8.parse(key); @@ -62,20 +112,28 @@ ipcRenderer.send('get-scale-rate'); console.log(err); } 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) { $(this).html($(this).attr(lan)); }); $("[language='t']").each(function (i) { $(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 = { "whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" }, "save": { zh: "保存", ozh: "保存", en: "Save" }, @@ -103,37 +161,64 @@ ipcRenderer.send('get-scale-rate'); "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." } }; - 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参数 - function GetFile() { + window.GetFile = function GetFile() { const params = new URLSearchParams(window.location.search); return params; + }; + // 向后兼容 + function GetFile() { + return window.GetFile(); } // 日期格式化 - function getDate() { + window.getDate = function getDate() { let date = new Date(); 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"); 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 dy = Math.abs(y2 - y1); var distance = Math.sqrt(dx * dx + dy * dy); 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 centerY = canvas.height / 2; var mouseX = pointer.x; @@ -147,10 +232,14 @@ ipcRenderer.send('get-scale-rate'); } angleDeg += 90; 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) { if (item.name == name) { return false; @@ -162,20 +251,28 @@ ipcRenderer.send('get-scale-rate'); } } 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; do { num++; } - while (!checkName(pre_name + num, objs1, objs2)); + while (!window.checkName(pre_name + num, objs1, objs2)); 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; if (_canvas == null) { temp_objs = canvas.getObjects(); @@ -190,10 +287,14 @@ ipcRenderer.send('get-scale-rate'); i++; } 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 i = 0; for (let res of temp_objs) { @@ -202,10 +303,14 @@ ipcRenderer.send('get-scale-rate'); } i++; } + }; + // 向后兼容 + function getType(target, canvas, objs) { + return window.getType(target, canvas, objs); } // 获取坐标的最小X值 - function getCoordsMinX(acoords) { + window.getCoordsMinX = function getCoordsMinX(acoords) { let x = acoords[0].x; for (let item of acoords) { if (item.x < x) { @@ -213,10 +318,14 @@ ipcRenderer.send('get-scale-rate'); } } return x; + }; + // 向后兼容 + function getCoordsMinX(acoords) { + return window.getCoordsMinX(acoords); } // 获取坐标的最大X值 - function getCoordsMaxX(acoords) { + window.getCoordsMaxX = function getCoordsMaxX(acoords) { let x = acoords[0].x; for (let item of acoords) { if (item.x > x) { @@ -224,10 +333,14 @@ ipcRenderer.send('get-scale-rate'); } } return x; + }; + // 向后兼容 + function getCoordsMaxX(acoords) { + return window.getCoordsMaxX(acoords); } // 获取坐标的最小Y值 - function getCoordsMinY(acoords) { + window.getCoordsMinY = function getCoordsMinY(acoords) { let y = acoords[0].y; for (let item of acoords) { if (item.y < y) { @@ -235,10 +348,14 @@ ipcRenderer.send('get-scale-rate'); } } return y; + }; + // 向后兼容 + function getCoordsMinY(acoords) { + return window.getCoordsMinY(acoords); } // 获取坐标的最大Y值 - function getCoordsMaxY(acoords) { + window.getCoordsMaxY = function getCoordsMaxY(acoords) { let y = acoords[0].y; for (let item of acoords) { if (item.y > y) { @@ -246,26 +363,37 @@ ipcRenderer.send('get-scale-rate'); } } return y; + }; + // 向后兼容 + function getCoordsMaxY(acoords) { + return window.getCoordsMaxY(acoords); } // ========================================== // 全局变量定义(所有模块共享) + // 注意:所有变量都附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 // ========================================== - const dpi = 300; // design2使用300 DPI - let addState = 0; // 0是不添加 - let background_image, background_image1, background_image2; - let bg_version = 1; - var zoom = 0; - let pre_add_image; // 预添加的图片对象(用于addPic) + window.dpi = 300; // design2使用300 DPI + // 确保 dpi 在 global 作用域中也可用(用于 .jsc 文件加载) + if (typeof global !== 'undefined') { + global.dpi = window.dpi; + } + 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, offset: 10 // 粘贴位置偏移量 }; // 文件管理 - var openAs = { + window.openAs = { _name: "", set name(val) { if (val == "") { @@ -281,46 +409,142 @@ ipcRenderer.send('get-scale-rate'); }; // 对象数组和历史记录 - let objs1 = []; - let objs2 = []; - let step1 = { val: 0 }, step2 = { val: 0 }; - let step = step1; - let objs = objs1; - let recordJson1 = [], recordJson2 = [], recordJson = recordJson1, recordObjs1 = [], recordObjs2 = [], recordObjs = recordObjs1; - let pre_objs1 = [], pre_objs2 = [], next_objs1 = [], next_objs2 = [], pre_objs = pre_objs1, next_objs = next_objs1; - let pre_json1 = [], pre_json2 = [], next_json1 = [], next_json2 = [], pre_json = pre_json1, next_json = next_json1; + window.objs1 = []; + window.objs2 = []; + window.step1 = { val: 0 }; + window.step2 = { val: 0 }; + window.step = window.step1; + window.objs = window.objs1; + window.recordJson1 = []; + 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中初始化) - var canvas1, canvas2; - var canvas; // 当前活动的画布(canvas1 或 canvas2) - var ctx1, ctx2; - let is_bgi_add = false; + window.canvas1 = undefined; + window.canvas2 = undefined; + window.canvas = undefined; // 当前活动的画布(canvas1 或 canvas2) + 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模块 - // 由于模块代码需要在layui.use内部执行,我们通过动态加载的方式 const fs = require('fs'); - - // 加载core.js(核心功能) - try { - const coreCode = fs.readFileSync(__dirname + '/design2/core.js', 'utf8'); - eval(coreCode); - } catch (e) { - console.error('加载core.js失败:', e); + let bytenode; + try { + bytenode = require('bytenode'); + require.extensions['.dl'] = require.extensions['.jsc']; + } catch(e) { + console.warn('[加载模块] bytenode 未安装,无法加载 .jsc 文件'); } - // 加载ui.js(UI控制) + const appPath = (() => { try { return remote.app.getAppPath(); } catch(e) { return __dirname || process.cwd(); } })(); + + // 读取模块映射配置 + let moduleMap = {}; try { - const uiCode = fs.readFileSync(__dirname + '/design2/ui.js', 'utf8'); - eval(uiCode); + const moduleMapPath = path.join(appPath, 'lib', 'module-map.json'); + if (fs.existsSync(moduleMapPath)) { + moduleMap = JSON.parse(fs.readFileSync(moduleMapPath, 'utf8')); + } } catch (e) { - console.error('加载ui.js失败:', e); + console.warn('[加载模块] 无法读取模块映射配置,使用默认文件名'); } - // 加载output.js(输出功能) - try { - const outputCode = fs.readFileSync(__dirname + '/design2/output.js', 'utf8'); - eval(outputCode); + // 获取映射后的文件名(跨平台兼容) + function getMappedFileName(moduleName) { + if (moduleMap.mappings && moduleMap.mappings.design2 && moduleMap.mappings.design2[moduleName]) { + 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) { - 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'); }); diff --git a/lib/design2/core.js b/lib/design2/core.js index 501f90a..bd9f730 100644 --- a/lib/design2/core.js +++ b/lib/design2/core.js @@ -29,10 +29,17 @@ try { canvas1 = new fabric.Canvas('canvas1') canvas2 = new fabric.Canvas('canvas2') +// 同步到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.canvas1 = canvas1; +window.canvas2 = canvas2; fabric.Object.prototype.objectCaching = false ctx1 = canvas1.getSelectionContext() ctx2 = canvas2.getSelectionContext() is_bgi_add = false +// 同步到 window 对象 +window.ctx1 = ctx1; +window.ctx2 = ctx2; +window.is_bgi_add = is_bgi_add; canvas1.zoomToPoint(new fabric.Point(canvas1.width / 2, canvas1.height / 2), $('#canvas-div').width() / 1200 > 1 ? 1 : $('#canvas-div').width() / 1200) //console.log(canvas1.width / 2, canvas1.height / 2); //console.log($("#canvas-div").width() / 1200 > 1 ? 1 : $("#canvas-div").width() / 1200); @@ -497,6 +504,7 @@ $('#source_front').width(zoom * $('#source_front').width()) $('#source_back').width(zoom * $('#source_back').width()) $('.canvas-container:eq(1)').hide() canvas = canvas1 +window.canvas = canvas fabric.Object.prototype.set({ borderColor: '#9013FE', cornerColor: '#9013FE', //激活状态角落图标的填充颜色 @@ -517,18 +525,27 @@ canvas2.preserveObjectStacking = true // ========================================== // 对象选择和属性更新函数 // ========================================== -function updateControls() { - if (!canvas.getActiveObject()) return; - $("#text_r").val(canvas.getActiveObject().get("angle").toFixed(0)); - $("#text_x").val((canvas.getActiveObject().get("left") - background_image.left).toFixed(0)); - $("#text_y").val((canvas.getActiveObject().get("top") - background_image.top).toFixed(0)); - $("#text_h").val((canvas.getActiveObject().get("scaleY") * canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("scaleX") * canvas.getActiveObject().get("width")).toFixed(0)); - if (canvas.getActiveObject().get("selectable")) { - $("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解锁 +// 将 updateControls 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.updateControls = function updateControls() { + // 使用 window.canvas 和 window.background_image 作为后备,确保在 eval() 执行时也能访问 + const currentCanvas = window.canvas || canvas; + const currentBackgroundImage = window.background_image || background_image; + if (!currentCanvas || !currentCanvas.getActiveObject()) return; + $("#text_r").val(currentCanvas.getActiveObject().get("angle").toFixed(0)); + $("#text_x").val((currentCanvas.getActiveObject().get("left") - currentBackgroundImage.left).toFixed(0)); + $("#text_y").val((currentCanvas.getActiveObject().get("top") - currentBackgroundImage.top).toFixed(0)); + $("#text_h").val((currentCanvas.getActiveObject().get("scaleY") * currentCanvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((currentCanvas.getActiveObject().get("scaleX") * currentCanvas.getActiveObject().get("width")).toFixed(0)); + // 根据锁定状态显示图标(使用lockMovementX判断,因为锁定时会设置所有lock属性) + if (currentCanvas.getActiveObject().get("lockMovementX")) { + $("#lock_img").attr("src", "public/images/lock20.png")//已锁定 } else { - $("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁 + $("#lock_img").attr("src", "public/images/unlock20.png")//未锁定 } +}; +// 向后兼容 +function updateControls() { + return window.updateControls(); } function selectObject(target, index) { updateControls(); @@ -536,10 +553,25 @@ function selectObject(target, index) { } function selectPic(target, index) { + // 检查是否有选中对象,如果没有则直接返回 + if (!canvas || !canvas.getActiveObject()) return; + $("#pic_control").show(); $("#set_bg").show(); let activeObj = canvas.getActiveObject(); - if (typeof pic_op !== 'undefined' && pic_op.setValue) { + + // 检查对象是否被锁定或设为背景(索引0且已锁定) + let idx = getIndex(activeObj, canvas); + if (idx === 0) { + // 如果是背景图且已锁定,不应该显示图片控件 + if (activeObj.get('lockMovementX') === true || activeObj.get('selectable') === false) { + canvas.discardActiveObject(); + canvas.renderAll(); + return; + } + } + + if (typeof pic_op !== 'undefined' && pic_op && typeof pic_op.setValue === 'function') { pic_op.setValue(100 - (activeObj.get("opacity") * 100)); } else { $("#pic_op").next().children(".layui-slider-bar").css("width", (1 - activeObj.get("opacity")) * 100 + "%"); @@ -878,6 +910,8 @@ function handleObjectSelected(e) { if (currentCanvas === canvas1 || currentCanvas === canvas2) { canvas = currentCanvas; objs = (currentCanvas === canvas1) ? objs1 : objs2; + window.canvas = canvas; + window.objs = objs; } let select_obj = canvas.getActiveObject(); @@ -897,6 +931,19 @@ function handleObjectSelected(e) { // 3. 获取索引 let i = getIndex(select_obj, canvas); + + // 检查对象是否被锁定或设为背景(索引0且已锁定) + if (i === 0) { + if (select_obj.get('lockMovementX') === true || select_obj.get('selectable') === false) { + // 如果是背景图且已锁定,取消选中 + canvas.discardActiveObject(); + canvas.renderAll(); + $("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide(); + $("#component_type").text(language_str("bg")); + selectObj(-1, true); + return; + } + } if (i != 0) { // --- 选中了普通对象 --- @@ -979,9 +1026,20 @@ function handleObjectMoving(e) { updateControls(); } -function initCanvasEvents() { - [canvas1, canvas2].forEach(currentCanvas => { +// 将 handleObjectSelected 附加到 window 对象,确保全局可访问 +window.handleObjectSelected = handleObjectSelected; +// 防止重复初始化事件监听器 +var _canvasEventsInitialized = false; + +function initCanvasEvents() { + // 如果已经初始化过,直接返回 + if (_canvasEventsInitialized) { + return; + } + _canvasEventsInitialized = true; + + [canvas1, canvas2].forEach(currentCanvas => { // 1. 鼠标移动 currentCanvas.on("mouse:move", (e) => { let offsetX = 0, offsetY = 0; @@ -1043,11 +1101,39 @@ function initCanvasEvents() { currentCanvas.on('object:selected', (e) => { canvas = currentCanvas; objs = (currentCanvas === canvas1) ? objs1 : objs2; + + // 阻止背景图(索引0)被选中(如果已锁定) + let selectedObj = e.target; + let idx = getIndex(selectedObj, currentCanvas); + if (idx === 0) { + let bgObj = currentCanvas.getObjects()[0]; + if (bgObj && (bgObj.get('lockMovementX') === true || bgObj.get('selectable') === false)) { + currentCanvas.discardActiveObject(); + currentCanvas.renderAll(); + return; + } + } + handleObjectSelected(e); + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } }); // 5. 对象移动 currentCanvas.on("object:moving", (e) => { + // 阻止背景图(索引0)被移动(如果已锁定) + let movingObj = e.target; + let idx = getIndex(movingObj, currentCanvas); + if (idx === 0) { + let bgObj = currentCanvas.getObjects()[0]; + if (bgObj && bgObj.get('lockMovementX') === true) { + e.e.preventDefault(); + e.e.stopPropagation(); + return false; + } + } handleObjectMoving(e); }); @@ -1091,11 +1177,16 @@ function initCanvasEvents() { updateControls(); } recordState(); + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } }); }); } -function updateList() { +// 将 updateList 附加到 window 对象,确保全局可访问 +window.updateList = function updateList() { let str = ""; let i = 0; @@ -1130,11 +1221,25 @@ function updateList() { (item.type === 3 ? "TEXT_" + displayIndex : (item.type === 1 ? "IMG_" + displayIndex : "OBJ_" + displayIndex)); + // 检查锁定状态(通过lockMovementX判断,因为锁定时会设置所有lock属性) + // 注意:索引0是背景图,objs数组是从下标0开始存第1个对象的,所以是 i+1 + let isLocked = false; + if (canvas.getObjects()[i + 1]) { + let canvasObj = canvas.getObjects()[i + 1]; + isLocked = canvasObj.get('lockMovementX') === true; + } + + // 锁定状态图标 + const lockIcon = isLocked ? + '' : + ''; + // 组装 HTML str = `
${nameText} + ${lockIcon}
${displayIndex}
` + str; @@ -1152,7 +1257,8 @@ function updateList() { }); } -function selectObj(objIndices, isFromCanvas = false) { +// 将 selectObj 附加到 window 对象,确保全局可访问 +window.selectObj = function selectObj(objIndices, isFromCanvas = false) { let indicesArray = (Array.isArray(objIndices)) ? objIndices : ((typeof objIndices === 'number' && objIndices >= 0) ? [objIndices] : []); // 清除所有高亮 @@ -1186,25 +1292,39 @@ function selectObj(objIndices, isFromCanvas = false) { } } -function recordState() { - ++step.val; - for (let i = step.val; i < recordObjs.length; i++) { - recordObjs.pop(); - recordJson.pop(); +// 将 recordState 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.recordState = function recordState() { + // 使用 window 变量作为后备,确保在 eval() 执行时也能访问 + const currentStep = window.step || step; + const currentRecordObjs = window.recordObjs || recordObjs; + const currentRecordJson = window.recordJson || recordJson; + const currentObjs = window.objs || objs; + const currentCanvas = window.canvas || canvas; + ++currentStep.val; + for (let i = currentStep.val; i < currentRecordObjs.length; i++) { + currentRecordObjs.pop(); + currentRecordJson.pop(); } - recordObjs.push(JSON.stringify(objs)) - j = canvas.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); + currentRecordObjs.push(JSON.stringify(currentObjs)) + let j = currentCanvas.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]); j.objects[0].hoverCursor = "default"; - recordJson.push(j); + currentRecordJson.push(j); +}; +// 向后兼容 +function recordState() { + return window.recordState(); } -function getIndex(target, _canvas = null) { +// 将 getIndex 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问 +window.getIndex = function getIndex(target, _canvas = null) { let temp_objs; - if (_canvas == null) { - temp_objs = canvas.getObjects(); - } else { - temp_objs = _canvas.getObjects(); + // 使用 window.canvas 作为默认值,确保在 eval() 执行时也能访问 + const currentCanvas = _canvas || window.canvas || canvas; + if (!currentCanvas) { + console.error('getIndex: canvas is undefined'); + return 0; } + temp_objs = currentCanvas.getObjects(); let i = 0; for (let res of temp_objs) { @@ -1214,6 +1334,10 @@ function getIndex(target, _canvas = null) { i++; } return 0; +}; +// 向后兼容 +function getIndex(target, _canvas = null) { + return window.getIndex(target, _canvas); } function getType(target) { @@ -1339,6 +1463,8 @@ function addBackground() { image.setSrc(image.toDataURL(), function (image) { background_image1 = image background_image = background_image1 + window.background_image1 = background_image1; + window.background_image = background_image; canvas1.add(image) canvas1.renderAll() @@ -1356,6 +1482,7 @@ function addBackground() { image.setSrc(image.toDataURL(), function (image) { background_image2 = image + window.background_image2 = background_image2; canvas2.add(image) canvas2.renderAll() @@ -1364,7 +1491,7 @@ function addBackground() { let file = GetFile().get('file') if (file && file != 'empty') { - open(file) + window.openFile(file); } }) }) @@ -1603,6 +1730,13 @@ ipcRenderer.on('sys-lan', (event, data) => { let lang = localStorage.getItem('lang') if (lang) { s_lan = lang + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge(lang) $('#language_select').val(lang) return @@ -1610,60 +1744,130 @@ ipcRenderer.on('sys-lan', (event, data) => { switch (data) { case 'zh-CN': s_lan = 'zh' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('zh') $('#language_select').val('zh') localStorage.setItem('lang', 'zh') break case 'zh': s_lan = 'zh' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('zh') $('#language_select').val('zh') localStorage.setItem('lang', 'zh') break case 'zh-TW': s_lan = 'ozh' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('ozh') $('#language_select').val('ozh') localStorage.setItem('lang', 'ozh') break case 'en': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-AU': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-CA': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-GB': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-NZ': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-US': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') break case 'en-ZA': s_lan = 'en' + // 同步到全局作用域(用于 .jsc 文件加载) + if (typeof window !== 'undefined') { + window.s_lan = s_lan; + } + if (typeof global !== 'undefined') { + global.s_lan = s_lan; + } langua_ge('en') $('#language_select').val('en') localStorage.setItem('lang', 'en') @@ -1679,7 +1883,9 @@ ipcRenderer.on('close', (event, message) => { btn3: function (index, layero) { } }, function (index, layero) { - output(() => ipcRenderer.send('run-close')) + if (typeof window.output === 'function') { + window.output(() => ipcRenderer.send('run-close')); + } }, function (index) { ipcRenderer.send('run-close') @@ -1811,28 +2017,10 @@ window.rotate = function (id) { $(`#${id}`).css('transform', `rotate(${angle}deg)`) $(`#${id}`).attr('angle', angle) } -$('#display').on('click', function () { - // 类型改变 - fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_2.png', function (i1) { - i1.left = background_image.left - i1.top = background_image.top - let img1 = i1 - - fabric.Image.fromURL('./public/images/back_bg_2.png', function (i2) { - i2.left = background_image.left - i2.top = background_image.top - let img2 = i2 - fabric.Image.fromURL('./public/images/op_2.png', function (i3) { - i2.left = background_image.left - i2.top = background_image.top - let img3 = i3 - display_func(img1, img2, img3) - }) - }) - }) -}) +// 注意:#display 事件绑定已在 ui.js 中定义(第2633行),此处已删除重复定义 // 导出文件 -async function savePdf(buffer) { +// 将 savePdf 附加到 window 对象,确保在 output.js 中也能访问 +window.savePdf = async function savePdf(buffer) { let fs = require('fs'); // 弹出保存对话框 const { canceled, filePath } = await dialog.showSaveDialog({ @@ -1846,918 +2034,27 @@ async function savePdf(buffer) { return; } - // 将Buffer写入PNG文件到用户选择的路径 + // 将Buffer写入PDF文件到用户选择的路径 fs.writeFile(filePath, buffer, (err) => { if (err) { console.error('写入文件失败:', err); } else { layer.msg(language_str("saveSucc") + filePath);//'保存成功至' - console.log('PNG文件已保存至:', filePath); + console.log('PDF文件已保存至:', filePath); } }); +}; +// 向后兼容 +async function savePdf(buffer) { + return window.savePdf(buffer); } -function display_func(img1, img2, img3) { - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $('#circle_text_control').hide() - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) //"背景" - canvas1.discardActiveObject().renderAll() - canvas2.discardActiveObject().renderAll() - // 过滤掉辅助线 - let _objs1 = canvas1.getObjects().filter(obj => !obj.isGuideLine) - let g1 = [] - let g3 = [] - let g5 = [] - let left = 0 //左裁剪 - let top = 0 //顶裁剪 - let black_left = 0 //黑色左裁剪 - let black_top = 0 //黑色顶裁剪 - let all_left = 0 //预览图左裁剪 - let all_top = 0 //预览图顶裁剪 - for (let item of _objs1) { - let idx = getIndex(item, canvas1) - - // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 - if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { - continue - } - - //console.log("------"); - //console.log(item.getCoords()); - //console.log(getCoordsMinX(background_image.getCoords())); - //console.log(getCoordsMinX(item.getCoords())); - //console.log(getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords())); - //console.log("------"); - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g3.push(fabric.util.object.clone(item)) - - if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) { - continue //计数器 或 合成文字 - } - if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) { - continue //二维码 条形码 - } - if (idx != 0 && objs1[idx - 1].type == 2) { - continue //合成图片 - } - if ( - idx != 0 && - ((objs1[idx - 1].type == 3 && (item.get('fill') == '#000000' || (item.get('fill') == '#ffffff' && false))) || - ( - objs1[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) || - //文字 && 黑色 - (objs1[idx - 1].type == 5 && //矩形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs1[idx - 1].type == 6 && //圆形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs1[idx - 1].type == 7 && //直线 - (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || - objs1[idx - 1].black == true) //勾选并入黑色图层 - // ( - // objs1[idx-1].type == 1//固定图片 - // && - // objs1[idx-1].black == true //勾选并入黑色图层 - // ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g5.push(fabric.util.object.clone(item)) - continue //黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g5.push(fabric.util.object.clone(item)) - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g1.push(fabric.util.object.clone(item)) - } - let url1 = new fabric.Group(g1).toDataURL({ - height: 648, - width: 1012, - top: top / zoom, - left: left / zoom - }) +// display_func 函数已移至 output.js,避免重复定义 +// function display_func(img1, img2, img3) { ... } - // g3.push(img1) - let url3 = new fabric.Group(g3).toDataURL({ - height: 648, - width: 1012, - top: all_top / zoom, - left: all_left / zoom - }) - let url5 = new fabric.Group(g5).toDataURL({ - height: 648, - width: 1012, - top: black_top / zoom, - left: black_left / zoom - }) - // 过滤掉辅助线 - let _objs2 = canvas2.getObjects().filter(obj => !obj.isGuideLine) - let g2 = [] - let g4 = [] - let g6 = [] - left = 0 - top = 0 - black_top = 0 - black_left = 0 - all_top = 0 - all_left = 0 - for (let item of _objs2) { - let idx = getIndex(item, canvas2) - - // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 - if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { - continue - } - - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g4.push(fabric.util.object.clone(item)) - - if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) { - continue //黑色字或计数器 或 合成文字 - } - if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) { - continue //二维码 条形码 - } - if (idx != 0 && objs2[idx - 1].type == 2) { - continue //合成图片 - } - if (idx != 0 && objs2[idx - 1].type == 10) { - continue //合成图片 - } - if ( - idx != 0 && - ((objs2[idx - 1].type == 3 && (item.get('fill') == '#000000' || (item.get('fill') == '#ffffff' && false))) || - ( - objs2[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) || - //文字 && 黑色 - (objs2[idx - 1].type == 5 && //矩形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs2[idx - 1].type == 6 && //圆形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs2[idx - 1].type == 7 && //直线 - (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || - objs2[idx - 1].black == true) //勾选并入黑色图层 - // ( - // objs2[idx-1].type == 1//固定图片 - // && - // objs2[idx-1].black == true //勾选并入黑色图层 - // ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g6.push(fabric.util.object.clone(item)) - continue //黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g6.push(fabric.util.object.clone(item)) - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g2.push(fabric.util.object.clone(item)) - } - let url2 = new fabric.Group(g2).toDataURL({ - height: 648, - width: 1012, - top: top / zoom, - left: left / zoom - }) - let white_url1 = canvas1.getObjects()[0].toDataURL({ - height: 648, - width: 1012 - }) - // g4.push(img2) - let url4 = new fabric.Group(g4).toDataURL({ - height: 648, - width: 1012, - top: all_top / zoom, - left: all_left / zoom - }) - let url6 = new fabric.Group(g6).toDataURL({ - height: 648, - width: 1012, - top: black_top / zoom, - left: black_left / zoom - }) - let white_url2 = canvas2.getObjects()[0].toDataURL({ - height: 648, - width: 1012 - }) - //console.log(canvas.getObjects()) - let w = document.body.clientWidth * 0.7 + 'px' - let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + 'px' - let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 'px' +// output 函数已移至 output.js,避免重复定义 +// function output(callback = null, _save = save) { ... } - if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) { - //高度超出,则按高度计算 - h = document.body.clientHeight * 0.8 + 'px' - h1 = document.body.clientHeight * 0.8 - 150 + 'px' - w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94 - } - let fs = require('fs'); - const Buffer = require('buffer').Buffer; - const buffer3 = Buffer.from(url3.replace(/^data:image\/\w+;base64,/, ""), 'base64'); - const printPath3 = path.join(exePath, 'print3.png'); - fs.writeFileSync(printPath3, buffer3); - const buffer4 = Buffer.from(url4.replace(/^data:image\/\w+;base64,/, ""), 'base64'); - const printPath4 = path.join(exePath, 'print4.png'); - fs.writeFileSync(printPath4, buffer4); - // 创建 PDF 实例 - const pdf = new jspdf.jsPDF({ - orientation: 'landscape', - unit: 'px', - format: [1012, 648] - }); - let btns = [language_str('output')] - if ((objs1.length != 0) & (objs2.length == 0)) { - //只有正面 - let img = new Image() - img.src = printPath3 - - pdf.addImage(img, 'JPEG', 0, 0, 1012, 648) - btns.push('打印正面') - } else if ((objs1.length == 0) & (objs2.length != 0)) { - //只有背面 - let img = new Image() - img.src = printPath4 - - pdf.addImage(img, 'JPEG', 0, 0, 1012, 648) - btns.push('打印背面') - } else { - let img = new Image() - img.src = printPath3 - - pdf.addImage(img, 'JPEG', 0, 0, 1012, 648) - - pdf.addPage() - let img2 = new Image() - img2.src = printPath4 - pdf.addImage(img2, 'JPEG', 0, 0, 1012, 648) - btns.push('打印正面') - btns.push('打印背面') - } - - var pdfBlob = pdf.output('blob') - var pdfBuffer = pdf.output('arraybuffer') - - layer.open({ - type: 1, - area: [w, h], - title: language_str('display'), //不显示标题栏"预览" - shadeClose: true, //点击遮罩关闭 - content: ` -
-
-
- -
- -
-
-
- -
- -
-
-
-
`, - btn: btns, //'导出' - btn1: function (index, layero) { - savePdf(Buffer.from(pdfBuffer)) - }, - btn2: function () { - if (btns[1] === '打印正面') { - printJS({ printable: printPath3, type: 'image', style: 'img { width: 100%; height: auto; }' }) - } else { - printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' }) - } - }, - btn3: function () { - //打印背面 - printJS({ printable: printPath4, type: 'image', style: 'img { width: 100%; height: auto; }' }) - } - }) -} -function output(callback = null, _save = save) { - // 类型改变 - fabric.Image.fromURL('./public/images/op_2.png', function (i1) { - i1.left = background_image.left - i1.top = background_image.top - let img1 = i1 - fabric.Image.fromURL('./public/images/op_2.png', function (i2) { - i2.left = background_image.left - i2.top = background_image.top - let img2 = i2 - - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) //"背景" - canvas1.discardActiveObject().renderAll() - canvas2.discardActiveObject().renderAll() - // 过滤掉辅助线 - let _objs1 = canvas1.getObjects().filter(obj => !obj.isGuideLine) - let g1 = [] - let g3 = [] - let g5 = [] //黑色图层 - let left = 0 //左裁剪 - let top = 0 //顶裁剪 - let black_left = 0 //黑色左裁剪 - let black_top = 0 //黑色顶裁剪 - let all_left = 0 //预览图左裁剪 - let all_top = 0 //预览图顶裁剪 - for (let item of _objs1) { - let idx = getIndex(item, canvas1) - - // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 - if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { - continue - } - //console.log("------"); - //console.log(item.getCoords()); - //console.log(getCoordsMinX(background_image.getCoords())); - //console.log(getCoordsMinX(item.getCoords())); - //console.log(getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords())); - //console.log("------"); - - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g3.push(fabric.util.object.clone(item)) - if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) { - continue //计数器 或 合成文字 - } - if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) { - continue //二维码 条形码 - } - if (idx != 0 && objs1[idx - 1].type == 2) { - continue //合成图片 - } - if ( - idx != 0 && - ((objs1[idx - 1].type == 3 && item.get('fill') == '#000000') || - ( - objs1[idx - 1].type == 11 - && - item.get("fill") == "#000000" - //圆形文字 && 黑色 - ) || - //文字 && 黑色 - (objs1[idx - 1].type == 5 && //矩形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs1[idx - 1].type == 6 && //圆形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs1[idx - 1].type == 7 && //直线 - (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || - objs1[idx - 1].black == true) //勾选并入黑色图层 - // || - // ( - // objs1[idx-1].type == 1//固定图片 - // && - // objs1[idx-1].black == true //勾选并入黑色图层 - // ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g5.push(fabric.util.object.clone(item)) - continue //黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g5.push(fabric.util.object.clone(item)) - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g1.push(fabric.util.object.clone(item)) - } - let url1 = new fabric.Group(g1).toDataURL({ - height: 648, - width: 1012, - top: top / zoom, - left: left / zoom - }) - g3.push(img1) - let url3 = new fabric.Group(g3).toDataURL({ - height: 648, - width: 1012, - top: all_top / zoom, - left: all_left / zoom - }) - let url5 = new fabric.Group(g5).toDataURL({ - height: 648, - width: 1012, - top: black_top / zoom, - left: black_left / zoom - }) - // 过滤掉辅助线 - let _objs2 = canvas2.getObjects().filter(obj => !obj.isGuideLine) - let g2 = [] - let g4 = [] - let g6 = [] //黑色图层 - left = 0 - top = 0 - black_left = 0 //黑色左裁剪 - black_top = 0 //黑色顶裁剪 - all_left = 0 //黑色左裁剪 - all_top = 0 //黑色顶裁剪 - for (let item of _objs2) { - let idx = getIndex(item, canvas2) - - // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 - if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { - continue - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) { - all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) { - all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g4.push(fabric.util.object.clone(item)) - if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) { - continue //计数器 或 合成文字 - } - if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) { - continue //二维码 条形码 - } - if (idx != 0 && objs2[idx - 1].type == 2) { - continue //合成图片 - } - if ( - idx != 0 && - ((objs2[idx - 1].type == 3 && (item.get('fill') == '#000000' || (item.get('fill') == '#ffffff' && false))) || - ( - objs2[idx - 1].type == 11 - && - (item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false)) - //圆形文字 && 黑色 - ) || - //文字 && 黑色 - (objs2[idx - 1].type == 5 && //矩形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs2[idx - 1].type == 6 && //圆形 - (((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('stroke') == '') || //黑填充 透明边框 - (item.get('fill') == '' && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //透明填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || //黑填充 黑边框 - ((item.get('fill') == '#000000' || item.get('fill') == '#ffffff') && item.get('strokeWidth') == 0))) || //黑填充 0边框 - (objs2[idx - 1].type == 7 && //直线 - (item.get('stroke') == '#000000' || item.get('stroke') == '#ffffff')) || - objs2[idx - 1].black == true) //勾选并入黑色图层 - // ( - // objs2[idx-1].type == 1//固定图片 - // && - // objs2[idx-1].black == true //勾选并入黑色图层 - // ) - ) { - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) { - black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) { - black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g6.push(fabric.util.object.clone(item)) - continue //黑色文字 黑色矩形 黑色线条 黑色圆形 - } else if (idx == 0) { - g6.push(fabric.util.object.clone(item)) - } - if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) { - left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords())) - } - if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) { - top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords())) - } - g2.push(fabric.util.object.clone(item)) - } - let url2 = new fabric.Group(g2).toDataURL({ - height: 648, - width: 1012, - top: top / zoom, - left: left / zoom - }) - let white_url1 = canvas1.getObjects()[0].toDataURL({ - height: 648, - width: 1012 - }) - g4.push(img2) - let url4 = new fabric.Group(g4).toDataURL({ - height: 648, - width: 1012, - top: all_top / zoom, - left: all_left / zoom - }) - let url6 = new fabric.Group(g6).toDataURL({ - height: 648, - width: 1012, - top: black_top / zoom, - left: black_left / zoom - }) - let white_url2 = canvas2.getObjects()[0].toDataURL({ - height: 648, - width: 1012 - }) - //console.log(canvas.getObjects()) - let w = document.body.clientWidth * 0.7 + 'px' - let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + 'px' - let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 'px' - - if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) { - //高度超出,则按高度计算 - h = document.body.clientHeight * 0.8 + 'px' - h1 = document.body.clientHeight * 0.8 - 150 + 'px' - w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94 - } - - let op = { frontColorPic: '', backColorPic: '', frontBlackPic: '', backBlackPic: '', frontData: [], backData: [], flag: 1, frontDisplayPic: url3, backDisplayPic: url4 } - if ((objs1.length != 0) & (objs2.length == 0)) { - op.flag = 2 - } else if ((objs1.length == 0) & (objs2.length != 0)) { - op.flag = 3 - } - op.frontColorPic = desEncrypt(url1) - op.backColorPic = desEncrypt(url2) - //op.frontBlPic = url5; - //op.backBlPic = url6; - op.frontBlackPic = desEncrypt(url5) - op.backBlackPic = desEncrypt(url6) - // 过滤掉辅助线 - let filteredObjs1 = _objs1.filter(obj => !obj.isGuideLine) - for (let item of filteredObjs1) { - let idx = getIndex(item, canvas1) - if (idx == 0) continue //background-image - - // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 - if (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined') { - continue - } - - let type = objs1[idx - 1].type - if (type == 2) { - //out_pic - let xy = getAbsoluteXY(item) - op.frontData.push({ - type: 1, - name: objs1[idx - 1].name, - FontColor: objs1[idx - 1].black ? '#000000' : '@', - transparency: item.get('opacity'), - x: parseInt((xy[0] - background_image1.left).toFixed(0)), - y: parseInt((xy[1] - background_image1.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 3) { - //text - /*2022-07-26 黑色并入黑色图层 - if(item.get("fill") == "#000000"){ - //纯黑 - op.frontData.push({ - "type" : 2, - "Text" : item.get("text"), - "FontFamily" : item.get("fontFamily"), - "FontSize" : parseInt(item.get("fontSize")), - "FontColor" : "#000000", - "FontBackgroudColor" : item.get("textBackgroundColor"), - "Bold" : item.get("fontWeight") == "bold", - "Underline" : item.get("underline"), - "Italic" : item.get("fontStyle") == "italic", - "Strikeout" : item.get("linethrough"), - "x" : parseInt((item.get("left") - background_image1.left).toFixed(0)), - "y" : parseInt((item.get("top") - background_image1.top).toFixed(0)), - "h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate" : parseInt(item.get("angle").toFixed(0)) - }); - } - */ - } else if (type == 11) { - //circle_text - op.frontData.push({ - "type": 2, - "Text": item.get("text"), - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": "#000000", - "FontBackgroudColor": item.get("textBackgroundColor"), - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((item.get("left") - background_image1.left).toFixed(0)), - "y": parseInt((item.get("top") - background_image1.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - "circleCenter": objs1[idx - 1].circleCenter || 0 - }); - } else if (type == 4) { - //out_text - let xy = getAbsoluteXY(item) - op.frontData.push({ - type: 3, - name: objs1[idx - 1].name, - FontFamily: item.get('fontFamily'), - DefaultText: item.get('text'), - FontBackgroudColor: item.get('textBackgroundColor'), - FontSize: parseInt(item.get('fontSize')), - FontColor: item.get('fill'), - Exceed: objs1[idx - 1].exceed, - AutoWrap: objs1[idx - 1].autoWrap, - FixSize: objs1[idx - 1].fixSize, - Bold: item.get('fontWeight') == 'bold', - Underline: item.get('underline'), - Italic: item.get('fontStyle') == 'italic', - Strikeout: item.get('linethrough'), - x: parseInt((xy[0] - background_image1.left).toFixed(0)), - y: parseInt((xy[1] - background_image1.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)), - align: objs1[idx - 1].align - }) - } else if (type == 8) { - //二维码 - let xy = getAbsoluteXY(item) - op.frontData.push({ - type: 4, - name: objs1[idx - 1].name, - FontColor: objs1[idx - 1].color, - DefaultText: objs1[idx - 1].val, - x: parseInt((xy[0] - background_image1.left).toFixed(0)), - y: parseInt((xy[1] - background_image1.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 9) { - //条形码 - let xy = getAbsoluteXY(item) - op.frontData.push({ - type: 5, - name: objs1[idx - 1].name, - FontSize: parseInt(objs1[idx - 1].fontSize), - DefaultText: objs1[idx - 1].val, - HideText: objs1[idx - 1].show, - FontFamily: objs1[idx - 1].font, - FontColor: objs1[idx - 1].color, - x: parseInt((xy[0] - background_image1.left).toFixed(0)), - y: parseInt((xy[1] - background_image1.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 10) { - let xy = getAbsoluteXY(item) - op.frontData.push({ - type: 6, - name: objs1[idx - 1].name, - FontFamily: item.get('fontFamily'), - FontSize: parseInt(item.get('fontSize')), - FontColor: item.get('fill'), - start: objs1[idx - 1].start, - add: parseInt(objs1[idx - 1].add), - x: parseInt((xy[0] - background_image1.left).toFixed(0)), - y: parseInt((xy[1] - background_image1.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } - } - //obj2 - // 过滤掉辅助线 - let filteredObjs2 = _objs2.filter(obj => !obj.isGuideLine) - for (let item of filteredObjs2) { - let idx = getIndex(item, canvas2) - if (idx == 0) continue //background-image - - // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 - if (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined') { - continue - } - - let type = objs2[idx - 1].type - if (type == 2) { - //out_pic - let xy = getAbsoluteXY(item) - op.backData.push({ - type: 1, - name: objs2[idx - 1].name, - FontColor: objs2[idx - 1].black ? '#000000' : '@', - transparency: item.get('opacity'), - x: parseInt((xy[0] - background_image2.left).toFixed(0)), - y: parseInt((xy[1] - background_image2.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 3) { - //text - /*2022-07-26 黑色并入黑色图层 - if(item.get("fill") == "#000000"){ - //纯黑 - op.backData.push({ - "type" : 2, - "Text" : item.get("text"), - "FontFamily" : item.get("fontFamily"), - "FontSize" : parseInt(item.get("fontSize")), - "FontColor" : "#000000", - "FontBackgroudColor" : item.get("textBackgroundColor"), - "Bold" : item.get("fontWeight") == "bold", - "Underline" : item.get("underline"), - "Italic" : item.get("fontStyle") == "italic", - "Strikeout" : item.get("linethrough"), - "x" : parseInt((item.get("left") - background_image2.left).toFixed(0)), - "y" : parseInt((item.get("top") - background_image2.top).toFixed(0)), - "h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate" : parseInt(item.get("angle").toFixed(0)) - }); - } - */ - } else if (type == 11) { - //circle_text - op.backData.push({ - "type": 2, - "Text": item.get("text"), - "FontFamily": item.get("fontFamily"), - "FontSize": parseInt(item.get("fontSize")), - "FontColor": "#000000", - "FontBackgroudColor": item.get("textBackgroundColor"), - "Bold": item.get("fontWeight") == "bold", - "Underline": item.get("underline"), - "Italic": item.get("fontStyle") == "italic", - "Strikeout": item.get("linethrough"), - "x": parseInt((item.get("left") - background_image2.left).toFixed(0)), - "y": parseInt((item.get("top") - background_image2.top).toFixed(0)), - "h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)), - "w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)), - "rotate": parseInt(item.get("angle").toFixed(0)), - "circleCenter": objs2[idx - 1].circleCenter || 0 - }); - } else if (type == 4) { - let xy = getAbsoluteXY(item) - op.backData.push({ - type: 3, - name: objs2[idx - 1].name, - FontFamily: item.get('fontFamily'), - DefaultText: item.get('text'), - FontSize: parseInt(item.get('fontSize')), - FontBackgroudColor: item.get('textBackgroundColor'), - FontColor: item.get('fill'), - Exceed: objs2[idx - 1].exceed, - AutoWrap: objs2[idx - 1].autoWrap, - FixSize: objs2[idx - 1].fixSize, - Bold: item.get('fontWeight') == 'bold', - Underline: item.get('underline'), - Italic: item.get('fontStyle') == 'italic', - Strikeout: item.get('linethrough'), - x: parseInt((xy[0] - background_image2.left).toFixed(0)), - y: parseInt((xy[1] - background_image2.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)), - align: objs2[idx - 1].align - }) - } else if (type == 8) { - //二维码 - let xy = getAbsoluteXY(item) - op.backData.push({ - type: 4, - name: objs2[idx - 1].name, - FontColor: objs2[idx - 1].color, - DefaultText: objs2[idx - 1].val, - x: parseInt((xy[0] - background_image2.left).toFixed(0)), - y: parseInt((xy[1] - background_image2.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 9) { - let xy = getAbsoluteXY(item) - op.backData.push({ - type: 5, - name: objs2[idx - 1].name, - DefaultText: objs2[idx - 1].val, - HideText: objs1[idx - 1].show, - FontSize: parseInt(objs2[idx - 1].fontSize), - FontFamily: objs2[idx - 1].font, - FontColor: objs2[idx - 1].color, - x: parseInt((xy[0] - background_image2.left).toFixed(0)), - y: parseInt((xy[1] - background_image2.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } else if (type == 10) { - let xy = getAbsoluteXY(item) - op.backData.push({ - type: 6, - name: objs2[idx - 1].name, - FontFamily: item.get('fontFamily'), - FontSize: parseInt(item.get('fontSize')), - FontColor: item.get('fill'), - start: parseInt(objs2[idx - 1].start), - add: parseInt(objs2[idx - 1].add), - x: parseInt((xy[0] - background_image2.left).toFixed(0)), - y: parseInt((xy[1] - background_image2.top).toFixed(0)), - h: parseInt((item.get('scaleY') * item.get('height')).toFixed(0)), - w: parseInt((item.get('scaleX') * item.get('width')).toFixed(0)), - rotate: parseInt(item.get('angle').toFixed(0)) - }) - } - } - _save(op, callback) - //return false 开启该代码可禁止点击该按钮关闭 - }) - }) -} -$('#output').on('click', function () { - output(null, saveAs) -}) var _keyctrl = false, _keyc = false, _textEdit = false, @@ -2810,7 +2107,9 @@ $('body').keydown(function (event) { // CTRL/CMD+SHIFT+S - 保存副本 if (isModifierKey && event.shiftKey && event.keyCode == 83) { event.preventDefault(); - output(null, saveAs); + if (typeof window.output === 'function') { + window.output(null, saveAs); + } return; } // CTRL/CMD+Z - 还原 @@ -2828,13 +2127,13 @@ $('body').keydown(function (event) { // CTRL/CMD+C - 复制 if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { event.preventDefault(); - copySelection(); + window.copySelection(); return; } // CTRL/CMD+V - 粘贴 if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { event.preventDefault(); - pasteFromClipboard(); + window.pasteFromClipboard(); return; } // CTRL/CMD+SHIFT+DEL - 清空 @@ -2951,7 +2250,7 @@ $('body').keydown(function (event) { }) // 复制选中对象 -function copySelection() { +window.copySelection = function copySelection() { const activeObjects = canvas.getActiveObjects(); if (!activeObjects || activeObjects.length === 0) { @@ -2964,7 +2263,7 @@ function copySelection() { } // 粘贴对象 -function pasteFromClipboard() { +window.pasteFromClipboard = function pasteFromClipboard() { if (!clipboardData.objects || clipboardData.objects.length === 0) { layer.msg("剪贴板为空") return; diff --git a/lib/design2/output.js b/lib/design2/output.js index 40116fd..7be7afb 100644 --- a/lib/design2/output.js +++ b/lib/design2/output.js @@ -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() $('#line_control').hide() $('#pic_control').hide() @@ -15,6 +16,27 @@ function display_func(img1, img2, img3) { $('#component_type').text(language_str('bg')) //"背景" canvas1.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 g1 = [] @@ -30,7 +52,7 @@ function display_func(img1, img2, img3) { let list1 = _objs1.filter(obj => !obj.isGuideLine) for (let item of list1) { let idx = getIndex(item, canvas1) - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { continue @@ -114,10 +136,9 @@ function display_func(img1, img2, img3) { }) // g3.push(img1) - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 let url3 = new fabric.Group(g3).toDataURL({ - format: 'png', - multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容 + height: 648, + width: 1012, top: all_top / zoom, left: all_left / zoom }) @@ -142,7 +163,7 @@ function display_func(img1, img2, img3) { let filteredObjs2 = _objs2.filter(obj => !obj.isGuideLine) for (let item of filteredObjs2) { let idx = getIndex(item, canvas2) - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { continue @@ -225,10 +246,9 @@ function display_func(img1, img2, img3) { width: 1012 }) // g4.push(img2) - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 let url4 = new fabric.Group(g4).toDataURL({ - format: 'png', - multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容 + height: 648, + width: 1012, top: all_top / zoom, left: all_left / zoom }) @@ -323,23 +343,53 @@ function display_func(img1, img2, img3) { `, btn: btns, //'导出' 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 () { + // 根据 btns[1] 的值决定打印哪一面 if (btns[1] === '打印正面') { + // 打印正面 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; }' }) } }, btn3: function () { - //打印背面 + // 打印背面(两面都有时,btn3 对应 btns[2] = '打印背面') 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) { i1.left = background_image.left @@ -380,7 +430,7 @@ function output(callback = null, _save = save) { // _objs1 已经在上面过滤过辅助线了,直接使用 for (let item of _objs1) { let idx = getIndex(item, canvas1) - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { continue @@ -464,10 +514,9 @@ function output(callback = null, _save = save) { left: left / zoom }) g3.push(img1) - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 let url3 = new fabric.Group(g3).toDataURL({ - format: 'png', - multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容 + height: 648, + width: 1012, top: all_top / zoom, left: all_left / zoom }) @@ -491,7 +540,7 @@ function output(callback = null, _save = save) { // _objs2 已经在上面过滤过辅助线了,直接使用 for (let item of _objs2) { let idx = getIndex(item, canvas2) - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { continue @@ -571,10 +620,9 @@ function output(callback = null, _save = save) { width: 1012 }) g4.push(img2) - // 预览图缩小尺寸以减小文件大小,使用 multiplier 来缩放整个 Group,保持所有内容完整 let url4 = new fabric.Group(g4).toDataURL({ - format: 'png', - multiplier: 0.6, // 缩小到原来的 60%,保持宽高比和所有内容 + height: 648, + width: 1012, top: all_top / zoom, left: all_left / zoom }) @@ -615,7 +663,7 @@ function output(callback = null, _save = save) { // _objs1 已经在上面过滤过辅助线了,直接使用 for (let item of _objs1) { let idx = getIndex(item, canvas1) - + // 安全检查:确保 objs1[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs1[idx - 1] || typeof objs1[idx - 1].type === 'undefined')) { continue @@ -758,7 +806,7 @@ function output(callback = null, _save = save) { // _objs2 已经在上面过滤过辅助线了,直接使用 for (let item of _objs2) { let idx = getIndex(item, canvas2) - + // 安全检查:确保 objs2[idx - 1] 存在且有 type 属性 if (idx != 0 && (!objs2[idx - 1] || typeof objs2[idx - 1].type === 'undefined')) { continue @@ -902,43 +950,44 @@ 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 - + const objects = canvas.getObjects() - + // 遍历对象(跳过背景图片,索引 0) for (let i = 1; i < objects.length; i++) { const obj = objects[i] if (!obj || obj.type !== 'image') continue - + const objIndex = i - 1 if (objIndex >= objsArray.length) continue - + const objMeta = objsArray[objIndex] if (!objMeta || (objMeta.type !== 8 && objMeta.type !== 9)) continue - + // type == 8: 二维码 - 复用 ui.js 中的生成逻辑 if (objMeta.type === 8) { - const qr = jrQrcode.getQrBase64(objMeta.val || 'https://www.cardsoon.com', { - padding: 0, - foreground: objMeta.color || '#000000' + const qr = jrQrcode.getQrBase64(objMeta.val || 'https://www.cardsoon.com', { + padding: 0, + foreground: objMeta.color || '#000000' }) - obj.setSrc(qr, function(img) { + obj.setSrc(qr, function (img) { canvas.renderAll() }) } // type == 9: 条形码 - 复用 ui.js 中的生成逻辑 else if (objMeta.type === 9) { - JsBarcode("#barcode", objMeta.val || '123456789', { - margin: 0, - lineColor: objMeta.color || '#000000', - fontSize: objMeta.fontSize || 18, - font: objMeta.font || 'Arial' + JsBarcode("#barcode", objMeta.val || '123456789', { + margin: 0, + lineColor: objMeta.color || '#000000', + fontSize: objMeta.fontSize || 18, + font: objMeta.font || 'Arial' }) const barcode = document.getElementById('barcode') const bar = barcode.toDataURL("image/png") - obj.setSrc(bar, function(img) { + obj.setSrc(bar, function (img) { canvas.renderAll() }) } @@ -946,7 +995,8 @@ function regenerateQrCodesAndBarcodes(canvas, objsArray) { } // 清理不需要的 src 字段(保留自定义图片的 src) -function cleanupSrcFields(jsonObjects, objsArray) { +// 将 cleanupSrcFields 附加到 window 对象,确保在 ui.js 中的 saveAs 函数也能访问 +window.cleanupSrcFields = function cleanupSrcFields(jsonObjects, objsArray) { if (!jsonObjects || !Array.isArray(jsonObjects)) 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) { @@ -990,7 +1044,7 @@ function saveAs(op1, callback) { canvas2.remove(obj) } }) - + let j = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) let b = canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) @@ -1009,18 +1063,27 @@ function saveAs(op1, callback) { dialog .showSaveDialog({ title: language_str('saveFile'), //'保存文件' - filters: [{ name: 'Soon File Type', extensions: ['soon'] }] + filters: [{ name: 'Soon File Type', extensions: ['soon'] }], + defaultPath: openAs.name || undefined }) .then((result) => { if (result.filePath == '') { return } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon' + if (result.filePath == null || result.filePath == undefined) { + 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') 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 layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至' saveHistory() @@ -1048,7 +1111,7 @@ function save(op1, callback) { canvas2.remove(obj) } }) - + let j = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) let b = canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) @@ -1068,7 +1131,7 @@ function save(op1, callback) { //打开的文件 let fs = require('fs') 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) //'保存成功至' saveHistory() if (callback && typeof callback === 'function') { @@ -1079,18 +1142,27 @@ function save(op1, callback) { dialog .showSaveDialog({ title: language_str('saveFile'), //'保存文件' - filters: [{ name: 'Soon File Type', extensions: ['soon'] }] + filters: [{ name: 'Soon File Type', extensions: ['soon'] }], + defaultPath: openAs.name || undefined }) .then((result) => { if (result.filePath == '') { return } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon' + if (result.filePath == null || result.filePath == undefined) { + 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') 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 layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至' saveHistory() @@ -1102,7 +1174,8 @@ function save(op1, callback) { }) } -function saveHistory() { +// 将 saveHistory 附加到 window 对象,确保在 ui.js 中也能访问 +window.saveHistory = function saveHistory() { let fs = require('fs') let j = {} try { @@ -1111,19 +1184,24 @@ function saveHistory() { for (let item of j.history) { if (item.path == openAs.name) { item.time = getDate() - fs.writeFileSync(fullPath, JSON.stringify(j)) + fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8') return } } j.history.push({ time: getDate(), path: openAs.name }) - fs.writeFileSync(fullPath, JSON.stringify(j)) + fs.writeFileSync(fullPath, JSON.stringify(j), 'utf8') } catch (e) { 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') var fsData = fs.readFileSync(file) openAs.name = file @@ -1147,34 +1225,38 @@ function open(file) { if (j.b.objects[0] && !j.b.objects[0].src) { j.b.objects[0].src = './public/images/bg_back_2.png' } - + // 为二维码和条形码对象创建临时的 src(Fabric.js 需要 src 来创建 Image 对象) // 加载完成后会重新生成,所以这里只需要一个占位符 const fo = j.fo || [] const bo = j.bo || [] const placeholder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' - + // 为正面二维码和条形码创建临时 src fo.forEach((objMeta, idx) => { if ((objMeta.type === 8 || objMeta.type === 9) && j.f.objects[idx + 1] && !j.f.objects[idx + 1].src) { j.f.objects[idx + 1].src = placeholder } }) - + // 为背面二维码和条形码创建临时 src bo.forEach((objMeta, idx) => { if ((objMeta.type === 8 || objMeta.type === 9) && j.b.objects && j.b.objects[idx + 1] && !j.b.objects[idx + 1].src) { j.b.objects[idx + 1].src = placeholder } }) - + // 加载 JSON,并在回调中重新生成二维码和条形码 - canvas1.loadFromJSON(j.f, function() { - regenerateQrCodesAndBarcodes(canvas1, fo) + canvas1.loadFromJSON(j.f, function () { + if (typeof window.regenerateQrCodesAndBarcodes === 'function') { + window.regenerateQrCodesAndBarcodes(canvas1, fo); + } canvas1.renderAll() }) - canvas2.loadFromJSON(j.b, function() { - regenerateQrCodesAndBarcodes(canvas2, bo) + canvas2.loadFromJSON(j.b, function () { + if (typeof window.regenerateQrCodesAndBarcodes === 'function') { + window.regenerateQrCodesAndBarcodes(canvas2, bo); + } canvas2.renderAll() }) background_image1 = canvas1.getObjects()[0] @@ -1203,10 +1285,22 @@ function open(file) { } canvas1.renderAll() canvas2.renderAll() - updateList() /* - 修复打开新文件后无法撤销的bug - 2022-07-16 - */ + // 调用 updateList,现在它已附加到 window 对象 + if (typeof window.updateList === 'function') { + window.updateList(); /* + 修复打开新文件后无法撤销的bug + 2022-07-16 + */ + } else { + // 延迟检查,确保 core.js 已加载 + setTimeout(() => { + if (typeof window.updateList === 'function') { + window.updateList(); + } else { + console.error('[open函数] ❌ updateList 函数未定义!'); + } + }, 100); + } setTimeout(() => { recordObjs1.push(JSON.stringify(objs1)) let j1 = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) @@ -1257,7 +1351,22 @@ function clearAll() { openAs.name = '' canvas1.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() } +// 将 clearAll 附加到 window 对象,确保全局可访问 +window.clearAll = clearAll; + diff --git a/lib/design2/ui.js b/lib/design2/ui.js index b4aa2e4..fc7d430 100644 --- a/lib/design2/ui.js +++ b/lib/design2/ui.js @@ -1,3273 +1,3470 @@ -var _keyctrl = false, - _keyc = false, - _textEdit = false, - _inputEdit = false -$('input').focus(function () { - _inputEdit = true -}) -$('input').blur(function () { - _inputEdit = false -}) -$('textarea').focus(function () { - _inputEdit = true -}) -$('textarea').blur(function () { - _inputEdit = false -}) -$('body').keyup(function (event) { - // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) - if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释放 - _keyctrl = false - } - if (event.keyCode == 67) { - _keyc = false - } -}) -$('body').keydown(function (event) { - // 统一的快捷键处理(兼容 Windows/Linux: Ctrl, Mac: Cmd/Meta) - const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端 - - // 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的) - if (!_inputEdit && !_textEdit) { - // CTRL/CMD+N - 新建 - if (isModifierKey && event.keyCode == 78) { - event.preventDefault(); - $('#new').click(); - return; - } - // CTRL/CMD+O - 打开 - if (isModifierKey && event.keyCode == 79) { - event.preventDefault(); - $('#open').click(); - return; - } - // CTRL/CMD+S - 保存 - if (isModifierKey && !event.shiftKey && event.keyCode == 83) { - event.preventDefault(); - $('#save').click(); - return; - } - // CTRL/CMD+SHIFT+S - 保存副本 - if (isModifierKey && event.shiftKey && event.keyCode == 83) { - event.preventDefault(); - output(null, saveAs); - return; - } - // CTRL/CMD+Z - 还原 - if (isModifierKey && !event.shiftKey && event.keyCode == 90) { - event.preventDefault(); - $('#previous').click(); - return; - } - // CTRL/CMD+Y - 重做 - if (isModifierKey && !event.shiftKey && event.keyCode == 89) { - event.preventDefault(); - $('#next').click(); - return; - } - // CTRL/CMD+C - 复制 - if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { - event.preventDefault(); - copySelection(); - return; - } - // CTRL/CMD+V - 粘贴 - if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { - event.preventDefault(); - pasteFromClipboard(); - return; - } - // CTRL/CMD+SHIFT+DEL - 清空 - if (isModifierKey && event.shiftKey && event.keyCode == 46) { - event.preventDefault(); - $('#clean').click(); - return; - } - // CTRL/CMD+DEL - 删除 - if (isModifierKey && !event.shiftKey && event.keyCode == 46) { - event.preventDefault(); - $('#delete').click(); - return; - } - } - // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) - if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd) - _keyctrl = true - if (_keyc && _textEdit) { - //同时按下且在编辑状态 - setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) - //clipboard.writeText((clipboard.readText()+' ')) - } - } - if (event.keyCode == 67) { - _keyc = true - if (_keyctrl & _textEdit) { - //同时按下且在编辑状态 - setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) - //clipboard.writeText((clipboard.readText()+' ')) - } - } - if (event.keyCode == 37) { - //left - let v = -1 - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = -5 - } - if (canvas.getActiveObject()) { - let x = canvas.getActiveObject().get('left') - x += v - canvas.getActiveObject().set('left', x) - canvas.renderAll() - recordState() - updateControls() - } - } - if (event.keyCode == 38) { - //up - let v = -1 - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = -5 - } - if (canvas.getActiveObject()) { - let y = canvas.getActiveObject().get('top') - y += v - canvas.getActiveObject().set('top', y) - canvas.renderAll() - recordState() - updateControls() - } - } - if (event.keyCode == 39) { - //right - let v = 1 - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = 5 - } - if (canvas.getActiveObject()) { - let x = canvas.getActiveObject().get('left') - x += v - canvas.getActiveObject().set('left', x) - canvas.renderAll() - recordState() - updateControls() - } - } - if (event.keyCode == 40) { - //down - let v = +1 - if (_keyctrl || event.ctrlKey || event.metaKey) { - v = 5 - } - if (canvas.getActiveObject()) { - let y = canvas.getActiveObject().get('top') - y += v - canvas.getActiveObject().set('top', y) - canvas.renderAll() - recordState() - updateControls() - } - } - // 普通删除键(DEL键,没有按CTRL/CMD) - if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) { - let actObjs = canvas.getActiveObjects() - let allObjs = canvas.getObjects() - let flag = 0 - for (let item of actObjs) { - if (item != allObjs[0]) { - let i = getIndex(item, canvas) //0是背景,所以从1开始,但objs不包含背景图片,故要-1 - objs.splice(i - 1, 1) - canvas.remove(item) - flag = 1 - } - } - updateList() - canvas.discardActiveObject() - if (flag == 1) { - recordState() - canvas.renderAll() - handleObjectSelected() - } - } -}) -// pre_add_image 已在 design2.js 中定义为全局变量 -$('#addPic').click(function () { - OpenDialog() - function OpenDialog() { - dialog - .showOpenDialog({ - title: language_str('selectPic'), //请选择图片 - buttonLabel: language_str('comf'), //"确认" - filters: [{ name: 'Image File Type', extensions: ['png', 'jpg', 'jpeg'] }] - }) - .then((result) => { - if (result.canceled) return - //console.log(result.filePaths) - fabric.Image.fromURL(result.filePaths[0], function (image) { - //image.left = pointer.x; - image.setSrc(image.toDataURL(), function (image) { - pre_add_image = image - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 1 - }) - //canvas.add(image); - }) - }) - .catch((err) => { - }) - } -}) -$('#addOutPic').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 2 -}) -$('#addText').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 3 -}) -$("#addCircleText").click(function () { - background_image.hoverCursor = "crosshair"; - $(this).css("background-color", "#646E76"); - - $("#addPic").css("background-color", ""); - $("#addOutPic").css("background-color", ""); - $("#addText").css("background-color", ""); - $("#addOutText").css("background-color", ""); - $("#addRect").css("background-color", ""); - $("#addCircle").css("background-color", ""); - $("#addLine").css("background-color", ""); - $("#addQrCode").css("background-color", ""); - $("#addBarCode").css("background-color", ""); - $("#addCounter").css("background-color", ""); - addState = 11; -}); -$('#addOutText').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 4 -}) -$('#addRect').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 5 -}) -$('#addCircle').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 6 -}) -$('#addLine').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 7 -}) -$('#addQrCode').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addBarCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 8 -}) -$('#addBarCode').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addCounter').css('background-color', '') - addState = 9 -}) -$('#addCounter').click(function () { - background_image.hoverCursor = 'crosshair' - $(this).css('background-color', '#646E76') - - $('#addPic').css('background-color', '') - $('#addOutPic').css('background-color', '') - $('#addText').css('background-color', '') - $("#addCircleText").css("background-color", ""); - $('#addOutText').css('background-color', '') - $('#addRect').css('background-color', '') - $('#addCircle').css('background-color', '') - $('#addLine').css('background-color', '') - $('#addQrCode').css('background-color', '') - $('#addBarCode').css('background-color', '') - addState = 10 -}) -$('#version_change').click(function () { - if (bg_version == 1) { - bg_version = 2 - } else { - bg_version = 1 - } - // 类型改变 - $('#source_front').attr('src', './public/images/front_bg' + bg_version + '_2.png') - canvas.renderAll() -}) -$('#front_side').click(function () { - $(this).addClass('ui-button-active') - $('#back_side').removeClass('ui-button-active') - $('.canvas-container:eq(0)').show() - $('.canvas-container:eq(1)').hide() - canvas = canvas1 - objs = objs1 - background_image = background_image1 - next_objs = next_objs1 - pre_objs = pre_objs1 - next_json = next_json1 - pre_json = pre_json1 - recordObjs = recordObjs1 - recordJson = recordJson1 - step = step1 - updateList() - - $('#line_control').hide() - $('#base_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) //背景 -}) -$('#back_side').click(function () { - $(this).addClass('ui-button-active') - $('#front_side').removeClass('ui-button-active') - $('.canvas-container:eq(0)').hide() - $('.canvas-container:eq(1)').show() - canvas = canvas2 - objs = objs2 - background_image = background_image2 - next_objs = next_objs2 - pre_objs = pre_objs2 - next_json = next_json2 - pre_json = pre_json2 - recordObjs = recordObjs2 - recordJson = recordJson2 - step = step2 - updateList() - $('#line_control').hide() - $('#base_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) //"背景" -}) -$('#top_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - _objs[0].set('top', background_image.get('top')) - canvas.renderAll() - return - } - let top = 0 - for (let item of _objs) { - let t_top = item.get('top') - if (t_top < top) { - top = t_top - } - } - groupItems = [] - for (let item of _objs) { - item.set('top', top) - groupItems.push(item) - } - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#bottom_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - let idx = getIndex(_objs[0]) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get('strokeWidth') - } - _objs[0].set('top', background_image.get('top') + background_image.get('height') - _objs[0].get('height') * _objs[0].get('scaleY') - other) - canvas.renderAll() - return - } - let bottom = 0 - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - let t_b = item.get('top') + item.get('height') * item.get('scaleY') + other - if (t_b > bottom) { - bottom = t_b - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - item.set('top', bottom - item.get('height') * item.get('scaleY') - other) - groupItems.push(item) - } - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#center_y_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - let idx = getIndex(_objs[0]) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get('strokeWidth') - } - _objs[0].set('top', background_image.get('top') + (background_image.get('height') - (_objs[0].get('height') + other) * _objs[0].get('scaleY')) / 2) - canvas.renderAll() - return - } - let top = 0 - for (let item of _objs) { - let t_top = item.get('top') - if (t_top < top) { - top = t_top - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - item.set('top', top + (item.group.height - (item.get('height') + other) * item.get('scaleY')) / 2) - groupItems.push(item) - } - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#left_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - _objs[0].set('left', background_image.get('left')) - canvas.renderAll() - return - } - let left = 0 - for (let item of _objs) { - let t_left = item.get('left') - if (t_left < left) { - left = t_left - } - } - groupItems = [] - for (let item of _objs) { - item.set('left', left) - groupItems.push(item) - } - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#right_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - let idx = getIndex(_objs[0]) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - _objs[0].set('left', background_image.get('left') + background_image.get('width') - _objs[0].get('width') * _objs[0].get('scaleX') - other) - canvas.renderAll() - return - } - let right = 0 - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - let t_r = item.get('left') + item.get('width') * item.get('scaleX') + other - if (t_r > right) { - right = t_r - } - } - let groupItems = [] - - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - item.set('left', right - item.get('width') * item.get('scaleX') - other) - groupItems.push(item) - } - //BUG1 - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#center_x_alignment').click(function () { - let _objs = canvas.getActiveObjects() - if (_objs.length == 1) { - //只选中了一个 - let idx = getIndex(_objs[0]) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = _objs[0].get('strokeWidth') - } - _objs[0].set('left', background_image.get('left') + (background_image.get('width') - (_objs[0].get('width') + other) * _objs[0].get('scaleX')) / 2) - canvas.renderAll() - return - } - let left = 0 - for (let item of _objs) { - let t_left = item.get('left') - if (t_left < left) { - left = t_left - } - } - groupItems = [] - for (let item of _objs) { - let idx = getIndex(item) - let type = objs[idx - 1].type - let other = 0 //strokeWidth - if (type == 5 || type == 6 || type == 7) { - other = item.get('strokeWidth') - } - item.set('left', left + (item.group.width - (item.get('width') + other) * item.get('scaleX')) / 2) - groupItems.push(item) - } - canvas.discardActiveObject() - let sel = new fabric.ActiveSelection(groupItems, { - canvas: canvas - }) - canvas.setActiveObject(sel) - canvas.requestRenderAll() - canvas.renderAll() -}) -$('#up_obj').click(function () { - //上移,放到前面 数组中在后面 - let idx = getIndex(canvas.getActiveObject()) - if (idx + 1 != canvas.getObjects().length) { - canvas.bringForward(canvas.getActiveObject()) - canvas.renderAll() - let temp = objs[idx - 1] - objs[idx - 1] = objs[idx] - objs[idx] = temp - //console.log(objs); - - recordState() - updateList() - selectObj(idx) - } -}) -$('#down_obj').click(function () { - //下移,放到后面 数组中在前面 - let idx = getIndex(canvas.getActiveObject()) - if (idx != 1) { - canvas.sendBackwards(canvas.getActiveObject()) - canvas.renderAll() - //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; - - let temp = objs[idx - 1] - objs[idx - 1] = objs[idx - 2] - objs[idx - 2] = temp - recordState() - updateList() - selectObj(idx - 2) - } -}) -$('#set_bg').click(function () { - //设置为背景 - let obj = canvas.getActiveObject() - let idx = getIndex(canvas.getActiveObject()) - const scaleX = 1012 / obj.width - const scaleY = 648 / obj.height - obj.set({ - scaleX: scaleX, - scaleY: scaleY, - left: ($('#canvas1').width() - 1012) / 2, - top: ($('#canvas1').height() - 648) / 2 - }) - $('#text_w').val(1012) - $('#text_h').val(648) - $('#text_x').val(0) - $('#text_y').val(0) - canvas.sendToBack(canvas.getActiveObject()) - canvas.bringForward(canvas.getActiveObject()) - canvas.renderAll() - let objItem = objs.splice(idx - 1, 1)[0] - objs.unshift(objItem) - recordState() - updateList() - selectObj(0) -}) -$('#previous').click(function () { - //撤销一次操作 - if (step.val == 0) { - return - } - - step.val-- - canvas.loadFromJSON(recordJson[step.val]) - if ($('#front_side').hasClass('ui-button-active')) { - //objs = JSON.parse(recordObjs[step.val]); - objs1 = JSON.parse(recordObjs[step.val]) - objs = objs1 - } else if ($('#back_side').hasClass('ui-button-active')) { - //objs = JSON.parse(recordObjs[step.val]); - objs2 = JSON.parse(recordObjs[step.val]) - objs = objs2 - } - - background_image = canvas.getObjects()[0] - canvas.renderAll() - //recordState(); - updateList() - - selectObj(-1) - - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -}) -$('#next').click(function () { - //撤销一次撤销操作 - if (step.val >= recordObjs.length - 1) { - return - } - - ++step.val - canvas.loadFromJSON(recordJson[step.val]) - if ($('#front_side').hasClass('ui-button-active')) { - //objs = JSON.parse(recordObjs[step.val]); - objs1 = JSON.parse(recordObjs[step.val]) - objs = objs1 - } else if ($('#back_side').hasClass('ui-button-active')) { - //objs = JSON.parse(recordObjs[step.val]); - objs2 = JSON.parse(recordObjs[step.val]) - objs = objs2 - } - background_image = canvas.getObjects()[0] - canvas.renderAll() - selectObj(-1) - - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - updateList() -}) -$('#clean').click(function () { - objs.splice(0, objs.length) - - let allObjs = canvas.getObjects() - for (let item of allObjs) { - if (item != allObjs[0]) { - canvas.remove(item) - } - } - updateList() - recordState() -}) -$('#rotate').click(function () { - let obj = canvas.getActiveObject() - obj.rotate(Math.round((obj.get('angle') + 90) % 360)) - $('#text_r').val(obj.get('angle')) - canvas.renderAll() - updateControls() - recordState() -}) -$('#vertical_obj').click(function () { - let obj = canvas.getActiveObject() - obj.set('flipY', !obj.get('flipY')) - canvas.renderAll() - updateControls() - recordState() -}) -$('#align_obj').click(function () { - let obj = canvas.getActiveObject() - obj.set('flipX', !obj.get('flipX')) - canvas.renderAll() - updateControls() - recordState() -}) -$('#text_italics').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('fontStyle', 'normal') - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('fontStyle', 'italic') - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#text_bold').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选,恢复正常 - canvas.getActiveObject().set('fontWeight', 'normal') - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('fontWeight', 'bold') - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#text_underline').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('underline', false) - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('underline', true) - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#text_linethrough').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('linethrough', false) - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('linethrough', true) - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$("#circle_text_italics").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选 - canvas.getActiveObject().set("fontStyle", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontStyle", "italic") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$("#circle_text_bold").click(function () { - if ($(this).hasClass("ui-radio-acitve")) { - //已选,恢复正常 - canvas.getActiveObject().set("fontWeight", "normal") - $(this).removeClass("ui-radio-acitve") - } else { - //未选 - canvas.getActiveObject().set("fontWeight", "bold") - $(this).addClass("ui-radio-acitve") - } - recordState(); - canvas.renderAll(); -}); -$('#out_left_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_left_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'left') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'left' - recordState() - canvas.renderAll() -}) -$('#out_right_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_right_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'right') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'right' - recordState() - canvas.renderAll() -}) -$('#out_center_alignment').click(function () { - $('#out_left_alignment').parent().removeClass('tool1') - $('#out_right_alignment').parent().removeClass('tool1') - $('#out_center_alignment').parent().removeClass('tool1') - setTimeout(() => { - $('#out_center_alignment').parent().addClass('tool1') - }); - canvas.getActiveObject().set('textAlign', 'center') - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].align = 'center' - recordState() - canvas.renderAll() -}) -$('#out_text_italics').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('fontStyle', 'normal') - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('fontStyle', 'italic') - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#out_text_bold').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选,恢复正常 - canvas.getActiveObject().set('fontWeight', 'normal') - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('fontWeight', 'bold') - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#out_text_underline').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('underline', false) - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('underline', true) - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#out_text_linethrough').click(function () { - if ($(this).hasClass('ui-radio-acitve')) { - //已选 - canvas.getActiveObject().set('linethrough', false) - $(this).removeClass('ui-radio-acitve') - } else { - //未选 - canvas.getActiveObject().set('linethrough', true) - $(this).addClass('ui-radio-acitve') - } - recordState() - canvas.renderAll() -}) -$('#lock').click(function () { - canvas.getActiveObject().set('selectable', !canvas.getActiveObject().get('selectable')) - if (canvas.getActiveObject().get('selectable')) { - $('#lock_img').attr('src', 'public/images/unlock20.png') //已经上锁,需要解锁 - } else { - $('#lock_img').attr('src', 'public/images/lock20.png') //没上锁,可以上锁 - } - recordState() - canvas.renderAll() -}) -$('#text_back_transparent').click(function () { - canvas.getActiveObject().set('textBackgroundColor', '') - $('#text_back_color').val('#ffffff') - canvas.renderAll() -}) -$('#circle_text_back_transparent').click(function () { - canvas.getActiveObject().set('textBackgroundColor', '') - $('#circle_text_back_color').val('#ffffff') - canvas.renderAll() -}) -$('#out_text_back_transparent').click(function () { - canvas.getActiveObject().set('textBackgroundColor', '') - $('#out_text_back_color').val('#ffffff') - canvas.renderAll() -}) -$('#rect_transparent').click(function () { - canvas.getActiveObject().set('fill', '') - $('#rect_color').val('#ffffff') - canvas.renderAll() -}) -$('#rect_stroke_transparent').click(function () { - canvas.getActiveObject().set('stroke', '') - $('#rect_stroke').val('#ffffff') - canvas.renderAll() -}) -$('#circle_transparent').click(function () { - canvas.getActiveObject().set('fill', '') - $('#circle_color').val('#ffffff') - canvas.renderAll() -}) -$('#circle_stroke_transparent').click(function () { - canvas.getActiveObject().set('stroke', '') - $('#circle_stroke').val('#ffffff') - canvas.renderAll() -}) -// 清理不需要的 src 字段(保留自定义图片的 src) -// cleanupSrcFields 函数已在 output.js 中定义 - -function saveAs(op1, callback) { - let j = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) - let b = canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) - - // 清理不需要的 src 字段(调用 output.js 中的 cleanupSrcFields) - cleanupSrcFields(j.objects, objs1); - cleanupSrcFields(b.objects, objs2); - - let o = { f: j, b: b, fo: objs1, bo: objs2 } - let con_o = Object.assign(o, op1) - dialog - .showSaveDialog({ - title: language_str('saveFile'), //'保存文件' - filters: [{ name: 'Soon File Type', extensions: ['soon'] }] - }) - .then((result) => { - if (result.filePath == '') { - return - } - if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { - result.filePath += '.soon' - } - let fs = require('fs') - con_o.soonType = 2 - fs.writeFileSync(result.filePath, JSON.stringify(con_o)) - openAs.name = result.filePath - layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至' - saveHistory() - if (callback && typeof callback === 'function') { - callback() - } - }) - .catch((err) => { - }) -} -// save 函数已在 output.js 中定义 -// 复制 -$("#copy").click(function () { - copySelection(); -}) -// 粘贴 -$("#paste").click(function () { - pasteFromClipboard(); -}) -// 保存按钮事件绑定 -$('#save').click(function () { - output(); // 调用 output 函数 - return; -}) -function getDate() { - let date = new Date() - return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() -} -function getAbsoluteXY(_obj) { - let coord = _obj.get('lineCoords') - //let xs = [], ys = []; - return [_obj.get('left'), _obj.get('top')] -} -// fullPath, saveHistory 和 open 函数已在 output.js 中定义 -$('#open').click(function () { - if (step.val == 0) { - OpenDialog(); - return; - } - layer.confirm( - '' + language_str('whetherSave') + '', - function (index) { - output(OpenDialog); - layer.close(index); - }, - function (index) { - OpenDialog(); - } - ) - function OpenDialog() { - dialog - .showOpenDialog({ - title: '请选择文件', - buttonLabel: language_str('comf'), - filters: [{ name: 'Soon File Type', extensions: ['soon'] }] - }) - .then((result) => { - if (result.canceled) return; - let filePath = result.filePaths[0]; - let fs = require('fs'); - let fsData = fs.readFileSync(filePath); - let j = JSON.parse(fsData.toString()); - let type = j.soonType ? j.soonType : j.backBlackPic ? 2 : 1; - - if (type == 1) { - ipcRenderer.send('open-design-page', filePath, type); - return; - } - - // 调用 output.js 中的 open 函数 - open(filePath); - }) - .catch((err) => { - console.log(err); - }) - } -}) -function clearAll() { - //let blank = "{\"f\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":1012,\"height\":648,\"fill\":\"#000000\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAX2YPDVmXlAHjVBgAABAgQIECBAgAABAgQIlAh8bQ8Gt83MQ0oWtiYBAgQIECBAgAABAgQIECCQBW7fg8GtM/OoPGuCAAECBAgQIECAAAECBAgQKBG4dQ8GN8zMdSULW5MAAQIECBAgQIAAAQIECBDIAjfuweADM/OsPGuCAAECBAgQIECAAAECBAgQKBH44B4M3jIzLy9Z2JoECBAgQIAAAQIECBAgQIBAFnjrHgxeMDPvzrMmCBAgQIAAAQIECBAgQIAAgRKBn9uDwYmZ+UTJwtYkQIAAAQIECBAgQIAAAQIEssCJPRg8cGa+ODNX5XkTBAgQIECAAAECBAgQIECAwGUucMfMPGztS27b9qGZedplvrD1CBAgQIAAAQIECBAgQIAAgSzw4bXW008Gg/1LD/cvP/QgQIAAAQIECBAgQIAAAQIEugVevtb6zZPB4JqZuanbw/YECBAgQIAAAQIECBAgQIDAzFy71rr568Fgf2zbdv3MPBENAQIECBAgQIAAAQIECBAgUCtw/VrrSfv2pwaDF8/Mb9eSWJwAAQIECBAgQIAAAQIECBB48VrrHXcPBg+dmc/OzLfwIUCAAAECBAgQIECAAAECBOoE/ntmrl5r3fYNwWD/H9u2vW1mXlJHYmECBAgQIECAAAECBAgQIEDg7Wutl55kuOufJByCwWNm5p9n5kGcCBAgQIAAAQIECBAgQIAAgRqB/5uZ711r3XKPweAQDd41Mz9fQ2JRAgQIECBAgAABAgQIECBA4HfXWi88leEbPmFwCAaPPHzK4CpeBAgQIECAAAECBAgQIECAwGUvcMfMPHattX+v4V2P04LBIRq8embecNmTWJAAAQIECBAgQIAAAQIECBB47VrrtAZwpmCwf4fBDTPzeG4ECBAgQIAAAQIECBAgQIDAZSvwqZk5sdb6yt03vMdgsA9t23ZiZj42M1dctiwWI0CAAAECBAgQIECAAAECvQJ3zsxT1lr7BwZOe5wxGByiwS/OzK/32tmcAAECBAgQIECAAAECBAhctgKvWmv92pm2S8Fg//M/nplnX7Y8FiNAgAABAgQIECBAgAABAn0C75uZ56y1tnMKBvsPbdv2rTPz5zPz5D4/GxMgQIAAAQIECBAgQIAAgctO4OMz87S11u1n2+ysnzA4+YPbtj388H0G1152TBYiQIAAAQIECBAgQIAAAQI9AjcdvrfgC2nlIwWD/Um2bXvMzHx0Zh6VntSfEyBAgAABAgQIECBAgAABAvc7gc/MzFPXWjcf5Z0dORgcosE1M/ORmfmuozy5GQIECBAgQIAAAQIECBAgQOB+IfDpmfnxtdb+CYMjPY4VDA7RYP+EwZ/MzBOO9AqGCBAgQIAAAQIECBAgQIAAgftS4JMz88y11v4JgyM/jh0MDtHgwTPzhzPzk0d+JYMECBAgQIAAAQIECBAgQIDAxRZ4/8w8f631peO+8DkFg0M02H/2lTPzKzNzxXFf2DwBAgQIECBAgAABAgQIECBwwQTunJlfnpk3ne1XJ57t1c85GJx80m3bThw+bfC4C7amJyZAgAABAgQIECBAgAABAgSOKvCPM/O8tdaNR/2Be5q718Fgf9Jt2/ZPGOyfNnj1zFx1b96QnyVAgAABAgQIECBAgAABAgTOSeCOmXnj4VMF+ycM7tXjvASDk+9g27ZHzMzrZuZnZ+ab7tU788MECBAgQIAAAQIECBAgQIDAUQT+d2Z+b2Zev9b6/FF+4Cgz5zUYnBIOrp6ZV8zMi2bmyqO8ETMECBAgQIAAAQIECBAgQIDAsQS+PDPvnJk3r7U+d6yfPMLwBQkGp4SDh87Mc/d/OzEzP3iE92OEAAECBAgQIECAAAECBAgQOLvA9TPznpl571rrtguFdUGDwalvetu2x8zMM2bmR2bmqTPzsAu1lOclQIAAAQIECBAgQIAAAQKXkcAXZ+avZ+avZubP1lo3X4zdLlowuFs8eMDMPGFmrpuZ75uZa2bmO2fm2w9fmrh/MsGDAAECBAgQIECAAAECBAi0COyfFNi/tPDfZ+bWmbllZvbfdrD/poNPrrW+drEh/h+5oaPdsxLhuQAAAABJRU5ErkJggg==\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"b\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":1012,\"height\":648,\"fill\":\"rgb(0,0,0)\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"fo\":[],\"bo\":[]}"; - let t_objs1 = canvas1.getObjects() - let t_objs2 = canvas2.getObjects() - for (let i = 1; i < t_objs1.length; i++) { - canvas1.remove(t_objs1[i]) - } - for (let i = 1; i < t_objs2.length; i++) { - canvas2.remove(t_objs2[i]) - } - objs2 = [] - objs1 = [] - step1.val = 0 - step2.val = 0 - recordJson1 = [] - recordJson2 = [] - recordObjs1 = [] - recordObjs2 = [] - if ($('#front_side').hasClass('ui-button-active')) { - objs = objs1 - recordObjs = recordObjs1 - recordJson = recordJson1 - step = step1 - } else if ($('#back_side').hasClass('ui-button-active')) { - objs = objs2 - recordObjs = recordObjs2 - recordJson = recordJson2 - step = step2 - } - openAs.name = '' - canvas1.renderAll() - canvas2.renderAll() - updateList() -} -$('#new').click(function () { - if (step.val == 0) { - ipcRenderer.send('open-first-page'); - return; - } - layer.confirm( - '' + language_str('whetherSave') + '', - function (index) { - output(() => ipcRenderer.send('open-first-page')); - layer.close(index); - }, - function (index) { - ipcRenderer.send('open-first-page'); - } - ) -}) -function chagneTitle() { } -function addBackground() { - // 类型改变 - fabric.Image.fromURL('./public/images/bg_front_2.png', function (image) { - //image.set("scaleX",$("#canvas-div").width() / 1200 < 1 ? $("#canvas-div").width() / 1200 : 1) - - image.left = ($('#canvas1').width() - image.width * image.get('scaleX')) / 2 - image.top = ($('#canvas1').height() - image.height * image.get('scaleY')) / 2 - - image.selectable = false - image.hoverable = false - image.hoverCursor = 'default' - image.setSrc(image.toDataURL(), function (image) { - background_image1 = image - background_image = background_image1 - canvas.add(image) - canvas.renderAll() - //pre_objs1.push(JSON.stringify(objs1)); - - recordObjs1.push(JSON.stringify(objs1)) - recordJson1.push(canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])) - }) - // 类型改变 - fabric.Image.fromURL('./public/images/bg_back_2.png', function (image) { - image.left = ($('#canvas2').width() - image.width) / 2 - image.top = ($('#canvas2').height() - image.height) / 2 - - image.selectable = false - image.hoverable = false - image.hoverCursor = 'default' - - image.setSrc(image.toDataURL(), function (image) { - background_image2 = image - canvas2.add(image) - canvas2.renderAll() - //pre_objs2.push(JSON.stringify(objs2)); - - recordObjs2.push(JSON.stringify(objs2)) - recordJson2.push(canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])) - - let file = GetFile().get('file') - if (file && file != 'empty') { - open(file) - } - }) - }) - is_bgi_add = true - }) -} -function selectObject(target, index) { - updateControls() - - $('#base_control').show() - //$("#text_x").val((target.left - background_image.left).toFixed(1)); -} -function updateControls() { - $('#text_r').val(canvas.getActiveObject().get('angle').toFixed(0)) - $('#text_x').val((canvas.getActiveObject().get('left') - background_image.left).toFixed(0)) - $('#text_y').val((canvas.getActiveObject().get('top') - background_image.top).toFixed(0)) - $('#text_h').val((canvas.getActiveObject().get('scaleY') * canvas.getActiveObject().get('height')).toFixed(0)) - $('#text_w').val((canvas.getActiveObject().get('scaleX') * canvas.getActiveObject().get('width')).toFixed(0)) - if (canvas.getActiveObject().get('selectable')) { - $('#lock_img').attr('src', 'public/images/unlock20.png') //已经上锁,需要解锁 - } else { - $('#lock_img').attr('src', 'public/images/lock20.png') //没上锁,可以上锁 - } -} -function checkName(name) { - //检查字段名是否重复了 - 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 resName(pre_name) { - //返回的是不重复的字段名 - let num = objs1.length + objs2.length - 1 - do { - num++ - } while (!checkName(pre_name + num)) //重复了就再加1 - return pre_name + num -} -function addPic(pointer) { - pre_add_image.left = pointer.x - pre_add_image.top = pointer.y - - canvas.add(pre_add_image) - - objs.push({ type: 1, black: false }) - canvas.renderAll() - updateList() - recordState() - //OpenDialog(); -} -function selectPic(target, index) { - //透明度 - - $('#pic_control').show() - $("#set_bg").show(); - pic_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) - - let idx = getIndex(canvas.getActiveObject()) - // $("#pic_black").prop("checked", objs[idx-1].black ? 'checked' : ''); - - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function addOutPic(pointer) { - fabric.Image.fromURL('./public/images/outpic_extra.png', function (image) { - let width = canvas.getWidth() - let height = canvas.getHeight() - image.left = pointer.x - image.top = pointer.y - image.opacity = 1 - //image.on("selected",function(){//test well - image.setSrc(image.toDataURL(), function (image) { - canvas.add(image) - objs.push({ type: 2, name: resName('OUT_PIC_'), black: false }) - canvas.renderAll() - updateList() - recordState() - }) - }) -} -function selectOutPic(target, index) { - //字段名 - $('#out_pic_control').show() - out_pic_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) - let idx = getIndex(canvas.getActiveObject()) - $('#out_pic_field_name').val(objs[idx - 1].name) - // $("#out_pic_black").prop("checked", objs[idx-1].black ? 'checked' : ''); - - $('#pic_control').hide() - $("#set_bg").hide(); - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} - -function addText(pointer) { - let text = new fabric.IText('TEXT', { - //源:文本 - left: pointer.x, - top: pointer.y, - fill: '#000000', - textBackgroundColor: '', - fontStyle: 'normal', - fontWeight: 'normal', - underline: false, - linethrough: false, - fontFamily: 'Arial' - }) - text.setControlVisible('ml', false) - text.setControlVisible('mt', false) - text.setControlVisible('mr', false) - text.setControlVisible('mb', false) - canvas.add(text) - objs.push({ type: 3, black: false }) - canvas.renderAll() - updateList() - recordState() -} -function selectText() { - //console.log(canvas.getActiveObject().get("fontFamily")); - $('#text_control').show() - $('#text_color').val(canvas.getActiveObject().get('fill')) - $('#text_back_color').val(canvas.getActiveObject().get('textBackgroundColor') == '' ? '#ffffff' : canvas.getActiveObject().get('textBackgroundColor')) - let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi - if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 - $("#text_size").val(val); - $('#text_text').val(canvas.getActiveObject().get('text')) - $('#text_font_family').val(canvas.getActiveObject().get('fontFamily')) - - if (canvas.getActiveObject().get('underline') == true) { - $('#text_underline').addClass('ui-radio-acitve') - } else { - $('#text_underline').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('fontWeight') == 'bold') { - $('#text_bold').addClass('ui-radio-acitve') - } else { - $('#text_bold').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('fontStyle') == 'italic') { - $('#text_italics').addClass('ui-radio-acitve') - } else { - $('#text_italics').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('linethrough') == true) { - $('#text_linethrough').addClass('ui-radio-acitve') - } else { - $('#text_linethrough').removeClass('ui-radio-acitve') - } - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function getDisdance(x1, y1, x2, y2) { - var dx = Math.abs(x2 - x1); // 计算x轴上的距离差,并取绝对值 - var dy = Math.abs(y2 - y1); // 计算y轴上的距离差,并取绝对值 - var distance = Math.sqrt(dx * dx + dy * dy); // 应用勾股定理计算距离 - return distance; -} -function getDeg(pointer) { - // 计算点击位置与画布中心的坐标差 - var centerX = canvas.width / 2; - var centerY = canvas.height / 2; - var mouseX = pointer.x; - var mouseY = pointer.y; - var dx = mouseX - centerX; - var dy = mouseY - centerY; - // 计算旋转角度(弧度) - var angleRad = Math.atan2(dy, dx); - // 将角度转换为度数 - var angleDeg = angleRad * (180 / Math.PI); - if (angleDeg < 0) { - angleDeg += 360; - } - angleDeg += 90 - return angleDeg -} -function addCircleText(pointer) { - let distance = getDisdance(pointer.x, pointer.y, canvas.width / 2, canvas.height / 2) - let angleDeg = getDeg(pointer) - let text = new fabric.CurvedText('Circle TEXT', {//源:圆形文本 - left: pointer.x, - top: pointer.y, - fill: "#000000", - textBackgroundColor: "", - fontStyle: "normal", - fontWeight: "normal", - diameter: distance * 2, - fontSize: 30, - underline: false, - linethrough: false, - lockScalingX: true, - lockScalingY: true, - fontFamily: 'Arial', - originX: 'center', - originY: 'center', - angle: angleDeg, - flipped: pointer.y > canvas.height / 2 ? true : false - }); - // distance = getDisdance(pointer.x+text.width/2, pointer.y, canvas.width/2,canvas.height/2) - text.setControlVisible("ml", false); - text.setControlVisible("mt", false); - text.setControlVisible("mr", false); - text.setControlVisible("mb", false); - canvas.add(text); - objs.push({ type: 11, black: false, circleCenter: 0 }); - canvas.renderAll(); - updateList(); - recordState(); -} -function selectCircleText() { - let idx = getIndex(canvas.getActiveObject()); - $("#circle_text_control").show(); - $("#circle_text_color").val(canvas.getActiveObject().get("fill")); - $("#circle_text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor")); - if (typeof circle_text_size_updating !== 'undefined') { - circle_text_size_updating = true; - } - circle_text_size.setValue(canvas.getActiveObject().get("fontSize")); - if (typeof circle_text_size_updating !== 'undefined') { - circle_text_size_updating = false; - } - circle_text_diameter.setValue(canvas.getActiveObject().get("diameter")); - $("#circle_text_center").prop("checked", objs[idx - 1].circleCenter ? 'checked' : ''); - $("#circle_text_text").val(canvas.getActiveObject().get("text")); - $("#circle_text_font_family").val(canvas.getActiveObject().get("fontFamily")); - - if (canvas.getActiveObject().get("underline") == true) { - $("#circle_text_underline").addClass("ui-radio-acitve") - } else { - $("#circle_text_underline").removeClass("ui-radio-acitve") - } - if (canvas.getActiveObject().get("fontWeight") == "bold") { - $("#circle_text_bold").addClass("ui-radio-acitve") - } else { - $("#circle_text_bold").removeClass("ui-radio-acitve") - } - if (canvas.getActiveObject().get("fontStyle") == "italic") { - $("#circle_text_italics").addClass("ui-radio-acitve") - } else { - $("#circle_text_italics").removeClass("ui-radio-acitve") - } - if (canvas.getActiveObject().get("linethrough") == true) { - $("#circle_text_linethrough").addClass("ui-radio-acitve") - } else { - $("#circle_text_linethrough").removeClass("ui-radio-acitve") - } - $("#pic_control").hide(); - $("#set_bg").hide(); - $("#rotate").hide(); - $("#out_pic_control").hide(); - $("#text_control").hide(); - $("#out_text_control").hide(); - $("#rect_control").hide(); - $("#circle_control").hide(); - $("#line_control").hide(); - $("#counter_control").hide(); - $("#qrcode_Controll").hide(); - $("#barcode_controll").hide(); - -} -function addOutText(pointer) { - //MERGE_TEXT_1 - let text = new fabric.Text('MERGE TEXT', { - //源:合成文本 - left: pointer.x, - top: pointer.y, - fill: '#000000', - fontStyle: 'normal', - fontWeight: 'normal', - textBackgroundColor: '', - underline: false, - linethrough: false, - fontFamily: 'Arial', - textAlign: 'center' - }) - - //text.on({ - text.setControlVisible('ml', false) - text.setControlVisible('mt', false) - text.setControlVisible('mr', false) - text.setControlVisible('mb', false) - - canvas.add(text) - objs.push({ type: 4, name: resName('OUT_TEXT_'), exceed: false, autoWrap: false, fixSize: false, black: false, align: 'center' }) - canvas.renderAll() - updateList() - recordState() -} -function selectOutText() { - //color - const align = canvas.getActiveObject().get('textAlign') - if (align === 'left') { - $('#out_left_alignment').parent().addClass('tool1') - } else if (align === 'right') { - $('#out_right_alignment').parent().addClass('tool1') - } else { - $('#out_center_alignment').parent().addClass('tool1') - } - $('#out_text_control').show() - $('#out_text_color').val(canvas.getActiveObject().get('fill')) - $('#out_text_text').val(canvas.getActiveObject().get('text')) - let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi - if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 - $("#out_text_size").val(val); - $('#out_text_back_color').val(canvas.getActiveObject().get('textBackgroundColor') == '' ? '#ffffff' : canvas.getActiveObject().get('textBackgroundColor')) - let idx = getIndex(canvas.getActiveObject()) - $('#out_text_field_name').val(objs[idx - 1].name) - $('#out_text_font_family').val(canvas.getActiveObject().get('fontFamily')) - $('#exceed').prop('checked', objs[idx - 1].exceed ? 'checked' : '') - $('#autoWrap').prop('checked', objs[idx - 1].autoWrap ? 'checked' : '') - $('#fixSize').prop('checked', objs[idx - 1].fixSize ? 'checked' : '') - if (canvas.getActiveObject().get('underline') == true) { - $('#out_text_underline').addClass('ui-radio-acitve') - } else { - $('#out_text_underline').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('fontWeight') == 'bold') { - $('#out_text_bold').addClass('ui-radio-acitve') - } else { - $('#out_text_bold').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('fontStyle') == 'italic') { - $('#out_text_italics').addClass('ui-radio-acitve') - } else { - $('#out_text_italics').removeClass('ui-radio-acitve') - } - if (canvas.getActiveObject().get('linethrough') == true) { - $('#out_text_linethrough').addClass('ui-radio-acitve') - } else { - $('#out_text_linethrough').removeClass('ui-radio-acitve') - } - - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#rect_control').hide() - $('#circle_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function addRect(pointer) { - let rect = new fabric.Rect({ - left: pointer.x, - top: pointer.y, - fill: '', - stroke: "#ff0000", - strokeWidth: 3, - width: 100, - height: 100 - }) - canvas.add(rect) - objs.push({ type: 5, black: false }) - canvas.renderAll() - updateList() - recordState() -} -function selectRect() { - //color - $('#rect_control').show() - $('#rect_color').val(canvas.getActiveObject().get('fill') == '' ? '#ffffff' : canvas.getActiveObject().get('fill')) - $('#rect_stroke').val(canvas.getActiveObject().get('stroke') == '' ? '#ffffff' : canvas.getActiveObject().get('stroke')) - $('#rect_stroke_width').val(canvas.getActiveObject().get('strokeWidth')) - $('#rect_radius').val(canvas.getActiveObject().get('rx')) - rect_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) - let a = canvas.getActiveObject().getCoords() - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#circle_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function addCircle(pointer) { - let circle = new fabric.Circle({ - left: pointer.x, - top: pointer.y, - fill: '', - stroke: '#ff0000', - strokeWidth: 3, - radius: 100, - strokeUniform: true - }) - canvas.add(circle) - objs.push({ type: 6, black: false }) - canvas.renderAll() - updateList() - recordState() -} -function selectCircle() { - //border-color - $('#circle_control').show() - $('#circle_color').val(canvas.getActiveObject().get('fill') == '' ? '#ffffff' : canvas.getActiveObject().get('fill')) - $('#circle_stroke').val(canvas.getActiveObject().get('stroke') == '' ? '#ffffff' : canvas.getActiveObject().get('stroke')) - $('#circle_stroke_width').val(canvas.getActiveObject().get('strokeWidth')) - circle_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#line_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function addLine(pointer) { - let line = new fabric.Line([50, 100, 200, 100], { - left: pointer.x, - top: pointer.y, - stroke: '#ff0000', - strokeWidth: 3, - strokeDashArray: [0, 0], - }) - - line.setControlVisible('tl', false) - line.setControlVisible('tr', false) - line.setControlVisible('br', false) - line.setControlVisible('bl', false) - line.setControlVisible('mt', false) - line.setControlVisible('mb', false) - canvas.add(line) - objs.push({ type: 7, black: false }) - canvas.renderAll() - updateList() - recordState() -} -function selectLine() { - //color - $('#line_control').show() - - let idx = getIndex(canvas.getActiveObject()) - $('#line_color').val(canvas.getActiveObject().get('stroke')) - $('#line_dist').val(canvas.getActiveObject().get('strokeDashArray')[0]) - $('#text_h').val(canvas.getActiveObject().get('strokeWidth')) - - $('#pic_control').hide() - $("#set_bg").hide(); - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function addQrCode(pointer) { - let qr = jrQrcode.getQrBase64('https://www.cardsoon.com', { padding: 0 }) - fabric.Image.fromURL(qr, function (image) { - image.left = pointer.x - image.top = pointer.y - canvas.add(image) - objs.push({ type: 8, name: resName('QR_CODE_'), color: '#000000', val: 'http://www.cardsoon.com', black: false }) - canvas.renderAll() - updateList() - recordState() - }) -} -function selectQrCode() { - //字段名 - $('#qrcode_Controll').show() - let idx = getIndex(canvas.getActiveObject()) - $('#qrcode_field_name').val(objs[idx - 1].name) - $('#qrcode_color').val(objs[idx - 1].color) - $('#qrcode_val').val(objs[idx - 1].val) - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#barcode_controll').hide() -} -function addBarCode(pointer) { - JsBarcode('#barcode', '123456789', { margin: 0, lineColor: '#000000', fontSize: 18, font: 'Arial' }) - let barcode = document.getElementById('barcode') - let bar = barcode.toDataURL('image/png') - fabric.Image.fromURL(bar, function (image) { - image.left = pointer.x - image.top = pointer.y - - canvas.add(image) - objs.push({ type: 9, name: resName('BAR_CODE_'), val: '123456789', color: '#000000', fontSize: 18, font: 'Arial', show: false, black: false }) //show是取消文字显示 - canvas.renderAll() - updateList() - recordState() - }) -} -function selectBarCode() { - //字段名 - $('#barcode_controll').show() - let idx = getIndex(canvas.getActiveObject()) - $('#barcode_field_name').val(objs[idx - 1].name) - $('#barcode_font_family').val(objs[idx - 1].font) - let val = parseFloat(objs[idx - 1].fontSize) * 72 / dpi - if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 - $("#barcode_size").val(val); - $('#barcode_val').val(objs[idx - 1].val) - $('#barcode_show').prop('checked', objs[idx - 1].show ? 'checked' : '') - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() -} -function addCounter(pointer) { - let text = new fabric.Text('0', { - left: pointer.x, - top: pointer.y, - fill: '#000000' - }) - canvas.add(text) - objs.push({ type: 10, name: resName('COUNTER_'), start: 0, add: 1, black: false }) - canvas.renderAll() - updateList() - recordState() -} -function selectCounter() { - //起始 - $('#counter_control').show() - - let idx = getIndex(canvas.getActiveObject()) - $('#counter_start').val(objs[idx - 1].start) - $('#counter_add').val(objs[idx - 1].add) - $('#counter_color').val(canvas.getActiveObject().get('fill')) - $('#count_font_family').val(canvas.getActiveObject().get('fontFamily')) - let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi - if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 - $("#count_size").val(val); - - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() -} -function getIndex(target, _canvas = null) { - let temp_objs - 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 getType(target) { - let temp_objs = canvas.getObjects() - let i = 0 - for (let res of temp_objs) { - if (target == res) { - return objs[i].type - } - i++ - } -} - -function updateList() { - let str = '' - let i = 0 - for (let item of objs) { - switch (item.type) { - case 1 /* 2022-06-14修改*/: - str = '
IMG_" + i + '
' + str - break - case 2: - str = '
" + item.name + '
' + str - break - case 3: - str = '
" + 'TEXT_' + i + '
' + str - break - case 4: - str = '
" + item.name + '
' + str - break - case 5: - str = '
RECT_" + i + '
' + str - break - case 6: - str = '
CIRCLE_" + i + '
' + str - break - case 7: - str = '
LINE_" + i + '
' + str - break - case 8: - str = '
QRCODE_" + i + '
' + str - break - case 9: - str = '
BARCODE_" + i + '
' + str - break - case 10: - str = '
COUNTER_" + i + '
' + str - break - case 11: - str = "
" + "CIRCLE_TEXT_" + i + "
" + str; - break; - } - i++ - } - $('.obj_list').html(str) -} -function selectObj(i, notSelect = false) { - //for(let item in $(".obj_list").children()){ - $('.obj_list div').each(function (index) { - //if(index == i){ - if ($(this).children('img').attr('id') == 'obj' + i) { - $(this).css('background-color', '#6F7A84') - canvas.setActiveObject(canvas.getObjects()[i + 1]) - canvas.renderAll() - } else { - $(this).css('background-color', '') - } - }) - if (!notSelect) { - handleObjectSelected() - } -} -function recordState() { - //pre_objs.push(JSON.stringify(objs)); - ++step.val - for (let i = step.val; i < recordObjs.length; i++) { - recordObjs.pop() - recordJson.pop() - } - //recordObjs.splice(step.val, 1, JSON.stringify(objs)) - recordObjs.push(JSON.stringify(objs)) - j = canvas.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) - j.objects[0].hoverCursor = 'default' - recordJson.push(j) -} -function getCoordsMinX(acoords) { - x = acoords[0].x - for (let item of acoords) { - if (item.x < x) { - x = item.x - } - } - return x -} -function getCoordsMaxX(acoords) { - x = acoords[0].x - for (let item of acoords) { - if (item.x > x) { - x = item.x - } - } - return x -} -function getCoordsMinY(acoords) { - y = acoords[0].y - for (let item of acoords) { - if (item.y < y) { - y = item.y - } - } - return y -} -function getCoordsMaxY(acoords) { - y = acoords[0].y - for (let item of acoords) { - if (item.y > y) { - y = item.y - } - } - return y -} - -$('#text_y').bind('input propertychange', function () { - if ($('#text_y').val() == '') { - $('#text_y').val(0) - } - let val = background_image.top - if ($('#text_y').val() != '') { - val = background_image.top + parseInt($('#text_y').val()) - } - canvas.getActiveObject().set('top', val) - canvas.renderAll() - recordState() -}) -$('#text_x').bind('input propertychange', function () { - if ($('#text_x').val() == '') { - $('#text_x').val(0) - } - let val = background_image.left - if ($('#text_x').val() != '') { - val = background_image.left + parseInt($('#text_x').val()) - } - canvas.getActiveObject().set('left', val) - canvas.renderAll() - recordState() -}) -$('#text_w').bind('input propertychange', function () { - let val = '0' - if ($('#text_w').val() != '') { - val = $('#text_w').val() - } - let type = objs[getIndex(canvas.getActiveObject()) - 1].type - if (type == 3 || type == 4) { - canvas.getActiveObject().set('width', parseInt(val)) - } else { - canvas.getActiveObject().set('scaleX', parseInt(val) / canvas.getActiveObject().get('width')) - } - - canvas.renderAll() - recordState() -}) -$('#text_h').bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()) - if (objs[idx - 1].type == 7) { - if ($('#text_h').val() == '') { - $('#text_h').val(canvas.getActiveObject().get('strokeWidth')) - } - canvas.getActiveObject().set('strokeWidth', parseInt($('#text_h').val())) - canvas.renderAll() - return - } - let val = '0' - if ($('#text_h').val() != '') { - val = $('#text_h').val() - } - let type = objs[getIndex(canvas.getActiveObject()) - 1].type - if (type == 3 || type == 4) { - canvas.getActiveObject().set('height', parseInt(val)) - } else { - canvas.getActiveObject().set('scaleY', parseInt(val) / canvas.getActiveObject().get('height')) - } - - canvas.renderAll() - recordState() -}) -$('#text_r').bind('input propertychange', function () { - if ($('#text_r').val() == '') { - $('#text_r').val('0') - } - $('#text_r').val(parseInt($('#text_r').val()) % 360) - //canvas.getActiveObject().set("rotate", val) - canvas.getActiveObject().rotate(parseInt($('#text_r').val())) - canvas.renderAll() - recordState() -}) -$('#out_pic_field_name').bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].name = $('#out_pic_field_name').val() - updateList() - recordState() -}) - -$('#text_black').click(function () { - let idx = getIndex(canvas.getActiveObject()) - if ($(this).prop('checked')) { - objs[idx - 1].black = true - } else { - objs[idx - 1].black = false - } - recordState() -}) -// $("#out_pic_black").click(function () { -$('#out_text_field_name').bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].name = $('#out_text_field_name').val() - updateList() - recordState() -}) -$('#qrcode_field_name').bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].name = $('#qrcode_field_name').val() - updateList() - recordState() -}) -$('#qrcode_color').bind('input propertychange', function () { - let item = canvas.getActiveObject() - let qr = jrQrcode.getQrBase64('https://www.cardsoon.com', { padding: 0, foreground: $(this).val() }) - let idx = getIndex(item) - objs[idx - 1].color = $(this).val() - item.setSrc(qr, function (img) { - canvas.renderAll() - recordState() - }) -}) -$("#qrcode_val").bind('change', function () { - let val = $(this).val() ? $(this).val() : 'https://www.cardsoon.com' - let item = canvas.getActiveObject(); - let qr = jrQrcode.getQrBase64(val, { padding: 0, foreground: $("#qrcode_color").val() }); - let idx = getIndex(item); - objs[idx - 1].val = val; - item.setSrc(qr, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$('#barcode_color').bind('input propertychange', function () { - let item = canvas.getActiveObject() - let idx = getIndex(item) - objs[idx - 1].color = $(this).val() - JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) - let barcode = document.getElementById('barcode') - let bar = barcode.toDataURL('image/png') - item.setSrc(bar, function (img) { - canvas.renderAll() - recordState() - }) -}) -$('#barcode_field_name').bind('input propertychange', function () { - let idx = getIndex(canvas.getActiveObject()) - objs[idx - 1].name = $('#barcode_field_name').val() - updateList() - recordState() -}) -$('#text_color').bind('input propertychange', function () { - canvas.getActiveObject().set('fill', $('#text_color').val()) - canvas.renderAll() - recordState() -}) -$('#text_back_color').bind('input propertychange', function () { - canvas.getActiveObject().set('textBackgroundColor', $('#text_back_color').val()) - canvas.renderAll() - recordState() -}) -$('#out_text_back_color').bind('input propertychange', function () { - canvas.getActiveObject().set('textBackgroundColor', $('#out_text_back_color').val()) - - canvas.renderAll() - recordState() -}) -$("#text_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#text_size").val())) { - val = parseFloat($("#text_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#text_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -$("#circle_text_color").bind('input propertychange', function () { - canvas.getActiveObject().set("fill", $("#circle_text_color").val()); - canvas.renderAll(); - recordState(); -}) -$("#circle_text_back_color").bind('input propertychange', function () { - canvas.getActiveObject().set("textBackgroundColor", $("#circle_text_back_color").val()); - - canvas.renderAll(); - recordState(); -}) -$("#circle_text_text").bind('input propertychange', function () { - let val = $("#circle_text_text").val().trim() - canvas.getActiveObject().set("text", ` ${val} `); - canvas.renderAll(); - updateList(); - recordState(); -}) -$("#circle_text_center").click(function () { - let idx = getIndex(canvas.getActiveObject()); - if ($(this).prop("checked")) { - objs[idx - 1].circleCenter = 1; - } else { - objs[idx - 1].circleCenter = 0; - } - recordState(); -}); -$('#out_text_color').bind('input propertychange', function () { - canvas.getActiveObject().set('fill', $('#out_text_color').val()) - canvas.renderAll() - recordState() -}) -$("#out_text_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#out_text_size").val())) { - val = parseFloat($("#out_text_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#out_text_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -$('#out_text_text').bind('input propertychange', function () { - let val = $("#out_text_text").val().trim() - canvas.getActiveObject().set("text", ` ${val} `); - canvas.renderAll() - updateList() - recordState() -}) -$('#rect_color').bind('input propertychange', function () { - canvas.getActiveObject().set('fill', $('#rect_color').val()) - - canvas.renderAll() - recordState() -}) -$('#rect_stroke').bind('input propertychange', function () { - canvas.getActiveObject().set('stroke', $('#rect_stroke').val()) - - canvas.renderAll() - recordState() -}) -$('#rect_stroke_width').bind('input propertychange', function () { - if ($('#rect_stroke_width').val() == '') { - $('#rect_stroke_width').val('0') - } else { - $('#rect_stroke_width').val(parseInt($('#rect_stroke_width').val())) - } - canvas.getActiveObject().set('strokeWidth', parseInt($('#rect_stroke_width').val())) - canvas.renderAll() - recordState() -}) -$('#rect_radius').bind('input propertychange', function () { - if ($('#rect_radius').val() == '') { - $('#rect_radius').val('0') - } else { - $('#rect_radius').val(parseInt($('#rect_radius').val())) - } - canvas.getActiveObject().set('rx', parseInt($('#rect_radius').val())) - canvas.getActiveObject().set('ry', parseInt($('#rect_radius').val())) - canvas.renderAll() - recordState() -}) -$('#circle_color').bind('input propertychange', function () { - canvas.getActiveObject().set('fill', $('#circle_color').val()) - - canvas.renderAll() - recordState() -}) -$('#circle_stroke').bind('input propertychange', function () { - canvas.getActiveObject().set('stroke', $('#circle_stroke').val()) - - canvas.renderAll() - recordState() -}) -$('#circle_stroke_width').bind('input propertychange', function () { - if ($('#circle_stroke_width').val() == '') { - $('#circle_stroke_width').val('0') - } else { - $(this).val(parseInt($(this).val())) - } - canvas.getActiveObject().set('strokeWidth', parseInt($('#circle_stroke_width').val())) - canvas.renderAll() - recordState() -}) -$('#counter_start').bind('input propertychange', function () { - canvas.getActiveObject().set('text', $('#counter_start').val()) - let item = canvas.getActiveObject() - let idx = getIndex(item) - objs[idx - 1].start = $(this).val() - canvas.renderAll() - recordState() -}) -$('#counter_add').bind('input propertychange', function () { - let item = canvas.getActiveObject() - let idx = getIndex(item) - objs[idx - 1].add = $(this).val() - canvas.renderAll() - recordState() -}) -$('#counter_color').bind('input propertychange', function () { - canvas.getActiveObject().set('fill', $('#counter_color').val()) - canvas.renderAll() - recordState() -}) -$("#count_size").bind('input propertychange', function () { - let val = 1 - if (parseFloat($("#count_size").val())) { - val = parseFloat($("#count_size").val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#count_size").val(val) - canvas.getActiveObject().set("fontSize", val * dpi / 72); - $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); - $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); - canvas.renderAll(); - recordState(); -}) -$('#line_color').bind('input propertychange', function () { - canvas.getActiveObject().set('stroke', $('#line_color').val()) - canvas.renderAll() - recordState() -}) -$('#line_dist').bind('input propertychange', function () { - if ($('#line_dist').val() == '') { - $('#line_dist').val(0) - } - canvas.getActiveObject().set('strokeDashArray', [parseInt($('#line_dist').val()), parseInt($('#line_dist').val())]) - canvas.renderAll() - recordState() -}) -$('#text_text').bind('input propertychange', function () { - let val = $("#text_text").val().trim() - canvas.getActiveObject().set("text", ` ${val} `); - canvas.renderAll() - updateList() - recordState() -}) -$('#barcode_val').bind('input propertychange', function () { - let item = canvas.getActiveObject() - let idx = getIndex(item) - objs[idx - 1].val = $(this).val() - JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) - - let barcode = document.getElementById('barcode') - let bar = barcode.toDataURL('image/png') - item.setSrc(bar, function (img) { - canvas.renderAll() - recordState() - }) -}) -$("#barcode_show").click(function () { - let item = canvas.getActiveObject(); - let idx = getIndex(canvas.getActiveObject()); - let val = $("#barcode_size").val() - if ($(this).prop("checked")) { - objs[idx - 1].show = true; - val = 0 - } else { - objs[idx - 1].show = false; - } - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: val * dpi / 72, font: objs[idx - 1].font }); - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}); -$("#barcode_size").bind('input propertychange', function () { - let item = canvas.getActiveObject(); - let idx = getIndex(item); - let val = 1 - if (parseFloat($(this).val())) { - val = parseFloat($(this).val()) - if (val < 1) { - val = 1 - } else if (val > dpi) { - val = dpi - } else if (val % 0.5 !== 0) { - val = Math.round(val * 2) / 2 - } - - } - $("#barcode_size").val(val) - objs[idx - 1].fontSize = val * dpi / 72; - JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); - - let barcode = document.getElementById('barcode'); - let bar = barcode.toDataURL("image/png"); - item.setSrc(bar, function (img) { - canvas.renderAll(); - recordState(); - }); -}) -$('#count_font_family').on('change', function () { - canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) - canvas.renderAll() - recordState() -}) -$('#text_font_family').on('change', function () { - canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) - canvas.renderAll() - recordState() -}) - -$('#circle_text_font_family').on('change', function () { - canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) - canvas.renderAll() - recordState(); -}); - -$('#language_select').on('change', function () { - //语言选择 - langua_ge($(this).find('option:selected').val()) - s_lan = $(this).find('option:selected').val() - localStorage.setItem('lang', s_lan) -}) -$('#barcode_font_family').on('change', function () { - let item = canvas.getActiveObject() - let idx = getIndex(item) - objs[idx - 1].font = $(this).find('option:selected').text() - JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) - - let barcode = document.getElementById('barcode') - let bar = barcode.toDataURL('image/png') - item.setSrc(bar, function (img) { - canvas.renderAll() - recordState() - }) - //recordState(); -}) -$('#out_text_font_family').on('change', function () { - canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) - canvas.renderAll() - recordState() -}) -$('.obj_list').on('click', 'div', function () { - let idx = objs.length - 1 - $(this).index() - selectObj(idx) -}) -$('#exceed').click(function () { - let idx = getIndex(canvas.getActiveObject()) - if ($(this).prop('checked')) { - objs[idx - 1].exceed = true - } else { - objs[idx - 1].exceed = false - } - recordState() -}) -$('#autoWrap').click(function () { - let idx = getIndex(canvas.getActiveObject()) - if ($(this).prop('checked')) { - objs[idx - 1].autoWrap = true - } else { - objs[idx - 1].autoWrap = false - } - recordState() -}) -$('#fixSize').click(function () { - let idx = getIndex(canvas.getActiveObject()) - if ($(this).prop('checked')) { - objs[idx - 1].fixSize = true - } else { - objs[idx - 1].fixSize = false - } - recordState() -}) -$('#delete').click(function () { - let actObjs = canvas.getActiveObjects() - let allObjs = canvas.getObjects() - let flag = 0 - for (let item of actObjs) { - if (item != allObjs[0]) { - let i = getIndex(item) //0是背景,所以从1开始,但objs不包含背景图片,故要-1 - objs.splice(i - 1, 1) - canvas.remove(item) - flag = 1 - } - } - updateList() - canvas.discardActiveObject() - if (flag == 1) { - recordState() - canvas.renderAll() - } - // let actObjs = canvas.getActiveObjects(); -}) - -//在关于我们获取版本号。 -$("#about").click(async function () { - - // 1. 先异步获取版本号 - let version = "0.0.0"; // 默认值,防止获取失败 - try { - if (window.sysAPI && window.sysAPI.getAppVersion) { - const v = await window.sysAPI.getAppVersion(); - version = "v" + v; // 拼接一个 v,变成 v2.3.017 - } - } catch (e) { - console.error("获取版本号失败", e); - } - - // 2. 获取成功后再弹出窗口 - layer.open({ - type: 1 - , title: language_str("about") - , area: '450px;' - , id: 'LAY_layuipro' - , moveType: 1 - , content: '
' + - '
' + - '
Soon Design
' + - // 【修改点】这里使用了刚才获取到的 version 变量 - '
' + language_str("vers") + ' ' + version + '
' + - '
' + language_str("copyright") + '
' + - '
' - }); -}) -$("#help").click(() => { - ipcRenderer.send('open-help-file'); -}); - -// =========================================================== -$('#display').on('click', function () { - // 类型改变 - fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_2.png', function (i1) { - i1.left = background_image.left - i1.top = background_image.top - let img1 = i1 - - fabric.Image.fromURL('./public/images/back_bg_2.png', function (i2) { - i2.left = background_image.left - i2.top = background_image.top - let img2 = i2 - fabric.Image.fromURL('./public/images/op_2.png', function (i3) { - i2.left = background_image.left - i2.top = background_image.top - let img3 = i3 - display_func(img1, img2, img3); - }) - }) - }) -}); -$("#output").click(function () { - output(); // 调用output函数(在output.js中定义) -}); -function handleObjectSelected() { - let select_obj = canvas.getActiveObject() - if (!select_obj) { - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) //comfirm - return - } - - // 如果是辅助线,直接返回,不处理 - if (select_obj.isGuideLine) { - return - } - - let i = getIndex(select_obj) - if (i != 0) { - //不是背景 - --i - - // 安全检查:确保 objs[i] 存在且有 type 属性 - if (!objs[i] || typeof objs[i].type === 'undefined') { - return - } - - switch (objs[i].type) { - case 1: - //console.log("图片"); - $('#component_type').text(language_str('img')) //"图片" - selectObject(select_obj, i) - selectPic(select_obj, i) - break - case 2: - //console.log("预留图片"); - - $('#component_type').text(language_str('simg')) //"合成图片" - selectObject(select_obj, i) - selectOutPic(select_obj, i) - break - case 3: - $('#component_type').text(language_str('text')) //"文字" - //console.log("文字"); - selectObject(select_obj, i) - selectText(select_obj, i) - break - case 4: - //console.log("标签"); - - $('#component_type').text(language_str('stext')) //"合成文字" - selectObject(select_obj, i) - selectOutText(select_obj, i) - break - case 5: - //console.log("矩形"); - - $('#component_type').text(language_str('rect')) //"矩形" - selectObject(select_obj, i) - selectRect(select_obj, i) - break - case 6: - //console.log("圆形"); - - $('#component_type').text(language_str('circ')) //"圆形" - selectObject(select_obj, i) - selectCircle(select_obj, i) - break - case 7: - //console.log("直线"); - - $('#component_type').text(language_str('line')) //"直线" - selectObject(select_obj, i) - selectLine(select_obj, i) - break - case 8: - //console.log("二维码"); - - $('#component_type').text(language_str('qrc')) //"二维码" - selectObject(select_obj, i) - selectQrCode(select_obj, i) - break - case 9: - //console.log("条形码"); - - $('#component_type').text(language_str('barc')) //"条形码" - selectObject(select_obj, i) - selectBarCode(select_obj, i) - break - case 10: - //console.log("计数器"); - - $('#component_type').text(language_str('counter')) //"计数器" - selectObject(select_obj, i) - selectCounter(select_obj, i) - break - case 11: - - $("#component_type").text(language_str("ctext"));//"圆形文字" - //console.log("圆形文字"); - selectObject(select_obj, i); - selectCircleText(select_obj, i); - break; - } - } else { - //背景,收起对象属性 - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#counter_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#component_type').text(language_str('bg')) - } -} - -canvas1.on('mouse:move', (e) => { - if (!e.pointer || typeof background_image === 'undefined' || !background_image) return; - let width = canvas.getWidth() - let height = canvas.getHeight() - $('#posText').text( - 'X: ' + (e.pointer.x - (width / 2 - (width / 2 - background_image.left) * zoom)).toFixed(0) + ' Y: ' + (e.pointer.y - (height / 2 - (height / 2 - background_image.top) * zoom)).toFixed(0) - ) -}) -canvas1.on("object:moving", function (e) { - let obj = canvas1.getActiveObject() - let idx = getIndex(e.target, canvas1); - // 添加边界检查,避免访问 undefined - if (idx > 0 && idx <= objs1.length && objs1[idx - 1] && objs1[idx - 1].type && objs1[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) { - let pointer = { - x: obj.left, - y: obj.top - } - let distance = getDisdance(pointer.x, pointer.y, canvas1.width / 2, canvas1.height / 2) - let angleDeg = getDeg(pointer) - let flipped = pointer.y > canvas1.height / 2 ? true : false - if (typeof circle_text_diameter !== 'undefined' && circle_text_diameter.setValue) { - circle_text_diameter.setValue(distance * 2 - 50); - } - obj.set("diameter", distance * 2); - obj.set("angle", angleDeg); - obj.set("flipped", flipped); - } - updateControls(); -}); -canvas1.on('object:scaling', function (event) { - updateControls(); -}) -canvas1.on('object:rotating', function (e) { - updateControls() -}) -canvas1.on('object:rotated', function (e) { - recordState() -}) -canvas1.on('object:added', function (e) { - //recordState(); -}) -canvas1.on('mouse:down', (e) => { - //单选 - canvas = canvas1; - objs = objs1; - let select_obj = canvas.getActiveObject() - - // 如果是辅助线,直接返回,不处理 - if (select_obj && select_obj.isGuideLine) { - return - } - - let i = getIndex(select_obj, canvas) - if (i != 0) { - //不是背景 - --i - - // 安全检查:确保 objs[i] 存在且有 type 属性 - if (!objs[i] || typeof objs[i].type === 'undefined') { - return - } - - switch (objs[i].type) { - case 1: - $('#component_type').text(language_str('img')) - selectObject(select_obj, i) - selectPic(select_obj, i) - break - case 2: - $('#component_type').text(language_str('simg')) - selectObject(select_obj, i) - selectOutPic(select_obj, i) - break - case 3: - $('#component_type').text(language_str('text')) - selectObject(select_obj, i) - selectText(select_obj, i) - break - case 4: - $('#component_type').text(language_str('stext')) - selectObject(select_obj, i) - selectOutText(select_obj, i) - break - case 5: - $('#component_type').text(language_str('rect')) - selectObject(select_obj, i) - selectRect(select_obj, i) - break - case 6: - $('#component_type').text(language_str('circ')) - selectObject(select_obj, i) - selectCircle(select_obj, i) - break - case 7: - $('#component_type').text(language_str('line')) - selectObject(select_obj, i) - selectLine(select_obj, i) - break - case 8: - $('#component_type').text(language_str('qrc')) - selectObject(select_obj, i) - selectQrCode(select_obj, i) - break - case 9: - $('#component_type').text(language_str('barc')) - selectObject(select_obj, i) - selectBarCode(select_obj, i) - break - case 10: - $('#component_type').text(language_str('counter')) - selectObject(select_obj, i) - selectCounter(select_obj, i) - break - case 11: - $("#component_type").text(language_str("ctext")); - selectObject(select_obj, i); - selectCircleText(select_obj, i); - break; - } - selectObj(i, true) - } else { - //背景,收起对象属性 - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#counter_control').hide() - selectObj(-1) - $('#component_type').text(language_str('bg')) - } -}) -canvas1.on('text:editing:entered', function () { - _textEdit = true -}) -canvas1.on('text:editing:exited', function () { - _textEdit = false -}) -canvas1.on('object:modified', function (event) { - if (canvas1.getActiveObjects().length > 1) { - return - } - - // 跳过辅助线 - if (event.target.isGuideLine) { - return - } - - let idx = getIndex(event.target, canvas1); - if (idx <= 0) return; - - // 安全检查:确保 objs[idx - 1] 存在且有 type 属性 - if (!objs[idx - 1] || typeof objs[idx - 1].type === 'undefined') { - return - } - - if (objs[idx - 1].type == 3) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas1.renderAll() - updateControls() - } else if (objs[idx - 1].type == 4) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas1.renderAll() - } else if (objs[idx - 1].type == 10) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas1.renderAll() - } else if (objs[idx - 1].type == 5) { - canvas1.getActiveObject().set('width', canvas1.getActiveObject().get('width') * canvas1.getActiveObject().get('scaleX')) - canvas1.getActiveObject().set('height', canvas1.getActiveObject().get('height') * canvas1.getActiveObject().get('scaleY')) - canvas1.getActiveObject().set('scaleX', 1) - canvas1.getActiveObject().set('scaleY', 1) - updateControls() - } - recordState() -}) -canvas1.on('mouse:up', (e) => { - canvas = canvas1; - objs = objs1; - switch (addState) { - case 1: - addPic(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addPic').css('background-color', '') - break - case 2: - addOutPic(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addOutPic').css('background-color', '') - break - case 3: - addText(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addText').css('background-color', '') - break - case 4: - addOutText(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addOutText').css('background-color', '') - break - case 5: - addRect(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addRect').css('background-color', '') - break - case 6: - addCircle(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addCircle').css('background-color', '') - break - case 7: - addLine(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addLine').css('background-color', '') - break - case 8: - addQrCode(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addQrCode').css('background-color', '') - break - case 9: - addBarCode(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas1.renderAll() - $('#addBarCode').css('background-color', '') - break - case 10: - addCounter(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - $('#addCounter').css('background-color', '') - break - case 11: - addCircleText(e.pointer); - addState = 0; - background_image.hoverCursor = "default"; - canvas1.renderAll(); - $("#addCircleText").css("background-color", ""); - break; - } -}) -canvas1.on('text:changed', (e) => { - $('#text_text').val(e.target.get('text')) -}) -canvas1.on('after:render', function () { - if (is_bgi_add) { - var image = document.getElementById('source_front') - ctx1.drawImage(image, (canvas.width - $('#source_front').width()) / 2, (canvas.height - $('#source_front').height()) / 2, $('#source_front').width(), $('#source_front').height()) - } -}) -canvas2.on('text:editing:entered', function () { - _textEdit = true -}) -canvas2.on('text:editing:exited', function () { - _textEdit = false -}) -canvas2.on('after:render', function () { - if (is_bgi_add) { - var image = document.getElementById('source_back') - ctx2.drawImage(image, (canvas.width - $('#source_back').width()) / 2, (canvas1.height - $('#source_back').height()) / 2, $('#source_back').width(), $('#source_back').height()) - } -}) -canvas2.on('mouse:move', (e) => { - if (!e.pointer || typeof background_image === 'undefined' || !background_image) return; - canvas = canvas2; - objs = objs2; - $('#posText').text('X: ' + (e.pointer.x - background_image.left).toFixed(0) + ' Y: ' + (e.pointer.y - background_image.top).toFixed(0)) -}) -canvas2.on("object:moving", function (e) { - canvas = canvas2; - objs = objs2; - let obj = canvas2.getActiveObject() - let idx = getIndex(e.target, canvas2); - // 添加边界检查,避免访问 undefined - if (idx > 0 && idx <= objs2.length && objs2[idx - 1] && objs2[idx - 1].type && objs2[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) { - let pointer = { - x: obj.left, - y: obj.top - } - let distance = getDisdance(pointer.x, pointer.y, canvas2.width / 2, canvas2.height / 2) - // 计算角度时需要使用 canvas2 - let centerX = canvas2.width / 2; - let centerY = canvas2.height / 2; - let mouseX = pointer.x; - let mouseY = pointer.y; - let dx = mouseX - centerX; - let dy = mouseY - centerY; - let angleRad = Math.atan2(dy, dx); - let angleDeg = angleRad * (180 / Math.PI); - if (angleDeg < 0) { - angleDeg += 360; - } - angleDeg += 90; - let flipped = pointer.y > canvas2.height / 2 ? true : false - if (typeof circle_text_diameter !== 'undefined' && circle_text_diameter.setValue) { - circle_text_diameter.setValue(distance * 2 - 50); - } - obj.set("diameter", distance * 2); - obj.set("angle", angleDeg); - obj.set("flipped", flipped); - } - updateControls(); -}); -canvas2.on('object:scaling', function (e) { - canvas = canvas2; - objs = objs2; - updateControls() -}) -canvas2.on('object:rotating', function (e) { - canvas = canvas2; - objs = objs2; - updateControls() -}) -canvas2.on('object:rotated', function (e) { - canvas = canvas2; - objs = objs2; - recordState() -}) -canvas2.on('object:added', function (e) { - //recordState(); -}) -canvas2.on('mouse:down', (e) => { - //单选 - canvas = canvas2; - objs = objs2; - let select_obj = canvas.getActiveObject() - - // 如果是辅助线,直接返回,不处理 - if (select_obj && select_obj.isGuideLine) { - return - } - - let i = getIndex(select_obj, canvas) - if (i != 0) { - //不是背景 - --i - - // 安全检查:确保 objs[i] 存在且有 type 属性 - if (!objs[i] || typeof objs[i].type === 'undefined') { - return - } - - switch (objs[i].type) { - case 1: - $('#component_type').text(language_str('img')) - selectObject(select_obj, i) - selectPic(select_obj, i) - break - case 2: - $('#component_type').text(language_str('simg')) - selectObject(select_obj, i) - selectOutPic(select_obj, i) - break - case 3: - $('#component_type').text(language_str('text')) - selectObject(select_obj, i) - selectText(select_obj, i) - break - case 4: - $('#component_type').text(language_str('stext')) - selectObject(select_obj, i) - selectOutText(select_obj, i) - break - case 5: - $('#component_type').text(language_str('rect')) - selectObject(select_obj, i) - selectRect(select_obj, i) - break - case 6: - $('#component_type').text(language_str('circ')) - selectObject(select_obj, i) - selectCircle(select_obj, i) - break - case 7: - $('#component_type').text(language_str('line')) - selectObject(select_obj, i) - selectLine(select_obj, i) - break - case 8: - $('#component_type').text(language_str('qrc')) - selectObject(select_obj, i) - selectQrCode(select_obj, i) - break - case 9: - $('#component_type').text(language_str('barc')) - selectObject(select_obj, i) - selectBarCode(select_obj, i) - break - case 10: - $('#component_type').text(language_str('counter')) - selectObject(select_obj, i) - selectCounter(select_obj, i) - break - case 11: - $("#component_type").text(language_str("ctext")); - selectObject(select_obj, i); - selectCircleText(select_obj, i); - break; - } - selectObj(i, true) - } else { - //背景,收起对象属性 - $('#base_control').hide() - $('#line_control').hide() - $('#pic_control').hide() - $('#out_pic_control').hide() - $('#text_control').hide() - $("#circle_text_control").hide(); - $('#out_text_control').hide() - $('#rect_control').hide() - $('#circle_control').hide() - $('#qrcode_Controll').hide() - $('#barcode_controll').hide() - $('#counter_control').hide() - selectObj(-1) - $('#component_type').text(language_str('bg')) - } -}) -canvas2.on('object:modified', function (event) { - canvas = canvas2; - objs = objs2; - if (canvas.getActiveObjects().length > 1) { - return - } - - // 跳过辅助线 - if (event.target.isGuideLine) { - return - } - - let idx = getIndex(event.target, canvas2); - if (idx <= 0) return; - - // 安全检查:确保 objs[idx - 1] 存在且有 type 属性 - if (!objs[idx - 1] || typeof objs[idx - 1].type === 'undefined') { - return - } - - if (objs[idx - 1].type == 3) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas2.renderAll() - } else if (objs[idx - 1].type == 4) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas2.renderAll() - } else if (objs[idx - 1].type == 10) { - event.target.fontSize *= event.target.scaleX - event.target.fontSize = event.target.fontSize.toFixed(0) - event.target.scaleX = 1 - event.target.scaleY = 1 - event.target._clearCache() - canvas2.renderAll() - } else if (objs[idx - 1].type == 5) { - canvas2.getActiveObject().set('width', canvas2.getActiveObject().get('width') * canvas2.getActiveObject().get('scaleX')) - canvas2.getActiveObject().set('height', canvas2.getActiveObject().get('height') * canvas2.getActiveObject().get('scaleY')) - canvas2.getActiveObject().set('scaleX', 1) - canvas2.getActiveObject().set('scaleY', 1) - updateControls() - } - recordState() -}) -canvas2.on('mouse:up', (e) => { - canvas = canvas2; - objs = objs2; - switch (addState) { - case 1: - addPic(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addPic').css('background-color', '') - break - case 2: - addOutPic(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addOutPic').css('background-color', '') - break - case 3: - addText(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addText').css('background-color', '') - break - case 4: - addOutText(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addOutText').css('background-color', '') - break - case 5: - addRect(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addRect').css('background-color', '') - break - case 6: - addCircle(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addCircle').css('background-color', '') - break - case 7: - addLine(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addLine').css('background-color', '') - break - case 8: - addQrCode(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addQrCode').css('background-color', '') - break - case 9: - addBarCode(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - canvas2.renderAll() - $('#addBarCode').css('background-color', '') - break - case 10: - addCounter(e.pointer) - addState = 0 - background_image.hoverCursor = 'default' - $('#addCounter').css('background-color', '') - break - case 11: - addCircleText(e.pointer); - addState = 0; - background_image.hoverCursor = "default"; - canvas2.renderAll(); - $("#addCircleText").css("background-color", ""); - break; - } -}) +var _keyctrl = false, + _keyc = false, + _textEdit = false, + _inputEdit = false +$('input').focus(function () { + _inputEdit = true +}) +$('input').blur(function () { + _inputEdit = false +}) +$('textarea').focus(function () { + _inputEdit = true +}) +$('textarea').blur(function () { + _inputEdit = false +}) +$('body').keyup(function (event) { + // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) + if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释放 + _keyctrl = false + } + if (event.keyCode == 67) { + _keyc = false + } +}) +$('body').keydown(function (event) { + // 统一的快捷键处理(兼容 Windows/Linux: Ctrl, Mac: Cmd/Meta) + const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端 + + // 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的) + if (!_inputEdit && !_textEdit) { + // CTRL/CMD+N - 新建 + if (isModifierKey && event.keyCode == 78) { + event.preventDefault(); + $('#new').click(); + return; + } + // CTRL/CMD+O - 打开 + if (isModifierKey && event.keyCode == 79) { + event.preventDefault(); + $('#open').click(); + return; + } + // CTRL/CMD+S - 保存 + if (isModifierKey && !event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + $('#save').click(); + return; + } + // CTRL/CMD+SHIFT+S - 保存副本 + if (isModifierKey && event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + if (typeof window.output === 'function') { + window.output(null, saveAs); + } + return; + } + // CTRL/CMD+Z - 还原 + if (isModifierKey && !event.shiftKey && event.keyCode == 90) { + event.preventDefault(); + $('#previous').click(); + return; + } + // CTRL/CMD+Y - 重做 + if (isModifierKey && !event.shiftKey && event.keyCode == 89) { + event.preventDefault(); + $('#next').click(); + return; + } + // CTRL/CMD+C - 复制 + if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { + event.preventDefault(); + window.copySelection(); + return; + } + // CTRL/CMD+V - 粘贴 + if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { + event.preventDefault(); + window.pasteFromClipboard(); + return; + } + // CTRL/CMD+SHIFT+DEL - 清空 + if (isModifierKey && event.shiftKey && event.keyCode == 46) { + event.preventDefault(); + $('#clean').click(); + return; + } + // CTRL/CMD+DEL - 删除 + if (isModifierKey && !event.shiftKey && event.keyCode == 46) { + event.preventDefault(); + $('#delete').click(); + return; + } + } + // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) + if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd) + _keyctrl = true + if (_keyc && _textEdit) { + //同时按下且在编辑状态 + setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) + //clipboard.writeText((clipboard.readText()+' ')) + } + } + if (event.keyCode == 67) { + _keyc = true + if (_keyctrl & _textEdit) { + //同时按下且在编辑状态 + setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1) + //clipboard.writeText((clipboard.readText()+' ')) + } + } + if (event.keyCode == 37) { + //left + let v = -1 + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = -5 + } + if (canvas.getActiveObject()) { + let x = canvas.getActiveObject().get('left') + x += v + canvas.getActiveObject().set('left', x) + canvas.renderAll() + recordState() + updateControls() + } + } + if (event.keyCode == 38) { + //up + let v = -1 + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = -5 + } + if (canvas.getActiveObject()) { + let y = canvas.getActiveObject().get('top') + y += v + canvas.getActiveObject().set('top', y) + canvas.renderAll() + recordState() + updateControls() + } + } + if (event.keyCode == 39) { + //right + let v = 1 + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = 5 + } + if (canvas.getActiveObject()) { + let x = canvas.getActiveObject().get('left') + x += v + canvas.getActiveObject().set('left', x) + canvas.renderAll() + recordState() + updateControls() + } + } + if (event.keyCode == 40) { + //down + let v = +1 + if (_keyctrl || event.ctrlKey || event.metaKey) { + v = 5 + } + if (canvas.getActiveObject()) { + let y = canvas.getActiveObject().get('top') + y += v + canvas.getActiveObject().set('top', y) + canvas.renderAll() + recordState() + updateControls() + } + } + // 普通删除键(DEL键,没有按CTRL/CMD) + if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) { + // 使用 window.canvas 作为后备,确保在 eval() 加载 .jsc 时也能访问 + const currentCanvas = window.canvas || canvas; + const currentObjs = window.objs || objs; + if (!currentCanvas) { + console.error('canvas is undefined in delete handler'); + return; + } + let actObjs = currentCanvas.getActiveObjects() + let allObjs = currentCanvas.getObjects() + let flag = 0 + for (let item of actObjs) { + if (item != allObjs[0]) { + let i = getIndex(item, currentCanvas) //0是背景,所以从1开始,但objs不包含背景图片,故要-1 + currentObjs.splice(i - 1, 1) + currentCanvas.remove(item) + flag = 1 + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + currentCanvas.discardActiveObject() + if (flag == 1) { + recordState() + canvas.renderAll() + if (typeof window.handleObjectSelected === 'function') { + window.handleObjectSelected() + } + } + } +}) +// pre_add_image 已在 design2.js 中定义为全局变量 +$('#addPic').click(function () { + OpenDialog() + function OpenDialog() { + dialog + .showOpenDialog({ + title: language_str('selectPic'), //请选择图片 + buttonLabel: language_str('comf'), //"确认" + filters: [{ name: 'Image File Type', extensions: ['png', 'jpg', 'jpeg'] }] + }) + .then((result) => { + if (result.canceled) return + //console.log(result.filePaths) + fabric.Image.fromURL(result.filePaths[0], function (image) { + //image.left = pointer.x; + image.setSrc(image.toDataURL(), function (image) { + pre_add_image = image + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 1 + }) + //canvas.add(image); + }) + }) + .catch((err) => { + }) + } +}) +$('#addOutPic').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 2 +}) +$('#addText').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 3 +}) +$("#addCircleText").click(function () { + background_image.hoverCursor = "crosshair"; + $(this).css("background-color", "#646E76"); + + $("#addPic").css("background-color", ""); + $("#addOutPic").css("background-color", ""); + $("#addText").css("background-color", ""); + $("#addOutText").css("background-color", ""); + $("#addRect").css("background-color", ""); + $("#addCircle").css("background-color", ""); + $("#addLine").css("background-color", ""); + $("#addQrCode").css("background-color", ""); + $("#addBarCode").css("background-color", ""); + $("#addCounter").css("background-color", ""); + addState = 11; +}); +$('#addOutText').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 4 +}) +$('#addRect').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 5 +}) +$('#addCircle').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 6 +}) +$('#addLine').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 7 +}) +$('#addQrCode').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addBarCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 8 +}) +$('#addBarCode').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addCounter').css('background-color', '') + addState = 9 +}) +$('#addCounter').click(function () { + background_image.hoverCursor = 'crosshair' + $(this).css('background-color', '#646E76') + + $('#addPic').css('background-color', '') + $('#addOutPic').css('background-color', '') + $('#addText').css('background-color', '') + $("#addCircleText").css("background-color", ""); + $('#addOutText').css('background-color', '') + $('#addRect').css('background-color', '') + $('#addCircle').css('background-color', '') + $('#addLine').css('background-color', '') + $('#addQrCode').css('background-color', '') + $('#addBarCode').css('background-color', '') + addState = 10 +}) +$('#version_change').click(function () { + if (bg_version == 1) { + bg_version = 2 + } else { + bg_version = 1 + } + // 类型改变 + $('#source_front').attr('src', './public/images/front_bg' + bg_version + '_2.png') + canvas.renderAll() +}) +$('#front_side').click(function () { + $(this).addClass('ui-button-active') + $('#back_side').removeClass('ui-button-active') + $('.canvas-container:eq(0)').show() + $('.canvas-container:eq(1)').hide() + canvas = canvas1 + objs = objs1 + background_image = background_image1 + window.canvas = canvas; + window.objs = objs; + window.background_image = background_image; + next_objs = next_objs1 + pre_objs = pre_objs1 + next_json = next_json1 + pre_json = pre_json1 + recordObjs = recordObjs1 + recordJson = recordJson1 + step = step1 + if (typeof window.updateList === 'function') { + window.updateList(); + } + + $('#line_control').hide() + $('#base_control').hide() + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#component_type').text(language_str('bg')) //背景 +}) +$('#back_side').click(function () { + $(this).addClass('ui-button-active') + $('#front_side').removeClass('ui-button-active') + $('.canvas-container:eq(0)').hide() + $('.canvas-container:eq(1)').show() + canvas = canvas2 + objs = objs2 + background_image = background_image2 + window.canvas = canvas; + window.objs = objs; + window.background_image = background_image; + next_objs = next_objs2 + pre_objs = pre_objs2 + next_json = next_json2 + pre_json = pre_json2 + recordObjs = recordObjs2 + recordJson = recordJson2 + step = step2 + if (typeof window.updateList === 'function') { + window.updateList(); + } + $('#line_control').hide() + $('#base_control').hide() + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#component_type').text(language_str('bg')) //"背景" +}) +$('#top_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景顶部 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMinY = getCoordsMinY(coords) + let bgMinY = getCoordsMinY(background_image.getCoords(true)) + let deltaY = bgMinY - objMinY + obj.set('top', obj.get('top') + deltaY) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的最小Y值 + let minTop = Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinY = getCoordsMinY(coords) + if (itemMinY < minTop) { + minTop = itemMinY + } + } + // 将所有对象对齐到最小Y值 + groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinY = getCoordsMinY(coords) + let deltaY = minTop - itemMinY + item.set('top', item.get('top') + deltaY) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#bottom_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景底部 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMaxY = getCoordsMaxY(coords) + let bgMaxY = getCoordsMaxY(background_image.getCoords(true)) + let deltaY = bgMaxY - objMaxY + obj.set('top', obj.get('top') + deltaY) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的最大Y值 + let maxBottom = -Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMaxY = getCoordsMaxY(coords) + if (itemMaxY > maxBottom) { + maxBottom = itemMaxY + } + } + // 将所有对象对齐到最大Y值 + groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMaxY = getCoordsMaxY(coords) + let deltaY = maxBottom - itemMaxY + item.set('top', item.get('top') + deltaY) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#center_y_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景垂直中心 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMinY = getCoordsMinY(coords) + let objMaxY = getCoordsMaxY(coords) + let objCenterY = (objMinY + objMaxY) / 2 + let bgCoords = background_image.getCoords(true) + let bgMinY = getCoordsMinY(bgCoords) + let bgMaxY = getCoordsMaxY(bgCoords) + let bgCenterY = (bgMinY + bgMaxY) / 2 + let deltaY = bgCenterY - objCenterY + obj.set('top', obj.get('top') + deltaY) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的中心Y值 + let minTop = Infinity + let maxBottom = -Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinY = getCoordsMinY(coords) + let itemMaxY = getCoordsMaxY(coords) + if (itemMinY < minTop) minTop = itemMinY + if (itemMaxY > maxBottom) maxBottom = itemMaxY + } + let groupCenterY = (minTop + maxBottom) / 2 + // 将所有对象对齐到中心Y值 + groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinY = getCoordsMinY(coords) + let itemMaxY = getCoordsMaxY(coords) + let itemCenterY = (itemMinY + itemMaxY) / 2 + let deltaY = groupCenterY - itemCenterY + item.set('top', item.get('top') + deltaY) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#left_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景左边缘 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMinX = getCoordsMinX(coords) + let bgMinX = getCoordsMinX(background_image.getCoords(true)) + let deltaX = bgMinX - objMinX + obj.set('left', obj.get('left') + deltaX) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的最小X值 + let minLeft = Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinX = getCoordsMinX(coords) + if (itemMinX < minLeft) { + minLeft = itemMinX + } + } + // 将所有对象对齐到最小X值 + groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinX = getCoordsMinX(coords) + let deltaX = minLeft - itemMinX + item.set('left', item.get('left') + deltaX) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#right_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景右边缘 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMaxX = getCoordsMaxX(coords) + let bgMaxX = getCoordsMaxX(background_image.getCoords(true)) + let deltaX = bgMaxX - objMaxX + obj.set('left', obj.get('left') + deltaX) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的最大X值 + let maxRight = -Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMaxX = getCoordsMaxX(coords) + if (itemMaxX > maxRight) { + maxRight = itemMaxX + } + } + // 将所有对象对齐到最大X值 + let groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMaxX = getCoordsMaxX(coords) + let deltaX = maxRight - itemMaxX + item.set('left', item.get('left') + deltaX) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#center_x_alignment').click(function () { + let _objs = canvas.getActiveObjects() + if (_objs.length == 1) { + //只选中了一个,对齐到背景水平中心 + let obj = _objs[0] + obj.setCoords() + let coords = obj.getCoords(true) + let objMinX = getCoordsMinX(coords) + let objMaxX = getCoordsMaxX(coords) + let objCenterX = (objMinX + objMaxX) / 2 + let bgCoords = background_image.getCoords(true) + let bgMinX = getCoordsMinX(bgCoords) + let bgMaxX = getCoordsMaxX(bgCoords) + let bgCenterX = (bgMinX + bgMaxX) / 2 + let deltaX = bgCenterX - objCenterX + obj.set('left', obj.get('left') + deltaX) + obj.setCoords() + canvas.renderAll() + recordState() + return + } + // 多个对象对齐:找到所有对象边界框的中心X值 + let minLeft = Infinity + let maxRight = -Infinity + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinX = getCoordsMinX(coords) + let itemMaxX = getCoordsMaxX(coords) + if (itemMinX < minLeft) minLeft = itemMinX + if (itemMaxX > maxRight) maxRight = itemMaxX + } + let groupCenterX = (minLeft + maxRight) / 2 + // 将所有对象对齐到中心X值 + groupItems = [] + for (let item of _objs) { + item.setCoords() + let coords = item.getCoords(true) + let itemMinX = getCoordsMinX(coords) + let itemMaxX = getCoordsMaxX(coords) + let itemCenterX = (itemMinX + itemMaxX) / 2 + let deltaX = groupCenterX - itemCenterX + item.set('left', item.get('left') + deltaX) + item.setCoords() + groupItems.push(item) + } + canvas.discardActiveObject() + let sel = new fabric.ActiveSelection(groupItems, { + canvas: canvas + }) + canvas.setActiveObject(sel) + canvas.requestRenderAll() + canvas.renderAll() + recordState() +}) +$('#up_obj').click(function () { + //上移,放到前面 数组中在后面 + let idx = getIndex(canvas.getActiveObject()) + if (idx + 1 != canvas.getObjects().length) { + canvas.bringForward(canvas.getActiveObject()) + canvas.renderAll() + let temp = objs[idx - 1] + objs[idx - 1] = objs[idx] + objs[idx] = temp + //console.log(objs); + + recordState() + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx); + } + } +}) +$('#down_obj').click(function () { + //下移,放到后面 数组中在前面 + let idx = getIndex(canvas.getActiveObject()) + if (idx != 1) { + canvas.sendBackwards(canvas.getActiveObject()) + canvas.renderAll() + //[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]]; + + let temp = objs[idx - 1] + objs[idx - 1] = objs[idx - 2] + objs[idx - 2] = temp + recordState() + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(idx - 2); + } + } +}) +$('#set_bg').click(function () { + //设置为背景 + let obj = canvas.getActiveObject() + let idx = getIndex(canvas.getActiveObject()) + const scaleX = 1012 / obj.width + const scaleY = 648 / obj.height + // 使用缩放后的实际尺寸计算位置,确保与初始背景图片位置一致 + const scaledWidth = obj.width * scaleX; + const scaledHeight = obj.height * scaleY; + obj.set({ + scaleX: scaleX, + scaleY: scaleY, + left: ($('#canvas1').width() - scaledWidth) / 2, + top: ($('#canvas1').height() - scaledHeight) / 2 + }) + $('#text_w').val(1012) + $('#text_h').val(648) + $('#text_x').val(0) + $('#text_y').val(0) + // 设为背景时,锁定所有编辑操作,并设置为不可选中 + obj.set({ + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockSkewingX: true, + lockSkewingY: true, + selectable: false, + evented: false + }); + $("#lock_img").attr("src", "public/images/lock20.png") + canvas.sendToBack(canvas.getActiveObject()) + canvas.bringForward(canvas.getActiveObject()) + canvas.renderAll() + let objItem = objs.splice(idx - 1, 1)[0] + objs.unshift(objItem) + + // 确保背景图(索引0)的锁定属性被正确设置 + setTimeout(() => { + let bgObj = canvas.getObjects()[0]; + if (bgObj) { + bgObj.set({ + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockSkewingX: true, + lockSkewingY: true, + selectable: false, + evented: false + }); + canvas.renderAll(); + } + }, 100); + + recordState() + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (typeof window.selectObj === 'function') { + window.selectObj(0); + } +}) +$('#previous').click(function () { + //撤销一次操作 + if (step.val == 0) { + return + } + + step.val-- + if ($('#front_side').hasClass('ui-button-active')) { + // 使用 recordJson1 和 recordObjs1 + if (recordJson1 && recordJson1[step.val]) { + canvas.loadFromJSON(recordJson1[step.val]) + } + if (recordObjs1 && recordObjs1[step.val]) { + objs1 = JSON.parse(recordObjs1[step.val]) + objs = objs1 + } + } else if ($('#back_side').hasClass('ui-button-active')) { + // 使用 recordJson2 和 recordObjs2 + if (recordJson2 && recordJson2[step.val]) { + canvas.loadFromJSON(recordJson2[step.val]) + } + if (recordObjs2 && recordObjs2[step.val]) { + objs2 = JSON.parse(recordObjs2[step.val]) + objs = objs2 + } + } + + background_image = canvas.getObjects()[0] + canvas.renderAll() + //recordState(); + if (typeof window.updateList === 'function') { + window.updateList(); + } + + selectObj(-1) + + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +}) +$('#next').click(function () { + //撤销一次撤销操作 + // 根据当前是正面还是背面检查对应的 recordObjs 长度 + if ($('#front_side').hasClass('ui-button-active')) { + if (step.val >= recordObjs1.length - 1) { + return + } + } else if ($('#back_side').hasClass('ui-button-active')) { + if (step.val >= recordObjs2.length - 1) { + return + } + } + + ++step.val + if ($('#front_side').hasClass('ui-button-active')) { + // 使用 recordJson1 和 recordObjs1 + if (recordJson1 && recordJson1[step.val]) { + canvas.loadFromJSON(recordJson1[step.val]) + } + if (recordObjs1 && recordObjs1[step.val]) { + objs1 = JSON.parse(recordObjs1[step.val]) + objs = objs1 + } + } else if ($('#back_side').hasClass('ui-button-active')) { + // 使用 recordJson2 和 recordObjs2 + if (recordJson2 && recordJson2[step.val]) { + canvas.loadFromJSON(recordJson2[step.val]) + } + if (recordObjs2 && recordObjs2[step.val]) { + objs2 = JSON.parse(recordObjs2[step.val]) + objs = objs2 + } + } + background_image = canvas.getObjects()[0] + canvas.renderAll() + selectObj(-1) + + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + if (typeof window.updateList === 'function') { + window.updateList(); + } +}) +$('#clean').click(function () { + objs.splice(0, objs.length) + + let allObjs = canvas.getObjects() + for (let item of allObjs) { + if (item != allObjs[0]) { + canvas.remove(item) + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#rotate').click(function () { + let obj = canvas.getActiveObject() + obj.rotate(Math.round((obj.get('angle') + 90) % 360)) + $('#text_r').val(obj.get('angle')) + canvas.renderAll() + updateControls() + recordState() +}) +$('#vertical_obj').click(function () { + let obj = canvas.getActiveObject() + obj.set('flipY', !obj.get('flipY')) + canvas.renderAll() + updateControls() + recordState() +}) +$('#align_obj').click(function () { + let obj = canvas.getActiveObject() + obj.set('flipX', !obj.get('flipX')) + canvas.renderAll() + updateControls() + recordState() +}) +$('#text_italics').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('fontStyle', 'normal') + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('fontStyle', 'italic') + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#text_bold').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选,恢复正常 + canvas.getActiveObject().set('fontWeight', 'normal') + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('fontWeight', 'bold') + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#text_underline').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('underline', false) + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('underline', true) + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#text_linethrough').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('linethrough', false) + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('linethrough', true) + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$("#circle_text_italics").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选 + canvas.getActiveObject().set("fontStyle", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontStyle", "italic") + $(this).addClass("ui-radio-acitve") + } + recordState(); + canvas.renderAll(); +}); +$("#circle_text_bold").click(function () { + if ($(this).hasClass("ui-radio-acitve")) { + //已选,恢复正常 + canvas.getActiveObject().set("fontWeight", "normal") + $(this).removeClass("ui-radio-acitve") + } else { + //未选 + canvas.getActiveObject().set("fontWeight", "bold") + $(this).addClass("ui-radio-acitve") + } + recordState(); + canvas.renderAll(); +}); +$('#out_left_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_left_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'left') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'left' + recordState() + canvas.renderAll() +}) +$('#out_right_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_right_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'right') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'right' + recordState() + canvas.renderAll() +}) +$('#out_center_alignment').click(function () { + $('#out_left_alignment').parent().removeClass('tool1') + $('#out_right_alignment').parent().removeClass('tool1') + $('#out_center_alignment').parent().removeClass('tool1') + setTimeout(() => { + $('#out_center_alignment').parent().addClass('tool1') + }); + canvas.getActiveObject().set('textAlign', 'center') + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].align = 'center' + recordState() + canvas.renderAll() +}) +$('#out_text_italics').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('fontStyle', 'normal') + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('fontStyle', 'italic') + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#out_text_bold').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选,恢复正常 + canvas.getActiveObject().set('fontWeight', 'normal') + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('fontWeight', 'bold') + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#out_text_underline').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('underline', false) + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('underline', true) + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#out_text_linethrough').click(function () { + if ($(this).hasClass('ui-radio-acitve')) { + //已选 + canvas.getActiveObject().set('linethrough', false) + $(this).removeClass('ui-radio-acitve') + } else { + //未选 + canvas.getActiveObject().set('linethrough', true) + $(this).addClass('ui-radio-acitve') + } + recordState() + canvas.renderAll() +}) +$('#lock').off('click').on('click', function (e) { + e.stopPropagation(); + if (!canvas.getActiveObject()) return; + let obj = canvas.getActiveObject(); + // 检查是否已锁定(通过lockMovementX判断,因为锁定时会设置所有lock属性) + let isLocked = obj.get('lockMovementX') === true; + let shouldLock = !isLocked; + + // 锁定/解锁所有编辑操作,锁定后不可选中 + obj.set({ + lockMovementX: shouldLock, + lockMovementY: shouldLock, + lockRotation: shouldLock, + lockScalingX: shouldLock, + lockScalingY: shouldLock, + lockSkewingX: shouldLock, + lockSkewingY: shouldLock, + // 锁定时不可选中,解锁时可选中 + selectable: !shouldLock, + evented: !shouldLock + }); + if (shouldLock) { + $('#lock_img').attr('src', 'public/images/lock20.png') //已锁定 + // 锁定后取消选中 + canvas.discardActiveObject(); + canvas.renderAll(); + // 锁定后不需要调用 updateControls,因为已经没有选中对象了 + } else { + $('#lock_img').attr('src', 'public/images/unlock20.png') //已解锁 + // 解锁后更新控件 + updateControls(); + } + recordState() + // 更新对象列表以同步锁状态 + if (typeof window.updateList === 'function') { + window.updateList(); + } + if (!shouldLock) { + canvas.renderAll(); + } +}) +$('#text_back_transparent').click(function () { + canvas.getActiveObject().set('textBackgroundColor', '') + $('#text_back_color').val('#ffffff') + canvas.renderAll() +}) +$('#circle_text_back_transparent').click(function () { + canvas.getActiveObject().set('textBackgroundColor', '') + $('#circle_text_back_color').val('#ffffff') + canvas.renderAll() +}) +$('#out_text_back_transparent').click(function () { + canvas.getActiveObject().set('textBackgroundColor', '') + $('#out_text_back_color').val('#ffffff') + canvas.renderAll() +}) +$('#rect_transparent').click(function () { + canvas.getActiveObject().set('fill', '') + $('#rect_color').val('#ffffff') + canvas.renderAll() +}) +$('#rect_stroke_transparent').click(function () { + canvas.getActiveObject().set('stroke', '') + $('#rect_stroke').val('#ffffff') + canvas.renderAll() +}) +$('#circle_transparent').click(function () { + canvas.getActiveObject().set('fill', '') + $('#circle_color').val('#ffffff') + canvas.renderAll() +}) +$('#circle_stroke_transparent').click(function () { + canvas.getActiveObject().set('stroke', '') + $('#circle_stroke').val('#ffffff') + canvas.renderAll() +}) +// 清理不需要的 src 字段(保留自定义图片的 src) +// cleanupSrcFields 函数已在 output.js 中定义 + +function saveAs(op1, callback) { + let j = canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) + let b = canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) + + // 清理不需要的 src 字段(使用 window.cleanupSrcFields,在 output.js 中定义) + if (typeof window.cleanupSrcFields === 'function') { + window.cleanupSrcFields(j.objects, objs1); + window.cleanupSrcFields(b.objects, objs2); + } + + let o = { f: j, b: b, fo: objs1, bo: objs2 } + let con_o = Object.assign(o, op1) + dialog + .showSaveDialog({ + title: language_str('saveFile'), //'保存文件' + filters: [{ name: 'Soon File Type', extensions: ['soon'] }] + }) + .then((result) => { + if (result.filePath == '') { + return + } + if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) { + result.filePath += '.soon' + } + let fs = require('fs') + con_o.soonType = 2 + fs.writeFileSync(result.filePath, JSON.stringify(con_o), 'utf8') + openAs.name = result.filePath + layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至' + if (typeof window.saveHistory === 'function') { + window.saveHistory(); + } + if (callback && typeof callback === 'function') { + callback() + } + }) + .catch((err) => { + }) +} +// save 函数已在 output.js 中定义 +// 复制 +$("#copy").click(function () { + window.copySelection(); +}) +// 粘贴 +$("#paste").click(function () { + window.pasteFromClipboard(); +}) +// 保存按钮事件绑定 +$('#save').click(function () { + if (typeof window.output === 'function') { + window.output(); // 调用 output 函数 + } + return; +}) +function getDate() { + let date = new Date() + return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() +} +function getAbsoluteXY(_obj) { + let coord = _obj.get('lineCoords') + //let xs = [], ys = []; + return [_obj.get('left'), _obj.get('top')] +} +// fullPath, saveHistory 和 open 函数已在 output.js 中定义 +$('#open').click(function () { + if (step.val == 0) { + OpenDialog(); + return; + } + layer.confirm( + '' + language_str('whetherSave') + '', + function (index) { + if (typeof window.output === 'function') { + window.output(OpenDialog); + } + layer.close(index); + }, + function (index) { + OpenDialog(); + } + ) + function OpenDialog() { + dialog + .showOpenDialog({ + title: '请选择文件', + buttonLabel: language_str('comf'), + filters: [{ name: 'Soon File Type', extensions: ['soon'] }] + }) + .then((result) => { + if (result.canceled) return; + let filePath = result.filePaths[0]; + let fs = require('fs'); + let fsData = fs.readFileSync(filePath); + let j = JSON.parse(fsData.toString()); + let type = j.soonType ? j.soonType : j.backBlackPic ? 2 : 1; + + if (type == 1) { + ipcRenderer.send('open-design-page', filePath, type); + return; + } + + // 调用 output.js 中的 openFile 函数 + if (typeof window.openFile === 'function') { + window.openFile(filePath); + } else { + console.error('openFile 函数未定义!'); + } + }) + .catch((err) => { + console.log(err); + }) + } +}) +$('#new').click(function () { + if (step.val == 0) { + ipcRenderer.send('open-first-page'); + return; + } + layer.confirm( + '' + language_str('whetherSave') + '', + function (index) { + if (typeof window.output === 'function') { + window.output(() => ipcRenderer.send('open-first-page')); + } + layer.close(index); + }, + function (index) { + ipcRenderer.send('open-first-page'); + } + ) +}) +function chagneTitle() { } +function addBackground() { + // 类型改变 + fabric.Image.fromURL('./public/images/bg_front_2.png', function (image) { + //image.set("scaleX",$("#canvas-div").width() / 1200 < 1 ? $("#canvas-div").width() / 1200 : 1) + + image.left = ($('#canvas1').width() - image.width * image.get('scaleX')) / 2 + image.top = ($('#canvas1').height() - image.height * image.get('scaleY')) / 2 + + image.selectable = false + image.hoverable = false + image.hoverCursor = 'default' + image.setSrc(image.toDataURL(), function (image) { + background_image1 = image + background_image = background_image1 + canvas.add(image) + canvas.renderAll() + //pre_objs1.push(JSON.stringify(objs1)); + + recordObjs1.push(JSON.stringify(objs1)) + recordJson1.push(canvas1.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])) + }) + // 类型改变 + fabric.Image.fromURL('./public/images/bg_back_2.png', function (image) { + image.left = ($('#canvas2').width() - image.width) / 2 + image.top = ($('#canvas2').height() - image.height) / 2 + + image.selectable = false + image.hoverable = false + image.hoverCursor = 'default' + + image.setSrc(image.toDataURL(), function (image) { + background_image2 = image + canvas2.add(image) + canvas2.renderAll() + //pre_objs2.push(JSON.stringify(objs2)); + + recordObjs2.push(JSON.stringify(objs2)) + recordJson2.push(canvas2.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline'])) + + let file = GetFile().get('file') + if (file && file != 'empty') { + if (typeof window.openFile === 'function') { + window.openFile(file); + } else { + console.error('openFile 函数未定义!'); + } + } + }) + }) + is_bgi_add = true + }) +} +function selectObject(target, index) { + updateControls() + + $('#base_control').show() + //$("#text_x").val((target.left - background_image.left).toFixed(1)); +} +function updateControls() { + // 检查是否有选中对象,如果没有则直接返回 + if (!canvas || !canvas.getActiveObject()) return; + + const activeObj = canvas.getActiveObject(); + $('#text_r').val(activeObj.get('angle').toFixed(0)) + $('#text_x').val((activeObj.get('left') - background_image.left).toFixed(0)) + $('#text_y').val((activeObj.get('top') - background_image.top).toFixed(0)) + $('#text_h').val((activeObj.get('scaleY') * activeObj.get('height')).toFixed(0)) + $('#text_w').val((activeObj.get('scaleX') * activeObj.get('width')).toFixed(0)) + // 根据锁定状态显示图标(使用lockMovementX判断,因为锁定时会设置所有lock属性) + if (activeObj.get('lockMovementX')) { + $('#lock_img').attr('src', 'public/images/lock20.png') //已锁定 + } else { + $('#lock_img').attr('src', 'public/images/unlock20.png') //未锁定 + } +} +function checkName(name) { + //检查字段名是否重复了 + 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 resName(pre_name) { + //返回的是不重复的字段名 + let num = objs1.length + objs2.length - 1 + do { + num++ + } while (!checkName(pre_name + num)) //重复了就再加1 + return pre_name + num +} +function addPic(pointer) { + pre_add_image.left = pointer.x + pre_add_image.top = pointer.y + + canvas.add(pre_add_image) + + objs.push({ type: 1, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() + //OpenDialog(); +} +function selectPic(target, index) { + // 检查是否有选中对象,如果没有则直接返回 + if (!canvas || !canvas.getActiveObject()) return; + + let activeObj = canvas.getActiveObject(); + + // 检查对象是否被锁定或设为背景(索引0且已锁定) + let idx = getIndex(activeObj, canvas); + if (idx === 0) { + // 如果是背景图且已锁定,不应该显示图片控件 + if (activeObj.get('lockMovementX') === true || activeObj.get('selectable') === false) { + canvas.discardActiveObject(); + canvas.renderAll(); + return; + } + } + + //透明度 + $('#pic_control').show() + $("#set_bg").show(); + + // 检查 pic_op 是否存在且有 setValue 方法 + if (typeof pic_op !== 'undefined' && pic_op && typeof pic_op.setValue === 'function') { + pic_op.setValue(100 - activeObj.get('opacity') * 100); + } else { + $("#pic_op").next().children(".layui-slider-bar").css("width", (1 - activeObj.get("opacity")) * 100 + "%"); + $("#pic_op").next().children(".layui-slider-handle").css("left", (1 - activeObj.get("opacity")) * 100 + "%"); + } + + // $("#pic_black").prop("checked", objs[idx-1].black ? 'checked' : ''); + + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function addOutPic(pointer) { + fabric.Image.fromURL('./public/images/outpic_extra.png', function (image) { + let width = canvas.getWidth() + let height = canvas.getHeight() + image.left = pointer.x + image.top = pointer.y + image.opacity = 1 + //image.on("selected",function(){//test well + image.setSrc(image.toDataURL(), function (image) { + canvas.add(image) + objs.push({ type: 2, name: resName('OUT_PIC_'), black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() + }) + }) +} +function selectOutPic(target, index) { + //字段名 + $('#out_pic_control').show() + out_pic_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) + let idx = getIndex(canvas.getActiveObject()) + $('#out_pic_field_name').val(objs[idx - 1].name) + // $("#out_pic_black").prop("checked", objs[idx-1].black ? 'checked' : ''); + + $('#pic_control').hide() + $("#set_bg").hide(); + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} + +function addText(pointer) { + let text = new fabric.IText('TEXT', { + //源:文本 + left: pointer.x, + top: pointer.y, + fill: '#000000', + textBackgroundColor: '', + fontStyle: 'normal', + fontWeight: 'normal', + underline: false, + linethrough: false, + fontFamily: 'Arial' + }) + text.setControlVisible('ml', false) + text.setControlVisible('mt', false) + text.setControlVisible('mr', false) + text.setControlVisible('mb', false) + canvas.add(text) + objs.push({ type: 3, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectText() { + //console.log(canvas.getActiveObject().get("fontFamily")); + $('#text_control').show() + $('#text_color').val(canvas.getActiveObject().get('fill')) + $('#text_back_color').val(canvas.getActiveObject().get('textBackgroundColor') == '' ? '#ffffff' : canvas.getActiveObject().get('textBackgroundColor')) + let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi + if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 + $("#text_size").val(val); + $('#text_text').val(canvas.getActiveObject().get('text')) + $('#text_font_family').val(canvas.getActiveObject().get('fontFamily')) + + if (canvas.getActiveObject().get('underline') == true) { + $('#text_underline').addClass('ui-radio-acitve') + } else { + $('#text_underline').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('fontWeight') == 'bold') { + $('#text_bold').addClass('ui-radio-acitve') + } else { + $('#text_bold').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('fontStyle') == 'italic') { + $('#text_italics').addClass('ui-radio-acitve') + } else { + $('#text_italics').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('linethrough') == true) { + $('#text_linethrough').addClass('ui-radio-acitve') + } else { + $('#text_linethrough').removeClass('ui-radio-acitve') + } + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function getDisdance(x1, y1, x2, y2) { + var dx = Math.abs(x2 - x1); // 计算x轴上的距离差,并取绝对值 + var dy = Math.abs(y2 - y1); // 计算y轴上的距离差,并取绝对值 + var distance = Math.sqrt(dx * dx + dy * dy); // 应用勾股定理计算距离 + return distance; +} +function getDeg(pointer) { + // 计算点击位置与画布中心的坐标差 + var centerX = canvas.width / 2; + var centerY = canvas.height / 2; + var mouseX = pointer.x; + var mouseY = pointer.y; + var dx = mouseX - centerX; + var dy = mouseY - centerY; + // 计算旋转角度(弧度) + var angleRad = Math.atan2(dy, dx); + // 将角度转换为度数 + var angleDeg = angleRad * (180 / Math.PI); + if (angleDeg < 0) { + angleDeg += 360; + } + angleDeg += 90 + return angleDeg +} +function addCircleText(pointer) { + let distance = getDisdance(pointer.x, pointer.y, canvas.width / 2, canvas.height / 2) + let angleDeg = getDeg(pointer) + let text = new fabric.CurvedText('Circle TEXT', {//源:圆形文本 + left: pointer.x, + top: pointer.y, + fill: "#000000", + textBackgroundColor: "", + fontStyle: "normal", + fontWeight: "normal", + diameter: distance * 2, + fontSize: 30, + underline: false, + linethrough: false, + lockScalingX: true, + lockScalingY: true, + fontFamily: 'Arial', + originX: 'center', + originY: 'center', + angle: angleDeg, + flipped: pointer.y > canvas.height / 2 ? true : false + }); + // distance = getDisdance(pointer.x+text.width/2, pointer.y, canvas.width/2,canvas.height/2) + text.setControlVisible("ml", false); + text.setControlVisible("mt", false); + text.setControlVisible("mr", false); + text.setControlVisible("mb", false); + canvas.add(text); + objs.push({ type: 11, black: false, circleCenter: 0 }); + canvas.renderAll(); + if (typeof window.updateList === 'function') { + window.updateList(); + }; + recordState(); +} +function selectCircleText() { + let idx = getIndex(canvas.getActiveObject()); + $("#circle_text_control").show(); + $("#circle_text_color").val(canvas.getActiveObject().get("fill")); + $("#circle_text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor")); + if (typeof circle_text_size_updating !== 'undefined') { + circle_text_size_updating = true; + } + circle_text_size.setValue(canvas.getActiveObject().get("fontSize")); + if (typeof circle_text_size_updating !== 'undefined') { + circle_text_size_updating = false; + } + circle_text_diameter.setValue(canvas.getActiveObject().get("diameter")); + $("#circle_text_center").prop("checked", objs[idx - 1].circleCenter ? 'checked' : ''); + $("#circle_text_text").val(canvas.getActiveObject().get("text")); + $("#circle_text_font_family").val(canvas.getActiveObject().get("fontFamily")); + + if (canvas.getActiveObject().get("underline") == true) { + $("#circle_text_underline").addClass("ui-radio-acitve") + } else { + $("#circle_text_underline").removeClass("ui-radio-acitve") + } + if (canvas.getActiveObject().get("fontWeight") == "bold") { + $("#circle_text_bold").addClass("ui-radio-acitve") + } else { + $("#circle_text_bold").removeClass("ui-radio-acitve") + } + if (canvas.getActiveObject().get("fontStyle") == "italic") { + $("#circle_text_italics").addClass("ui-radio-acitve") + } else { + $("#circle_text_italics").removeClass("ui-radio-acitve") + } + if (canvas.getActiveObject().get("linethrough") == true) { + $("#circle_text_linethrough").addClass("ui-radio-acitve") + } else { + $("#circle_text_linethrough").removeClass("ui-radio-acitve") + } + $("#pic_control").hide(); + $("#set_bg").hide(); + $("#rotate").hide(); + $("#out_pic_control").hide(); + $("#text_control").hide(); + $("#out_text_control").hide(); + $("#rect_control").hide(); + $("#circle_control").hide(); + $("#line_control").hide(); + $("#counter_control").hide(); + $("#qrcode_Controll").hide(); + $("#barcode_controll").hide(); + +} +function addOutText(pointer) { + //MERGE_TEXT_1 + let text = new fabric.Text('MERGE TEXT', { + //源:合成文本 + left: pointer.x, + top: pointer.y, + fill: '#000000', + fontStyle: 'normal', + fontWeight: 'normal', + textBackgroundColor: '', + underline: false, + linethrough: false, + fontFamily: 'Arial', + textAlign: 'center' + }) + + //text.on({ + text.setControlVisible('ml', false) + text.setControlVisible('mt', false) + text.setControlVisible('mr', false) + text.setControlVisible('mb', false) + + canvas.add(text) + objs.push({ type: 4, name: resName('OUT_TEXT_'), exceed: false, autoWrap: false, fixSize: false, black: false, align: 'center' }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectOutText() { + //color + const align = canvas.getActiveObject().get('textAlign') + if (align === 'left') { + $('#out_left_alignment').parent().addClass('tool1') + } else if (align === 'right') { + $('#out_right_alignment').parent().addClass('tool1') + } else { + $('#out_center_alignment').parent().addClass('tool1') + } + $('#out_text_control').show() + $('#out_text_color').val(canvas.getActiveObject().get('fill')) + $('#out_text_text').val(canvas.getActiveObject().get('text')) + let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi + if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 + $("#out_text_size").val(val); + $('#out_text_back_color').val(canvas.getActiveObject().get('textBackgroundColor') == '' ? '#ffffff' : canvas.getActiveObject().get('textBackgroundColor')) + let idx = getIndex(canvas.getActiveObject()) + $('#out_text_field_name').val(objs[idx - 1].name) + $('#out_text_font_family').val(canvas.getActiveObject().get('fontFamily')) + $('#exceed').prop('checked', objs[idx - 1].exceed ? 'checked' : '') + $('#autoWrap').prop('checked', objs[idx - 1].autoWrap ? 'checked' : '') + $('#fixSize').prop('checked', objs[idx - 1].fixSize ? 'checked' : '') + if (canvas.getActiveObject().get('underline') == true) { + $('#out_text_underline').addClass('ui-radio-acitve') + } else { + $('#out_text_underline').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('fontWeight') == 'bold') { + $('#out_text_bold').addClass('ui-radio-acitve') + } else { + $('#out_text_bold').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('fontStyle') == 'italic') { + $('#out_text_italics').addClass('ui-radio-acitve') + } else { + $('#out_text_italics').removeClass('ui-radio-acitve') + } + if (canvas.getActiveObject().get('linethrough') == true) { + $('#out_text_linethrough').addClass('ui-radio-acitve') + } else { + $('#out_text_linethrough').removeClass('ui-radio-acitve') + } + + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#rect_control').hide() + $('#circle_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function addRect(pointer) { + let rect = new fabric.Rect({ + left: pointer.x, + top: pointer.y, + fill: '', + stroke: "#ff0000", + strokeWidth: 3, + width: 100, + height: 100 + }) + canvas.add(rect) + objs.push({ type: 5, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectRect() { + //color + $('#rect_control').show() + $('#rect_color').val(canvas.getActiveObject().get('fill') == '' ? '#ffffff' : canvas.getActiveObject().get('fill')) + $('#rect_stroke').val(canvas.getActiveObject().get('stroke') == '' ? '#ffffff' : canvas.getActiveObject().get('stroke')) + $('#rect_stroke_width').val(canvas.getActiveObject().get('strokeWidth')) + $('#rect_radius').val(canvas.getActiveObject().get('rx')) + rect_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) + let a = canvas.getActiveObject().getCoords() + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#circle_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function addCircle(pointer) { + let circle = new fabric.Circle({ + left: pointer.x, + top: pointer.y, + fill: '', + stroke: '#ff0000', + strokeWidth: 3, + radius: 100, + strokeUniform: true + }) + canvas.add(circle) + objs.push({ type: 6, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectCircle() { + //border-color + $('#circle_control').show() + $('#circle_color').val(canvas.getActiveObject().get('fill') == '' ? '#ffffff' : canvas.getActiveObject().get('fill')) + $('#circle_stroke').val(canvas.getActiveObject().get('stroke') == '' ? '#ffffff' : canvas.getActiveObject().get('stroke')) + $('#circle_stroke_width').val(canvas.getActiveObject().get('strokeWidth')) + circle_op.setValue(100 - canvas.getActiveObject().get('opacity') * 100) + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#line_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function addLine(pointer) { + let line = new fabric.Line([50, 100, 200, 100], { + left: pointer.x, + top: pointer.y, + stroke: '#ff0000', + strokeWidth: 3, + strokeDashArray: [0, 0], + }) + + line.setControlVisible('tl', false) + line.setControlVisible('tr', false) + line.setControlVisible('br', false) + line.setControlVisible('bl', false) + line.setControlVisible('mt', false) + line.setControlVisible('mb', false) + canvas.add(line) + objs.push({ type: 7, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectLine() { + //color + $('#line_control').show() + + let idx = getIndex(canvas.getActiveObject()) + $('#line_color').val(canvas.getActiveObject().get('stroke')) + $('#line_dist').val(canvas.getActiveObject().get('strokeDashArray')[0]) + $('#text_h').val(canvas.getActiveObject().get('strokeWidth')) + + $('#pic_control').hide() + $("#set_bg").hide(); + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function addQrCode(pointer) { + let qr = jrQrcode.getQrBase64('https://www.cardsoon.com', { padding: 0 }) + fabric.Image.fromURL(qr, function (image) { + image.left = pointer.x + image.top = pointer.y + canvas.add(image) + objs.push({ type: 8, name: resName('QR_CODE_'), color: '#000000', val: 'http://www.cardsoon.com', black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() + }) +} +function selectQrCode() { + //字段名 + $('#qrcode_Controll').show() + let idx = getIndex(canvas.getActiveObject()) + $('#qrcode_field_name').val(objs[idx - 1].name) + $('#qrcode_color').val(objs[idx - 1].color) + $('#qrcode_val').val(objs[idx - 1].val) + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#barcode_controll').hide() +} +function addBarCode(pointer) { + JsBarcode('#barcode', '123456789', { margin: 0, lineColor: '#000000', fontSize: 18, font: 'Arial' }) + let barcode = document.getElementById('barcode') + let bar = barcode.toDataURL('image/png') + fabric.Image.fromURL(bar, function (image) { + image.left = pointer.x + image.top = pointer.y + + canvas.add(image) + objs.push({ type: 9, name: resName('BAR_CODE_'), val: '123456789', color: '#000000', fontSize: 18, font: 'Arial', show: false, black: false }) //show是取消文字显示 + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() + }) +} +function selectBarCode() { + //字段名 + $('#barcode_controll').show() + let idx = getIndex(canvas.getActiveObject()) + $('#barcode_field_name').val(objs[idx - 1].name) + $('#barcode_font_family').val(objs[idx - 1].font) + let val = parseFloat(objs[idx - 1].fontSize) * 72 / dpi + if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 + $("#barcode_size").val(val); + $('#barcode_val').val(objs[idx - 1].val) + $('#barcode_show').prop('checked', objs[idx - 1].show ? 'checked' : '') + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() +} +function addCounter(pointer) { + let text = new fabric.Text('0', { + left: pointer.x, + top: pointer.y, + fill: '#000000' + }) + canvas.add(text) + objs.push({ type: 10, name: resName('COUNTER_'), start: 0, add: 1, black: false }) + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +} +function selectCounter() { + //起始 + $('#counter_control').show() + + let idx = getIndex(canvas.getActiveObject()) + $('#counter_start').val(objs[idx - 1].start) + $('#counter_add').val(objs[idx - 1].add) + $('#counter_color').val(canvas.getActiveObject().get('fill')) + $('#count_font_family').val(canvas.getActiveObject().get('fontFamily')) + let val = parseFloat(canvas.getActiveObject().get("fontSize")) * 72 / dpi + if (val % 0.5 !== 0) val = Math.round(val * 2) / 2 + $("#count_size").val(val); + + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() +} +function getIndex(target, _canvas = null) { + let temp_objs + 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 getType(target) { + let temp_objs = canvas.getObjects() + let i = 0 + for (let res of temp_objs) { + if (target == res) { + return objs[i].type + } + i++ + } +} + +// updateList 和 selectObj 函数在 core.js 中定义并附加到 window 对象 +function recordState() { + //pre_objs.push(JSON.stringify(objs)); + ++step.val + for (let i = step.val; i < recordObjs.length; i++) { + recordObjs.pop() + recordJson.pop() + } + //recordObjs.splice(step.val, 1, JSON.stringify(objs)) + recordObjs.push(JSON.stringify(objs)) + j = canvas.toJSON(['selectable', 'hoverable', 'hoverCursor', 'text', 'fontStyle', 'fontWeight', 'underline']) + j.objects[0].hoverCursor = 'default' + recordJson.push(j) +} +function getCoordsMinX(acoords) { + x = acoords[0].x + for (let item of acoords) { + if (item.x < x) { + x = item.x + } + } + return x +} +function getCoordsMaxX(acoords) { + x = acoords[0].x + for (let item of acoords) { + if (item.x > x) { + x = item.x + } + } + return x +} +function getCoordsMinY(acoords) { + y = acoords[0].y + for (let item of acoords) { + if (item.y < y) { + y = item.y + } + } + return y +} +function getCoordsMaxY(acoords) { + y = acoords[0].y + for (let item of acoords) { + if (item.y > y) { + y = item.y + } + } + return y +} + +$('#text_y').bind('input propertychange', function () { + if ($('#text_y').val() == '') { + $('#text_y').val(0) + } + let val = background_image.top + if ($('#text_y').val() != '') { + val = background_image.top + parseInt($('#text_y').val()) + } + canvas.getActiveObject().set('top', val) + canvas.renderAll() + recordState() +}) +$('#text_x').bind('input propertychange', function () { + if ($('#text_x').val() == '') { + $('#text_x').val(0) + } + let val = background_image.left + if ($('#text_x').val() != '') { + val = background_image.left + parseInt($('#text_x').val()) + } + canvas.getActiveObject().set('left', val) + canvas.renderAll() + recordState() +}) +$('#text_w').bind('input propertychange', function () { + let val = '0' + if ($('#text_w').val() != '') { + val = $('#text_w').val() + } + let type = objs[getIndex(canvas.getActiveObject()) - 1].type + if (type == 3 || type == 4) { + canvas.getActiveObject().set('width', parseInt(val)) + } else { + canvas.getActiveObject().set('scaleX', parseInt(val) / canvas.getActiveObject().get('width')) + } + + canvas.renderAll() + recordState() +}) +$('#text_h').bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()) + if (objs[idx - 1].type == 7) { + if ($('#text_h').val() == '') { + $('#text_h').val(canvas.getActiveObject().get('strokeWidth')) + } + canvas.getActiveObject().set('strokeWidth', parseInt($('#text_h').val())) + canvas.renderAll() + return + } + let val = '0' + if ($('#text_h').val() != '') { + val = $('#text_h').val() + } + let type = objs[getIndex(canvas.getActiveObject()) - 1].type + if (type == 3 || type == 4) { + canvas.getActiveObject().set('height', parseInt(val)) + } else { + canvas.getActiveObject().set('scaleY', parseInt(val) / canvas.getActiveObject().get('height')) + } + + canvas.renderAll() + recordState() +}) +$('#text_r').bind('input propertychange', function () { + if ($('#text_r').val() == '') { + $('#text_r').val('0') + } + $('#text_r').val(parseInt($('#text_r').val()) % 360) + //canvas.getActiveObject().set("rotate", val) + canvas.getActiveObject().rotate(parseInt($('#text_r').val())) + canvas.renderAll() + recordState() +}) +$('#out_pic_field_name').bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].name = $('#out_pic_field_name').val() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) + +$('#text_black').click(function () { + let idx = getIndex(canvas.getActiveObject()) + if ($(this).prop('checked')) { + objs[idx - 1].black = true + } else { + objs[idx - 1].black = false + } + recordState() +}) +// $("#out_pic_black").click(function () { +$('#out_text_field_name').bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].name = $('#out_text_field_name').val() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#qrcode_field_name').bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].name = $('#qrcode_field_name').val() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#qrcode_color').bind('input propertychange', function () { + let item = canvas.getActiveObject() + let qr = jrQrcode.getQrBase64('https://www.cardsoon.com', { padding: 0, foreground: $(this).val() }) + let idx = getIndex(item) + objs[idx - 1].color = $(this).val() + item.setSrc(qr, function (img) { + canvas.renderAll() + recordState() + }) +}) +$("#qrcode_val").bind('change', function () { + let val = $(this).val() ? $(this).val() : 'https://www.cardsoon.com' + let item = canvas.getActiveObject(); + let qr = jrQrcode.getQrBase64(val, { padding: 0, foreground: $("#qrcode_color").val() }); + let idx = getIndex(item); + objs[idx - 1].val = val; + item.setSrc(qr, function (img) { + canvas.renderAll(); + recordState(); + }); +}); +$('#barcode_color').bind('input propertychange', function () { + let item = canvas.getActiveObject() + let idx = getIndex(item) + objs[idx - 1].color = $(this).val() + JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) + let barcode = document.getElementById('barcode') + let bar = barcode.toDataURL('image/png') + item.setSrc(bar, function (img) { + canvas.renderAll() + recordState() + }) +}) +$('#barcode_field_name').bind('input propertychange', function () { + let idx = getIndex(canvas.getActiveObject()) + objs[idx - 1].name = $('#barcode_field_name').val() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#text_color').bind('input propertychange', function () { + canvas.getActiveObject().set('fill', $('#text_color').val()) + canvas.renderAll() + recordState() +}) +$('#text_back_color').bind('input propertychange', function () { + canvas.getActiveObject().set('textBackgroundColor', $('#text_back_color').val()) + canvas.renderAll() + recordState() +}) +$('#out_text_back_color').bind('input propertychange', function () { + canvas.getActiveObject().set('textBackgroundColor', $('#out_text_back_color').val()) + + canvas.renderAll() + recordState() +}) +$("#text_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#text_size").val())) { + val = parseFloat($("#text_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#text_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + recordState(); +}) +$("#circle_text_color").bind('input propertychange', function () { + canvas.getActiveObject().set("fill", $("#circle_text_color").val()); + canvas.renderAll(); + recordState(); +}) +$("#circle_text_back_color").bind('input propertychange', function () { + canvas.getActiveObject().set("textBackgroundColor", $("#circle_text_back_color").val()); + + canvas.renderAll(); + recordState(); +}) +$("#circle_text_text").bind('input propertychange', function () { + let val = $("#circle_text_text").val().trim() + canvas.getActiveObject().set("text", ` ${val} `); + canvas.renderAll(); + if (typeof window.updateList === 'function') { + window.updateList(); + }; + recordState(); +}) +$("#circle_text_center").click(function () { + let idx = getIndex(canvas.getActiveObject()); + if ($(this).prop("checked")) { + objs[idx - 1].circleCenter = 1; + } else { + objs[idx - 1].circleCenter = 0; + } + recordState(); +}); +$('#out_text_color').bind('input propertychange', function () { + canvas.getActiveObject().set('fill', $('#out_text_color').val()) + canvas.renderAll() + recordState() +}) +$("#out_text_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#out_text_size").val())) { + val = parseFloat($("#out_text_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#out_text_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + recordState(); +}) +$('#out_text_text').bind('input propertychange', function () { + let val = $("#out_text_text").val().trim() + canvas.getActiveObject().set("text", ` ${val} `); + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#rect_color').bind('input propertychange', function () { + canvas.getActiveObject().set('fill', $('#rect_color').val()) + + canvas.renderAll() + recordState() +}) +$('#rect_stroke').bind('input propertychange', function () { + canvas.getActiveObject().set('stroke', $('#rect_stroke').val()) + + canvas.renderAll() + recordState() +}) +$('#rect_stroke_width').bind('input propertychange', function () { + if ($('#rect_stroke_width').val() == '') { + $('#rect_stroke_width').val('0') + } else { + $('#rect_stroke_width').val(parseInt($('#rect_stroke_width').val())) + } + canvas.getActiveObject().set('strokeWidth', parseInt($('#rect_stroke_width').val())) + canvas.renderAll() + recordState() +}) +$('#rect_radius').bind('input propertychange', function () { + if ($('#rect_radius').val() == '') { + $('#rect_radius').val('0') + } else { + $('#rect_radius').val(parseInt($('#rect_radius').val())) + } + canvas.getActiveObject().set('rx', parseInt($('#rect_radius').val())) + canvas.getActiveObject().set('ry', parseInt($('#rect_radius').val())) + canvas.renderAll() + recordState() +}) +$('#circle_color').bind('input propertychange', function () { + canvas.getActiveObject().set('fill', $('#circle_color').val()) + + canvas.renderAll() + recordState() +}) +$('#circle_stroke').bind('input propertychange', function () { + canvas.getActiveObject().set('stroke', $('#circle_stroke').val()) + + canvas.renderAll() + recordState() +}) +$('#circle_stroke_width').bind('input propertychange', function () { + if ($('#circle_stroke_width').val() == '') { + $('#circle_stroke_width').val('0') + } else { + $(this).val(parseInt($(this).val())) + } + canvas.getActiveObject().set('strokeWidth', parseInt($('#circle_stroke_width').val())) + canvas.renderAll() + recordState() +}) +$('#counter_start').bind('input propertychange', function () { + canvas.getActiveObject().set('text', $('#counter_start').val()) + let item = canvas.getActiveObject() + let idx = getIndex(item) + objs[idx - 1].start = $(this).val() + canvas.renderAll() + recordState() +}) +$('#counter_add').bind('input propertychange', function () { + let item = canvas.getActiveObject() + let idx = getIndex(item) + objs[idx - 1].add = $(this).val() + canvas.renderAll() + recordState() +}) +$('#counter_color').bind('input propertychange', function () { + canvas.getActiveObject().set('fill', $('#counter_color').val()) + canvas.renderAll() + recordState() +}) +$("#count_size").bind('input propertychange', function () { + let val = 1 + if (parseFloat($("#count_size").val())) { + val = parseFloat($("#count_size").val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#count_size").val(val) + canvas.getActiveObject().set("fontSize", val * dpi / 72); + $("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0)); + $("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0)); + canvas.renderAll(); + recordState(); +}) +$('#line_color').bind('input propertychange', function () { + canvas.getActiveObject().set('stroke', $('#line_color').val()) + canvas.renderAll() + recordState() +}) +$('#line_dist').bind('input propertychange', function () { + if ($('#line_dist').val() == '') { + $('#line_dist').val(0) + } + canvas.getActiveObject().set('strokeDashArray', [parseInt($('#line_dist').val()), parseInt($('#line_dist').val())]) + canvas.renderAll() + recordState() +}) +$('#text_text').bind('input propertychange', function () { + let val = $("#text_text").val().trim() + canvas.getActiveObject().set("text", ` ${val} `); + canvas.renderAll() + if (typeof window.updateList === 'function') { + window.updateList(); + } + recordState() +}) +$('#barcode_val').bind('input propertychange', function () { + let item = canvas.getActiveObject() + let idx = getIndex(item) + objs[idx - 1].val = $(this).val() + JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) + + let barcode = document.getElementById('barcode') + let bar = barcode.toDataURL('image/png') + item.setSrc(bar, function (img) { + canvas.renderAll() + recordState() + }) +}) +$("#barcode_show").click(function () { + let item = canvas.getActiveObject(); + let idx = getIndex(canvas.getActiveObject()); + let val = $("#barcode_size").val() + if ($(this).prop("checked")) { + objs[idx - 1].show = true; + val = 0 + } else { + objs[idx - 1].show = false; + } + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: val * dpi / 72, font: objs[idx - 1].font }); + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + recordState(); + }); +}); +$("#barcode_size").bind('input propertychange', function () { + let item = canvas.getActiveObject(); + let idx = getIndex(item); + let val = 1 + if (parseFloat($(this).val())) { + val = parseFloat($(this).val()) + if (val < 1) { + val = 1 + } else if (val > dpi) { + val = dpi + } else if (val % 0.5 !== 0) { + val = Math.round(val * 2) / 2 + } + + } + $("#barcode_size").val(val) + objs[idx - 1].fontSize = val * dpi / 72; + JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }); + + let barcode = document.getElementById('barcode'); + let bar = barcode.toDataURL("image/png"); + item.setSrc(bar, function (img) { + canvas.renderAll(); + recordState(); + }); +}) +$('#count_font_family').on('change', function () { + canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) + canvas.renderAll() + recordState() +}) +$('#text_font_family').on('change', function () { + canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) + canvas.renderAll() + recordState() +}) + +$('#circle_text_font_family').on('change', function () { + canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text()) + canvas.renderAll() + recordState(); +}); + +$('#language_select').on('change', function () { + //语言选择 + langua_ge($(this).find('option:selected').val()) + s_lan = $(this).find('option:selected').val() + localStorage.setItem('lang', s_lan) +}) +$('#barcode_font_family').on('change', function () { + let item = canvas.getActiveObject() + let idx = getIndex(item) + objs[idx - 1].font = $(this).find('option:selected').text() + JsBarcode('#barcode', objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font }) + + let barcode = document.getElementById('barcode') + let bar = barcode.toDataURL('image/png') + item.setSrc(bar, function (img) { + canvas.renderAll() + recordState() + }) + //recordState(); +}) +$('#out_text_font_family').on('change', function () { + canvas.getActiveObject().set('fontFamily', $(this).find('option:selected').text()) + canvas.renderAll() + recordState() +}) +$('.obj_list').on('click', 'div', function () { + let idx = objs.length - 1 - $(this).index() + selectObj(idx) +}) +$('#exceed').click(function () { + let idx = getIndex(canvas.getActiveObject()) + if ($(this).prop('checked')) { + objs[idx - 1].exceed = true + } else { + objs[idx - 1].exceed = false + } + recordState() +}) +$('#autoWrap').click(function () { + let idx = getIndex(canvas.getActiveObject()) + if ($(this).prop('checked')) { + objs[idx - 1].autoWrap = true + } else { + objs[idx - 1].autoWrap = false + } + recordState() +}) +$('#fixSize').click(function () { + let idx = getIndex(canvas.getActiveObject()) + if ($(this).prop('checked')) { + objs[idx - 1].fixSize = true + } else { + objs[idx - 1].fixSize = false + } + recordState() +}) +$('#delete').click(function () { + let actObjs = canvas.getActiveObjects() + let allObjs = canvas.getObjects() + let flag = 0 + for (let item of actObjs) { + if (item != allObjs[0]) { + let i = getIndex(item) //0是背景,所以从1开始,但objs不包含背景图片,故要-1 + objs.splice(i - 1, 1) + canvas.remove(item) + flag = 1 + } + } + if (typeof window.updateList === 'function') { + window.updateList(); + } + canvas.discardActiveObject() + if (flag == 1) { + recordState() + canvas.renderAll() + } + // let actObjs = canvas.getActiveObjects(); +}) + +//在关于我们获取版本号。 +$("#about").click(async function () { + + // 1. 先异步获取版本号 + let version = "0.0.0"; // 默认值,防止获取失败 + try { + if (window.sysAPI && window.sysAPI.getAppVersion) { + const v = await window.sysAPI.getAppVersion(); + version = "v" + v; // 拼接一个 v,变成 v2.3.017 + } + } catch (e) { + console.error("获取版本号失败", e); + } + + // 2. 获取成功后再弹出窗口 + layer.open({ + type: 1 + , title: language_str("about") + , area: '450px;' + , id: 'LAY_layuipro' + , moveType: 1 + , content: '
' + + '
' + + '
Soon Design
' + + // 【修改点】这里使用了刚才获取到的 version 变量 + '
' + language_str("vers") + ' ' + version + '
' + + '
' + language_str("copyright") + '
' + + '
' + }); +}) +$("#help").click(() => { + ipcRenderer.send('open-help-file'); +}); + +// =========================================================== +$('#display').off('click').on('click', function () { + // 类型改变 + fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_2.png', function (i1) { + i1.left = background_image.left + i1.top = background_image.top + let img1 = i1 + + fabric.Image.fromURL('./public/images/back_bg_2.png', function (i2) { + i2.left = background_image.left + i2.top = background_image.top + let img2 = i2 + fabric.Image.fromURL('./public/images/op_2.png', function (i3) { + i2.left = background_image.left + i2.top = background_image.top + let img3 = i3 + if (typeof window.display_func === 'function') { + window.display_func(img1, img2, img3); + } + }) + }) + }) +}); +$("#output").click(function () { + // 另存为:传递 saveAs 函数作为第二个参数 + if (typeof window.output === 'function') { + window.output(null, saveAs); // 调用output函数,使用saveAs进行另存为 + } +}); +function handleObjectSelected() { + let select_obj = canvas.getActiveObject() + if (!select_obj) { + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#component_type').text(language_str('bg')) //comfirm + return + } + + // 如果是辅助线,直接返回,不处理 + if (select_obj.isGuideLine) { + return + } + + let i = getIndex(select_obj) + if (i != 0) { + //不是背景 + --i + + // 安全检查:确保 objs[i] 存在且有 type 属性 + if (!objs[i] || typeof objs[i].type === 'undefined') { + return + } + + switch (objs[i].type) { + case 1: + //console.log("图片"); + $('#component_type').text(language_str('img')) //"图片" + selectObject(select_obj, i) + selectPic(select_obj, i) + break + case 2: + //console.log("预留图片"); + + $('#component_type').text(language_str('simg')) //"合成图片" + selectObject(select_obj, i) + selectOutPic(select_obj, i) + break + case 3: + $('#component_type').text(language_str('text')) //"文字" + //console.log("文字"); + selectObject(select_obj, i) + selectText(select_obj, i) + break + case 4: + //console.log("标签"); + + $('#component_type').text(language_str('stext')) //"合成文字" + selectObject(select_obj, i) + selectOutText(select_obj, i) + break + case 5: + //console.log("矩形"); + + $('#component_type').text(language_str('rect')) //"矩形" + selectObject(select_obj, i) + selectRect(select_obj, i) + break + case 6: + //console.log("圆形"); + + $('#component_type').text(language_str('circ')) //"圆形" + selectObject(select_obj, i) + selectCircle(select_obj, i) + break + case 7: + //console.log("直线"); + + $('#component_type').text(language_str('line')) //"直线" + selectObject(select_obj, i) + selectLine(select_obj, i) + break + case 8: + //console.log("二维码"); + + $('#component_type').text(language_str('qrc')) //"二维码" + selectObject(select_obj, i) + selectQrCode(select_obj, i) + break + case 9: + //console.log("条形码"); + + $('#component_type').text(language_str('barc')) //"条形码" + selectObject(select_obj, i) + selectBarCode(select_obj, i) + break + case 10: + //console.log("计数器"); + + $('#component_type').text(language_str('counter')) //"计数器" + selectObject(select_obj, i) + selectCounter(select_obj, i) + break + case 11: + + $("#component_type").text(language_str("ctext"));//"圆形文字" + //console.log("圆形文字"); + selectObject(select_obj, i); + selectCircleText(select_obj, i); + break; + } + } else { + //背景,收起对象属性 + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#counter_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#component_type').text(language_str('bg')) + } +} + +// 防止重复初始化事件监听器 +if (typeof window._design2CanvasEventsInitialized === 'undefined') { + window._design2CanvasEventsInitialized = true; + + canvas1.on('mouse:move', (e) => { + if (!e.pointer || typeof background_image === 'undefined' || !background_image) return; + let width = canvas.getWidth() + let height = canvas.getHeight() + $('#posText').text( + 'X: ' + (e.pointer.x - (width / 2 - (width / 2 - background_image.left) * zoom)).toFixed(0) + ' Y: ' + (e.pointer.y - (height / 2 - (height / 2 - background_image.top) * zoom)).toFixed(0) + ) + }) + canvas1.on("object:moving", function (e) { + let obj = canvas1.getActiveObject() + let idx = getIndex(e.target, canvas1); + // 添加边界检查,避免访问 undefined + if (idx > 0 && idx <= objs1.length && objs1[idx - 1] && objs1[idx - 1].type && objs1[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) { + let pointer = { + x: obj.left, + y: obj.top + } + let distance = getDisdance(pointer.x, pointer.y, canvas1.width / 2, canvas1.height / 2) + let angleDeg = getDeg(pointer) + let flipped = pointer.y > canvas1.height / 2 ? true : false + if (typeof circle_text_diameter !== 'undefined' && circle_text_diameter.setValue) { + circle_text_diameter.setValue(distance * 2 - 50); + } + obj.set("diameter", distance * 2); + obj.set("angle", angleDeg); + obj.set("flipped", flipped); + } + updateControls(); + }); + canvas1.on('object:scaling', function (event) { + updateControls(); + }) + canvas1.on('object:rotating', function (e) { + updateControls() + }) + canvas1.on('object:rotated', function (e) { + recordState() + }) + canvas1.on('object:added', function (e) { + //recordState(); + }) + canvas1.on('mouse:down', (e) => { + //单选 + canvas = canvas1; + objs = objs1; + let select_obj = canvas.getActiveObject() + + // 如果是辅助线,直接返回,不处理 + if (select_obj && select_obj.isGuideLine) { + return + } + + let i = getIndex(select_obj, canvas) + if (i != 0) { + //不是背景 + --i + + // 安全检查:确保 objs[i] 存在且有 type 属性 + if (!objs[i] || typeof objs[i].type === 'undefined') { + return + } + + switch (objs[i].type) { + case 1: + $('#component_type').text(language_str('img')) + selectObject(select_obj, i) + selectPic(select_obj, i) + break + case 2: + $('#component_type').text(language_str('simg')) + selectObject(select_obj, i) + selectOutPic(select_obj, i) + break + case 3: + $('#component_type').text(language_str('text')) + selectObject(select_obj, i) + selectText(select_obj, i) + break + case 4: + $('#component_type').text(language_str('stext')) + selectObject(select_obj, i) + selectOutText(select_obj, i) + break + case 5: + $('#component_type').text(language_str('rect')) + selectObject(select_obj, i) + selectRect(select_obj, i) + break + case 6: + $('#component_type').text(language_str('circ')) + selectObject(select_obj, i) + selectCircle(select_obj, i) + break + case 7: + $('#component_type').text(language_str('line')) + selectObject(select_obj, i) + selectLine(select_obj, i) + break + case 8: + $('#component_type').text(language_str('qrc')) + selectObject(select_obj, i) + selectQrCode(select_obj, i) + break + case 9: + $('#component_type').text(language_str('barc')) + selectObject(select_obj, i) + selectBarCode(select_obj, i) + break + case 10: + $('#component_type').text(language_str('counter')) + selectObject(select_obj, i) + selectCounter(select_obj, i) + break + case 11: + $("#component_type").text(language_str("ctext")); + selectObject(select_obj, i); + selectCircleText(select_obj, i); + break; + } + selectObj(i, true) + } else { + //背景,收起对象属性 + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#counter_control').hide() + selectObj(-1) + $('#component_type').text(language_str('bg')) + } + }) + canvas1.on('text:editing:entered', function () { + _textEdit = true + }) + canvas1.on('text:editing:exited', function () { + _textEdit = false + }) + canvas1.on('object:modified', function (event) { + if (canvas1.getActiveObjects().length > 1) { + return + } + + // 跳过辅助线 + if (event.target.isGuideLine) { + return + } + + let idx = getIndex(event.target, canvas1); + if (idx <= 0) return; + + // 安全检查:确保 objs[idx - 1] 存在且有 type 属性 + if (!objs[idx - 1] || typeof objs[idx - 1].type === 'undefined') { + return + } + + if (objs[idx - 1].type == 3) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas1.renderAll() + updateControls() + } else if (objs[idx - 1].type == 4) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas1.renderAll() + } else if (objs[idx - 1].type == 10) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas1.renderAll() + } else if (objs[idx - 1].type == 5) { + canvas1.getActiveObject().set('width', canvas1.getActiveObject().get('width') * canvas1.getActiveObject().get('scaleX')) + canvas1.getActiveObject().set('height', canvas1.getActiveObject().get('height') * canvas1.getActiveObject().get('scaleY')) + canvas1.getActiveObject().set('scaleX', 1) + canvas1.getActiveObject().set('scaleY', 1) + updateControls() + } + recordState() + }) + canvas1.on('mouse:up', (e) => { + canvas = canvas1; + objs = objs1; + switch (addState) { + case 1: + addPic(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addPic').css('background-color', '') + break + case 2: + addOutPic(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addOutPic').css('background-color', '') + break + case 3: + addText(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addText').css('background-color', '') + break + case 4: + addOutText(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addOutText').css('background-color', '') + break + case 5: + addRect(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addRect').css('background-color', '') + break + case 6: + addCircle(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addCircle').css('background-color', '') + break + case 7: + addLine(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addLine').css('background-color', '') + break + case 8: + addQrCode(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addQrCode').css('background-color', '') + break + case 9: + addBarCode(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas1.renderAll() + $('#addBarCode').css('background-color', '') + break + case 10: + addCounter(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + $('#addCounter').css('background-color', '') + break + case 11: + addCircleText(e.pointer); + addState = 0; + background_image.hoverCursor = "default"; + canvas1.renderAll(); + $("#addCircleText").css("background-color", ""); + break; + } + }) + canvas1.on('text:changed', (e) => { + $('#text_text').val(e.target.get('text')) + }) + canvas1.on('after:render', function () { + if (is_bgi_add) { + var image = document.getElementById('source_front') + ctx1.drawImage(image, (canvas.width - $('#source_front').width()) / 2, (canvas.height - $('#source_front').height()) / 2, $('#source_front').width(), $('#source_front').height()) + } + }) + canvas2.on('text:editing:entered', function () { + _textEdit = true + }) + canvas2.on('text:editing:exited', function () { + _textEdit = false + }) + canvas2.on('after:render', function () { + if (is_bgi_add) { + var image = document.getElementById('source_back') + ctx2.drawImage(image, (canvas.width - $('#source_back').width()) / 2, (canvas1.height - $('#source_back').height()) / 2, $('#source_back').width(), $('#source_back').height()) + } + }) + canvas2.on('mouse:move', (e) => { + if (!e.pointer || typeof background_image === 'undefined' || !background_image) return; + canvas = canvas2; + objs = objs2; + $('#posText').text('X: ' + (e.pointer.x - background_image.left).toFixed(0) + ' Y: ' + (e.pointer.y - background_image.top).toFixed(0)) + }) + canvas2.on("object:moving", function (e) { + canvas = canvas2; + objs = objs2; + let obj = canvas2.getActiveObject() + let idx = getIndex(e.target, canvas2); + // 添加边界检查,避免访问 undefined + if (idx > 0 && idx <= objs2.length && objs2[idx - 1] && objs2[idx - 1].type && objs2[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) { + let pointer = { + x: obj.left, + y: obj.top + } + let distance = getDisdance(pointer.x, pointer.y, canvas2.width / 2, canvas2.height / 2) + // 计算角度时需要使用 canvas2 + let centerX = canvas2.width / 2; + let centerY = canvas2.height / 2; + let mouseX = pointer.x; + let mouseY = pointer.y; + let dx = mouseX - centerX; + let dy = mouseY - centerY; + let angleRad = Math.atan2(dy, dx); + let angleDeg = angleRad * (180 / Math.PI); + if (angleDeg < 0) { + angleDeg += 360; + } + angleDeg += 90; + let flipped = pointer.y > canvas2.height / 2 ? true : false + if (typeof circle_text_diameter !== 'undefined' && circle_text_diameter.setValue) { + circle_text_diameter.setValue(distance * 2 - 50); + } + obj.set("diameter", distance * 2); + obj.set("angle", angleDeg); + obj.set("flipped", flipped); + } + updateControls(); + }); + canvas2.on('object:scaling', function (e) { + canvas = canvas2; + objs = objs2; + updateControls() + }) + canvas2.on('object:rotating', function (e) { + canvas = canvas2; + objs = objs2; + updateControls() + }) + canvas2.on('object:rotated', function (e) { + canvas = canvas2; + objs = objs2; + recordState() + }) + canvas2.on('object:added', function (e) { + //recordState(); + }) + canvas2.on('mouse:down', (e) => { + //单选 + canvas = canvas2; + objs = objs2; + let select_obj = canvas.getActiveObject() + + // 如果是辅助线,直接返回,不处理 + if (select_obj && select_obj.isGuideLine) { + return + } + + let i = getIndex(select_obj, canvas) + if (i != 0) { + //不是背景 + --i + + // 安全检查:确保 objs[i] 存在且有 type 属性 + if (!objs[i] || typeof objs[i].type === 'undefined') { + return + } + + switch (objs[i].type) { + case 1: + $('#component_type').text(language_str('img')) + selectObject(select_obj, i) + selectPic(select_obj, i) + break + case 2: + $('#component_type').text(language_str('simg')) + selectObject(select_obj, i) + selectOutPic(select_obj, i) + break + case 3: + $('#component_type').text(language_str('text')) + selectObject(select_obj, i) + selectText(select_obj, i) + break + case 4: + $('#component_type').text(language_str('stext')) + selectObject(select_obj, i) + selectOutText(select_obj, i) + break + case 5: + $('#component_type').text(language_str('rect')) + selectObject(select_obj, i) + selectRect(select_obj, i) + break + case 6: + $('#component_type').text(language_str('circ')) + selectObject(select_obj, i) + selectCircle(select_obj, i) + break + case 7: + $('#component_type').text(language_str('line')) + selectObject(select_obj, i) + selectLine(select_obj, i) + break + case 8: + $('#component_type').text(language_str('qrc')) + selectObject(select_obj, i) + selectQrCode(select_obj, i) + break + case 9: + $('#component_type').text(language_str('barc')) + selectObject(select_obj, i) + selectBarCode(select_obj, i) + break + case 10: + $('#component_type').text(language_str('counter')) + selectObject(select_obj, i) + selectCounter(select_obj, i) + break + case 11: + $("#component_type").text(language_str("ctext")); + selectObject(select_obj, i); + selectCircleText(select_obj, i); + break; + } + selectObj(i, true) + } else { + //背景,收起对象属性 + $('#base_control').hide() + $('#line_control').hide() + $('#pic_control').hide() + $('#out_pic_control').hide() + $('#text_control').hide() + $("#circle_text_control").hide(); + $('#out_text_control').hide() + $('#rect_control').hide() + $('#circle_control').hide() + $('#qrcode_Controll').hide() + $('#barcode_controll').hide() + $('#counter_control').hide() + selectObj(-1) + $('#component_type').text(language_str('bg')) + } + }) + canvas2.on('object:modified', function (event) { + canvas = canvas2; + objs = objs2; + if (canvas.getActiveObjects().length > 1) { + return + } + + // 跳过辅助线 + if (event.target.isGuideLine) { + return + } + + let idx = getIndex(event.target, canvas2); + if (idx <= 0) return; + + // 安全检查:确保 objs[idx - 1] 存在且有 type 属性 + if (!objs[idx - 1] || typeof objs[idx - 1].type === 'undefined') { + return + } + + if (objs[idx - 1].type == 3) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas2.renderAll() + } else if (objs[idx - 1].type == 4) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas2.renderAll() + } else if (objs[idx - 1].type == 10) { + event.target.fontSize *= event.target.scaleX + event.target.fontSize = event.target.fontSize.toFixed(0) + event.target.scaleX = 1 + event.target.scaleY = 1 + event.target._clearCache() + canvas2.renderAll() + } else if (objs[idx - 1].type == 5) { + canvas2.getActiveObject().set('width', canvas2.getActiveObject().get('width') * canvas2.getActiveObject().get('scaleX')) + canvas2.getActiveObject().set('height', canvas2.getActiveObject().get('height') * canvas2.getActiveObject().get('scaleY')) + canvas2.getActiveObject().set('scaleX', 1) + canvas2.getActiveObject().set('scaleY', 1) + updateControls() + } + recordState() + }) + canvas2.on('mouse:up', (e) => { + canvas = canvas2; + objs = objs2; + switch (addState) { + case 1: + addPic(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addPic').css('background-color', '') + break + case 2: + addOutPic(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addOutPic').css('background-color', '') + break + case 3: + addText(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addText').css('background-color', '') + break + case 4: + addOutText(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addOutText').css('background-color', '') + break + case 5: + addRect(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addRect').css('background-color', '') + break + case 6: + addCircle(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addCircle').css('background-color', '') + break + case 7: + addLine(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addLine').css('background-color', '') + break + case 8: + addQrCode(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addQrCode').css('background-color', '') + break + case 9: + addBarCode(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + canvas2.renderAll() + $('#addBarCode').css('background-color', '') + break + case 10: + addCounter(e.pointer) + addState = 0 + background_image.hoverCursor = 'default' + $('#addCounter').css('background-color', '') + break + case 11: + addCircleText(e.pointer); + addState = 0; + background_image.hoverCursor = "default"; + canvas2.renderAll(); + $("#addCircleText").css("background-color", ""); + break; + } + }) +} diff --git a/lib/difxapi.dl b/lib/difxapi.dl deleted file mode 100644 index 6f1b042..0000000 --- a/lib/difxapi.dl +++ /dev/null @@ -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) diff --git a/lib/difxapi.jsc b/lib/difxapi.jsc deleted file mode 100644 index 6f1b042..0000000 --- a/lib/difxapi.jsc +++ /dev/null @@ -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) diff --git a/lib/directx9.dl b/lib/directx9.dl deleted file mode 100644 index 46e41ff..0000000 Binary files a/lib/directx9.dl and /dev/null differ diff --git a/lib/directx9.jsc b/lib/directx9.jsc deleted file mode 100644 index 2dd7145..0000000 Binary files a/lib/directx9.jsc and /dev/null differ diff --git a/lib/drfwsfg.jsc b/lib/drfwsfg.jsc deleted file mode 100644 index 434938e..0000000 Binary files a/lib/drfwsfg.jsc and /dev/null differ diff --git a/lib/drwsfg.dl b/lib/drwsfg.dl deleted file mode 100644 index 1e3d37b..0000000 Binary files a/lib/drwsfg.dl and /dev/null differ diff --git a/lib/drwssd.dl b/lib/drwssd.dl deleted file mode 100644 index 4435fd3..0000000 Binary files a/lib/drwssd.dl and /dev/null differ diff --git a/lib/drwssd.jsc b/lib/drwssd.jsc deleted file mode 100644 index 760160c..0000000 Binary files a/lib/drwssd.jsc and /dev/null differ diff --git a/lib/module-map.json b/lib/module-map.json new file mode 100644 index 0000000..c81bc05 --- /dev/null +++ b/lib/module-map.json @@ -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", + "修改后需要重新运行加密脚本", + "确保映射值唯一,避免冲突" + ] +} + diff --git a/main.js b/main.js index 88778ce..3f0b688 100644 --- a/main.js +++ b/main.js @@ -152,26 +152,78 @@ function createWindow() { const fileName = 'User Manual.pdf'; 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 { helpPath = path.join(process.cwd(), 'help', fileName); } console.log("Help file path: ", helpPath); - if (fs.existsSync(helpPath)) { + if (helpPath && fs.existsSync(helpPath)) { try { - const errorMessage = await shell.openPath(helpPath); - if (errorMessage) { - console.error('Error opening help file:', errorMessage); + // Linux上使用shell.openExternal更可靠 + if (process.platform === 'linux') { + await shell.openExternal(`file://${helpPath}`); } 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) { 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 { 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); + } + } + } } }); diff --git a/package.json b/package.json index 4687750..78c8a19 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,20 @@ "main": "main.js", "scripts": { "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:mac": "electron-builder --mac --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": { "productName": "SoonDesign", @@ -21,6 +30,23 @@ "extraFiles": [ "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": { "oneClick": false, "allowElevation": true, @@ -65,8 +91,8 @@ }, "linux": { "target": [ - { "target": "AppImage", "arch": ["x64"] }, - { "target": "deb", "arch": ["x64"] } + { "target": "AppImage", "arch": ["x64", "arm64"] }, + { "target": "deb", "arch": ["x64", "arm64"] } ], "category": "Utility", "icon": "public/images/IconA256.png", diff --git a/public/js/guideLines1.js b/public/js/guideLines1.js index 91080b2..eaf3694 100644 --- a/public/js/guideLines1.js +++ b/public/js/guideLines1.js @@ -62,7 +62,7 @@ function initAligningGuidelines(canvas) { }); canvas.on('object:moving', function(e) { - + var activeObject = e.target, canvasObjects = canvas.getObjects(), activeObjectCenter = activeObject.getCenterPoint(), @@ -74,15 +74,22 @@ function initAligningGuidelines(canvas) { horizontalInTheRange = false, verticalInTheRange = false, transform = canvas._currentTransform; - + 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, // but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move - + for (var i = canvasObjects.length; i--; ) { - + if (canvasObjects[i] === activeObject) continue; + + // 跳过辅助线对象,避免辅助线之间相互对齐产生重影 + if (canvasObjects[i].isGuideLine) continue; var objectCenter = canvasObjects[i].getCenterPoint(), objectLeft = objectCenter.x, @@ -202,11 +209,40 @@ function initAligningGuidelines(canvas) { }); canvas.on('after:render', function() { + // 合并相同 x 坐标的竖向辅助线(使用四舍五入处理浮点数精度问题) + var mergedVerticalLines = {}; 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--; ) { - 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; }); diff --git a/public/js/guideLines2.js b/public/js/guideLines2.js index 0a01726..86498f5 100644 --- a/public/js/guideLines2.js +++ b/public/js/guideLines2.js @@ -62,7 +62,7 @@ function initAligningGuidelines(canvas) { }); canvas.on('object:moving', function(e) { - + var activeObject = e.target, canvasObjects = canvas.getObjects(), activeObjectCenter = activeObject.getCenterPoint(), @@ -74,15 +74,22 @@ function initAligningGuidelines(canvas) { horizontalInTheRange = false, verticalInTheRange = false, transform = canvas._currentTransform; - + 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, // but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move - + for (var i = canvasObjects.length; i--; ) { - + if (canvasObjects[i] === activeObject) continue; + + // 跳过辅助线对象,避免辅助线之间相互对齐产生重影 + if (canvasObjects[i].isGuideLine) continue; var objectCenter = canvasObjects[i].getCenterPoint(), objectLeft = objectCenter.x, @@ -202,11 +209,40 @@ function initAligningGuidelines(canvas) { }); canvas.on('after:render', function() { + // 合并相同 x 坐标的竖向辅助线(使用四舍五入处理浮点数精度问题) + var mergedVerticalLines = {}; 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--; ) { - 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; }); diff --git a/scripts/encrypt/README.md b/scripts/encrypt/README.md new file mode 100644 index 0000000..7e44116 --- /dev/null +++ b/scripts/encrypt/README.md @@ -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" + } + } +} +``` + diff --git a/scripts/encrypt/cleanup-jsc.js b/scripts/encrypt/cleanup-jsc.js new file mode 100644 index 0000000..c3a43fb --- /dev/null +++ b/scripts/encrypt/cleanup-jsc.js @@ -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} 个文件不存在`); + diff --git a/scripts/encrypt/cleanup.js b/scripts/encrypt/cleanup.js new file mode 100644 index 0000000..dc71d60 --- /dev/null +++ b/scripts/encrypt/cleanup.js @@ -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 目录复制文件回原位置'); +} diff --git a/scripts/encrypt/encrypt-electron-win.bat b/scripts/encrypt/encrypt-electron-win.bat new file mode 100644 index 0000000..f3b8aea --- /dev/null +++ b/scripts/encrypt/encrypt-electron-win.bat @@ -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 + diff --git a/scripts/encrypt/encrypt-electron.js b/scripts/encrypt/encrypt-electron.js new file mode 100644 index 0000000..8076e67 --- /dev/null +++ b/scripts/encrypt/encrypt-electron.js @@ -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); + diff --git a/scripts/encrypt/encrypt-electron.sh b/scripts/encrypt/encrypt-electron.sh new file mode 100644 index 0000000..d79b377 --- /dev/null +++ b/scripts/encrypt/encrypt-electron.sh @@ -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 + diff --git a/scripts/encrypt/restore.js b/scripts/encrypt/restore.js new file mode 100644 index 0000000..497bf4e --- /dev/null +++ b/scripts/encrypt/restore.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 目录'); +} +