From cf7d065379ee2d8098c8daa8dfa0e3f4c666e271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 11 Aug 2026 18:52:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(shop):=20=E5=95=86=E5=93=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=BC=96=E8=BE=91=E5=BC=B9=E7=AA=97=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E4=B8=BAWangEditor=E5=AF=8C=E6=96=87=E6=9C=AC=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 用户反馈编辑弹窗的Markdown编辑器体验差,采用website-admin的富文本编辑器替代 - 新增依赖@wangeditor/editor、@wangeditor/editor-for-vue、markdown-it及类型声明 - 新建RichTextEditor组件,去除Nuxt专用包装,适配现有文件上传接口 - shopGoodsEdit.vue移除MdEditor及相关冗余代码,改用RichTextEditor显示内容 - 实现编辑时Markdown内容转换为HTML,保持数据库存储格式新旧兼容 - 保存逻辑保持不变,提交内容为HTML格式 - 确认小程序端可兼容新旧内容格式,潜在HTML图片链接误解析风险 - build验证通过,文件产出正常,图片上传小程序域名白名单需上线后确认 --- .workbuddy/memory/2026-08-11.md | 28 ++ package.json | 4 + pnpm-lock.yaml | 395 ++++++++++++++++++ src/components/RichTextEditor.vue | 205 +++++++++ .../shopGoods/components/shopGoodsEdit.vue | 186 ++------- 5 files changed, 658 insertions(+), 160 deletions(-) create mode 100644 src/components/RichTextEditor.vue diff --git a/.workbuddy/memory/2026-08-11.md b/.workbuddy/memory/2026-08-11.md index 7d2df7f..742a0d0 100644 --- a/.workbuddy/memory/2026-08-11.md +++ b/.workbuddy/memory/2026-08-11.md @@ -85,3 +85,31 @@ - **⚠️ 上线前置动作(否则不生效)**:必须在 db_guilixu 执行该 SQL 加列,且 guilixu-java 需重新编译部署(实体加了字段)。 - 此修复同时解决"运费模板"也存不进库的问题(同一根因,用户只报了 canExpress)。 - 前端 运费模板 必填校验(save 内 `canExpress===1 && !expressTemplateId`)与动态 label 已早先存在,逻辑无需改。 + +## 商品管理编辑弹窗:Markdown 编辑器换成 WangEditor 富文本 + +### 需求 +用户反馈商品「编辑弹窗」的 Markdown 编辑器不好用,要求换成 website-admin 的 `app/pages/articles.vue` 那套编辑器。 + +### 方案(经评估后采用) +- articles.vue 用的是 `app/components/RichTextEditor.vue`(WangEditor `@wangeditor/editor-for-vue`,输出 HTML),并非 Markdown。 +- 采用「编辑时按需转换」策略:**老商品 content 是 Markdown,编辑回显时用 markdown-it 转成 HTML 再进富文本编辑器;已是 HTML 则原样返回**。零 DB 风险,存储格式新旧混存。 + +### 改动清单 +1. **新增依赖**(guilixu-admin,pnpm):`@wangeditor/editor@^5`、`@wangeditor/editor-for-vue@^5`、`markdown-it@^14`、`@types/markdown-it@^14`(已写 package.json + node_modules)。 +2. **新建组件** `src/components/RichTextEditor.vue`:从 website-admin 的同名组件复制,**删除 Nuxt 专属 `` 包装**(guilixu-admin 是 Vite SPA 无此组件);图片上传用 `@/api/system/file` 的 `uploadFile`(返回 `res.url || res.path`,admin 已有)。 +3. **改造** `src/views/shop/shopGoods/components/shopGoodsEdit.vue`: + - 移除 `MdEditor`(`md-editor-v3`)+ 相关 import / `markdownToolbars` / `onMarkdownUploadImg` / `editorVisible` watch / `disabled` ref / `editorRef` / 文件库 `SelectData` 弹窗(无打开入口,死代码)/ `:deep(.md-editor-*)` 样式。 + - 商品详情 tab 内改用 ``(仅在 tab 激活时挂载,规避隐藏容器初始化宽度 0 问题)。 + - 新增 `md = markdownit()` 与 `toEditorContent(raw)`,编辑回显 `content.value = toEditorContent(props.data.content)`。 + - 补回被误删的 `FileRecord` import(chooseImage 等函数仍用)。 +4. **保存逻辑不变**:`save()` 已读 `content.value`,直接提交 HTML。 + +### 验证 +- `pnpm build`(vite build)通过,exit 0,dist 正常产出。 + +### 风险 / 待确认 +- **消费端(小程序 `guilixu-taro/src/pages/shop/product-detail.tsx`)已兼容两种格式**:`parseContent` 把 `![alt](url)` 转 ``,其余 HTML 直接 `RichText nodes` 渲染 → 新旧 content 都能展示,不崩。 +- **潜在坑**:若 HTML content 里含裸 `.jpg` 链接(非 `` 包裹,如 ``),`parseContent` 的兜底会把该 URL 误转成 `` 破坏链接。WangEditor 产出的图片都是 ``,正常商品详情极少触发,低概率。 +- `uploadFile` 返回的 `url` 是否为小程序域名白名单内完整 URL 需上线后在真机确认(影响商品详情页图片显示)。 +- 老商品仅在「重新编辑」时转 HTML;从未编辑过的老 Markdown 商品保持 Markdown,仍由小程序正确渲染。 diff --git a/package.json b/package.json index ef3c058..61bf10d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "@bytemd/plugin-gfm": "^1.17.2", "@bytemd/plugin-highlight": "^1.17.4", "@bytemd/plugin-highlight-ssr": "^1.20.2", + "@wangeditor/editor": "^5", + "@wangeditor/editor-for-vue": "^5", "@wecom/jssdk": "^1.3.1", "ali-oss": "^6.18.0", "ant-design-vue": "^4.2.6", @@ -53,6 +55,7 @@ "js-md5": "^0.7.3", "jsbarcode": "^3.11.5", "lodash-es": "^4.17.21", + "markdown-it": "^14", "md-editor-v3": "^5.2.3", "mitt": "^3.0.1", "nprogress": "^0.2.0", @@ -73,6 +76,7 @@ "@types/dompurify": "^3.2.0", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.6", + "@types/markdown-it": "^14.1.2", "@types/node": "^22.15.0", "@types/nprogress": "^0.2.0", "@types/qrcode": "^1.5.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74a05ca..6ab2276 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,12 @@ importers: '@bytemd/plugin-highlight-ssr': specifier: ^1.20.2 version: 1.22.0(bytemd@1.22.0) + '@wangeditor/editor': + specifier: ^5 + version: 5.1.23 + '@wangeditor/editor-for-vue': + specifier: ^5 + version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.3(typescript@5.9.3)) '@wecom/jssdk': specifier: ^1.3.1 version: 1.4.5 @@ -97,6 +103,9 @@ importers: lodash-es: specifier: ^4.17.21 version: 4.17.21 + markdown-it: + specifier: ^14 + version: 14.1.0 md-editor-v3: specifier: ^5.2.3 version: 5.8.5(vue@3.5.3(typescript@5.9.3)) @@ -152,6 +161,9 @@ importers: '@types/lodash-es': specifier: ^4.17.6 version: 4.17.12 + '@types/markdown-it': + specifier: ^14.1.2 + version: 14.1.2 '@types/node': specifier: ^22.15.0 version: 22.19.18 @@ -1371,6 +1383,9 @@ packages: '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@transloadit/prettier-bytes@0.0.7': + resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==} + '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -1444,6 +1459,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/event-emitter@0.3.5': + resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==} + '@types/file-saver@2.0.7': resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} @@ -1566,6 +1584,23 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@uppy/companion-client@2.2.2': + resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==} + + '@uppy/core@2.3.4': + resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==} + + '@uppy/store-default@2.1.1': + resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==} + + '@uppy/utils@4.1.3': + resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==} + + '@uppy/xhr-upload@2.1.3': + resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==} + peerDependencies: + '@uppy/core': ^2.3.3 + '@vavt/copy2clipboard@1.0.3': resolution: {integrity: sha512-HtG48r2FBYp9eRvGB3QGmtRBH1zzRRAVvFbGgFstOwz4/DDaNiX0uZc3YVKPydqgOav26pibr9MtoCaWxn7aeA==} @@ -1654,6 +1689,93 @@ packages: '@vue/shared@3.5.34': resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==} + '@wangeditor/basic-modules@1.1.7': + resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/code-highlight@1.0.3': + resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/core@1.1.19': + resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==} + peerDependencies: + '@uppy/core': ^2.1.1 + '@uppy/xhr-upload': ^2.0.3 + dom7: ^3.0.0 + is-hotkey: ^0.2.0 + lodash.camelcase: ^4.3.0 + lodash.clonedeep: ^4.5.0 + lodash.debounce: ^4.0.8 + lodash.foreach: ^4.5.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + lodash.toarray: ^4.4.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/editor-for-vue@5.1.12': + resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==} + peerDependencies: + '@wangeditor/editor': '>=5.1.0' + vue: ^3.0.5 + + '@wangeditor/editor@5.1.23': + resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==} + + '@wangeditor/list-module@1.0.5': + resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/table-module@1.1.4': + resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/upload-image-module@1.0.2': + resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==} + peerDependencies: + '@uppy/core': ^2.0.3 + '@uppy/xhr-upload': ^2.0.3 + '@wangeditor/basic-modules': 1.x + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.foreach: ^4.5.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/video-module@1.1.4': + resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==} + peerDependencies: + '@uppy/core': ^2.1.4 + '@uppy/xhr-upload': ^2.0.7 + '@wangeditor/core': 1.x + dom7: ^3.0.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + '@wecom/jssdk@1.4.5': resolution: {integrity: sha512-1SSmcDUid7QOQNNFaM4d884NXJQYuoO+oLZtM9TRO5uMXYj2s69hmuAoPUr3D3br6VDgv4H+tbIG5A5A+uB9lA==} @@ -2256,6 +2378,9 @@ packages: dom-scroll-into-view@2.0.1: resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} + dom7@3.0.0: + resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==} + dompurify@3.4.5: resolution: {integrity: sha512-OrwIBKsdNSVEeubdJ1HBv/wNENRM9ytAVCv7YXt//A3vPdVMNuACRqK9mXCGCBW2ln7BT/A4X0jXHo2Gu89miA==} @@ -2728,6 +2853,9 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + i18next@20.6.1: + resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2751,6 +2879,9 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -2809,6 +2940,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hotkey@0.2.0: + resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2825,9 +2959,16 @@ packages: resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} engines: {node: '>=0.10.0'} + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + is-type-of@1.4.0: resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + is-what@3.14.1: resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} @@ -3024,6 +3165,12 @@ packages: lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -3039,6 +3186,9 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + lodash.foreach@4.5.0: + resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} + lodash.groupby@4.6.0: resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} @@ -3064,6 +3214,12 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + lodash.toarray@4.4.0: + resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==} + lodash.union@4.6.0: resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} @@ -3278,6 +3434,9 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-match@1.0.2: + resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} @@ -3332,6 +3491,9 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + namespace-emitter@2.0.1: + resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3584,6 +3746,14 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + preact@10.29.8: + resolution: {integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==} + peerDependencies: + preact-render-to-string: '>=5' + peerDependenciesMeta: + preact-render-to-string: + optional: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3597,6 +3767,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -3841,6 +4015,18 @@ packages: simple-swizzle@0.2.4: resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + slate-history@0.66.0: + resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==} + peerDependencies: + slate: '>=0.65.3' + + slate@0.72.8: + resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==} + + snabbdom@3.6.4: + resolution: {integrity: sha512-VmxEfuw1/Y/eFj5VtMhYnukExpYiPkNzoo3+N3qwAOUDMl8wXgbli5ebR+j0knE3lZ/0eYskLxNcX64uy10N9w==} + engines: {node: '>=12.17.0'} + socket.io-client@4.8.1: resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} engines: {node: '>=10.0.0'} @@ -3881,6 +4067,9 @@ packages: resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} engines: {node: '>=0.8'} + ssr-window@3.0.0: + resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==} + statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -3973,6 +4162,9 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -4311,6 +4503,9 @@ packages: engines: {node: '>= 8'} hasBin: true + wildcard@1.1.2: + resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==} + win-release@1.1.1: resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==} engines: {node: '>=0.10.0'} @@ -5993,6 +6188,8 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} + '@transloadit/prettier-bytes@0.0.7': {} + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -6060,6 +6257,8 @@ snapshots: '@types/estree@1.0.8': {} + '@types/event-emitter@0.3.5': {} + '@types/file-saver@2.0.7': {} '@types/geojson@7946.0.16': {} @@ -6211,6 +6410,37 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@uppy/companion-client@2.2.2': + dependencies: + '@uppy/utils': 4.1.3 + namespace-emitter: 2.0.1 + + '@uppy/core@2.3.4': + dependencies: + '@transloadit/prettier-bytes': 0.0.7 + '@uppy/store-default': 2.1.1 + '@uppy/utils': 4.1.3 + lodash.throttle: 4.1.1 + mime-match: 1.0.2 + namespace-emitter: 2.0.1 + nanoid: 3.3.11 + preact: 10.29.8 + transitivePeerDependencies: + - preact-render-to-string + + '@uppy/store-default@2.1.1': {} + + '@uppy/utils@4.1.3': + dependencies: + lodash.throttle: 4.1.1 + + '@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4)': + dependencies: + '@uppy/companion-client': 2.2.2 + '@uppy/core': 2.3.4 + '@uppy/utils': 4.1.3 + nanoid: 3.3.11 + '@vavt/copy2clipboard@1.0.3': {} '@vavt/util@2.1.1': {} @@ -6365,6 +6595,116 @@ snapshots: '@vue/shared@3.5.34': {} + '@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + is-url: 1.2.4 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.4 + + '@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + prismjs: 1.30.0 + slate: 0.72.8 + snabbdom: 3.6.4 + + '@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@types/event-emitter': 0.3.5 + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + dom7: 3.0.0 + event-emitter: 0.3.5 + html-void-elements: 2.0.1 + i18next: 20.6.1 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + scroll-into-view-if-needed: 2.2.31 + slate: 0.72.8 + slate-history: 0.66.0(slate@0.72.8) + snabbdom: 3.6.4 + + '@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.3(typescript@5.9.3))': + dependencies: + '@wangeditor/editor': 5.1.23 + vue: 3.5.3(typescript@5.9.3) + + '@wangeditor/editor@5.1.23': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.4 + transitivePeerDependencies: + - preact-render-to-string + + '@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + slate: 0.72.8 + snabbdom: 3.6.4 + + '@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.4 + + '@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + lodash.foreach: 4.5.0 + slate: 0.72.8 + snabbdom: 3.6.4 + + '@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.4) + dom7: 3.0.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.4 + '@wecom/jssdk@1.4.5': {} acorn-jsx@5.3.2(acorn@8.15.0): @@ -7006,6 +7346,10 @@ snapshots: dom-scroll-into-view@2.0.1: {} + dom7@3.0.0: + dependencies: + ssr-window: 3.0.0 + dompurify@3.4.5: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -7556,6 +7900,10 @@ snapshots: dependencies: ms: 2.1.3 + i18next@20.6.1: + dependencies: + '@babel/runtime': 7.28.4 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -7571,6 +7919,8 @@ snapshots: immediate@3.0.6: {} + immer@9.0.21: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -7613,6 +7963,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hotkey@0.2.0: {} + is-number@7.0.0: {} is-path-inside@3.0.3: {} @@ -7621,12 +7973,16 @@ snapshots: is-plain-object@3.0.1: {} + is-plain-object@5.0.0: {} + is-type-of@1.4.0: dependencies: core-util-is: 1.0.3 is-class-hotfix: 0.0.6 isstream: 0.1.2 + is-url@1.2.4: {} + is-what@3.14.1: {} is-wsl@2.2.0: @@ -7792,6 +8148,10 @@ snapshots: lodash-es@4.17.21: {} + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + lodash.debounce@4.0.8: {} lodash.defaults@4.2.0: {} @@ -7802,6 +8162,8 @@ snapshots: lodash.flatten@4.4.0: {} + lodash.foreach@4.5.0: {} + lodash.groupby@4.6.0: {} lodash.isboolean@3.0.3: {} @@ -7818,6 +8180,10 @@ snapshots: lodash.merge@4.6.2: {} + lodash.throttle@4.1.1: {} + + lodash.toarray@4.4.0: {} + lodash.union@4.6.0: {} lodash.uniq@4.5.0: {} @@ -8215,6 +8581,10 @@ snapshots: mime-db@1.52.0: {} + mime-match@1.0.2: + dependencies: + wildcard: 1.1.2 + mime-types@2.1.35: dependencies: mime-db: 1.52.0 @@ -8265,6 +8635,8 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + namespace-emitter@2.0.1: {} + nanoid@3.3.11: {} nanoid@5.1.6: {} @@ -8469,6 +8841,8 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + preact@10.29.8: {} + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -8477,6 +8851,8 @@ snapshots: prettier@2.8.8: {} + prismjs@1.30.0: {} + process-nextick-args@2.0.1: {} property-information@6.5.0: {} @@ -8784,6 +9160,19 @@ snapshots: dependencies: is-arrayish: 0.3.4 + slate-history@0.66.0(slate@0.72.8): + dependencies: + is-plain-object: 5.0.0 + slate: 0.72.8 + + slate@0.72.8: + dependencies: + immer: 9.0.21 + is-plain-object: 5.0.0 + tiny-warning: 1.0.3 + + snabbdom@3.6.4: {} + socket.io-client@4.8.1: dependencies: '@socket.io/component-emitter': 3.1.2 @@ -8827,6 +9216,8 @@ snapshots: dependencies: frac: 1.1.2 + ssr-window@3.0.0: {} + statuses@1.5.0: {} stream-http@2.8.2: @@ -8949,6 +9340,8 @@ snapshots: through@2.3.8: {} + tiny-warning@1.0.3: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -9284,6 +9677,8 @@ snapshots: dependencies: isexe: 2.0.0 + wildcard@1.1.2: {} + win-release@1.1.1: dependencies: semver: 5.7.2 diff --git a/src/components/RichTextEditor.vue b/src/components/RichTextEditor.vue new file mode 100644 index 0000000..802e07a --- /dev/null +++ b/src/components/RichTextEditor.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/src/views/shop/shopGoods/components/shopGoodsEdit.vue b/src/views/shop/shopGoods/components/shopGoodsEdit.vue index e46087d..7da6f25 100644 --- a/src/views/shop/shopGoods/components/shopGoodsEdit.vue +++ b/src/views/shop/shopGoods/components/shopGoodsEdit.vue @@ -106,11 +106,11 @@ v-model:value="form.buyingPrice" /> - + - - -
- 💡 提示:支持 Markdown 语法,可直接拖拽上传图片,也可以使用工具栏按钮从文件库选择图片 -
@@ -674,23 +668,6 @@ - - - - - @@ -703,7 +680,7 @@ import { SettingOutlined, UploadOutlined } from '@ant-design/icons-vue'; -import {ref, reactive, watch, nextTick} from 'vue'; +import {ref, reactive, watch} from 'vue'; import {useRouter} from 'vue-router'; import {Form, message} from 'ant-design-vue'; import {assignObject, messageLoading, uuid} from 'ele-admin-pro'; @@ -713,12 +690,11 @@ import {useThemeStore} from '@/store/modules/theme'; import {storeToRefs} from 'pinia'; import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types'; import {FormInstance, RuleObject} from 'ant-design-vue/es/form'; -import {FileRecord} from '@/api/system/file/model'; import {ShopMerchant} from '@/api/shop/shopMerchant/model'; import {uploadFile, uploadOss} from '@/api/system/file'; -import { MdEditor } from 'md-editor-v3'; -import 'md-editor-v3/lib/style.css'; -import 'md-editor-v3/lib/preview.css'; +import {FileRecord} from '@/api/system/file/model'; +import RichTextEditor from '@/components/RichTextEditor.vue'; +import markdownit from 'markdown-it'; import {ShopSpec} from '@/api/shop/shopSpec/model'; import {ShopGoodsSku} from '@/api/shop/shopGoodsSku/model'; import {ShopGoodsSpec} from '@/api/shop/shopGoodsSpec/model'; @@ -731,7 +707,6 @@ import {ShopExpressTemplate} from '@/api/shop/shopExpressTemplate/model'; import {listShopExpressTemplate} from '@/api/shop/shopExpressTemplate'; import {listShopCommissionRole} from '@/api/shop/shopCommissionRole'; import {listShopGoodsRoleCommission} from '@/api/shop/shopGoodsRoleCommission'; -import SelectData from "@/components/SelectFile/components/select-data.vue"; // 是否是修改 const isUpdate = ref(false); @@ -762,7 +737,21 @@ const maxable = ref(true); const formRef = ref(null); const images = ref([]); const content = ref(''); -const disabled = ref(false); + +// Markdown -> HTML 转换(编辑回显旧数据时,把 Markdown 内容转成富文本可识别的 HTML) +const md = markdownit(); +/** + * 把后端 content 转为富文本编辑器可用的 HTML: + * - 已是 HTML(含标签)则原样返回,避免二次转义; + * - 否则按 Markdown 渲染为 HTML。 + */ +const toEditorContent = (raw?: string): string => { + if (!raw) return ''; + const s = raw.trim(); + if (/<[a-z][\s\S]*>/i.test(s)) return raw; + return md.render(s); +}; + // 当前选项卡 const active = ref('base'); @@ -969,34 +958,6 @@ const onDeleteEnsureTag = (tag: string) => { ensureTag.value.splice(index, 1); }; -// 从文件库选择图片的回调 -const onFileSelected = (data: FileRecord) => { - if (fileSelectCallback.value) { - // 使用文件的完整URL,确保有值 - const imageUrl = data.url || data.path || ''; - if (imageUrl) { - fileSelectCallback.value(imageUrl); - message.success('图片插入成功'); - } - fileSelectCallback.value = null; - } - showFileSelector.value = false; -}; - -// 从视频库选择视频的回调 -const onVideoSelected = (data: FileRecord) => { - if (videoSelectCallback.value) { - // 使用文件的完整URL,确保有值 - const videoUrl = data.path || data.downloadUrl || ''; - if (videoUrl) { - videoSelectCallback.value(videoUrl); - message.success('视频插入成功'); - } - videoSelectCallback.value = null; - } - showVideoSelector.value = false; -}; - // 🎨 智能一键排版 - 人性化设计 const handleAutoFormat = (editor: any) => { try { @@ -1740,88 +1701,6 @@ const batchApply = () => { }; -const editorRef = ref(null); - -// 文件库选择弹窗状态 -const showFileSelector = ref(false); -const fileSelectCallback = ref<((url: string) => void) | null>(null); - -// 视频库选择弹窗状态 -const showVideoSelector = ref(false); -const videoSelectCallback = ref<((url: string) => void) | null>(null); - -// 编辑器可见性控制 -// 删除了 TinyMCE 相关代码,改用 MdEditor -const editorVisible = ref(false); - -// 当 Tab 切换到商品详情时,启用编辑器 -watch( - () => active.value, - (key) => { - if (key === 'content') { - // 切换到商品详情 Tab 时,等待 DOM 渲染完成后启用编辑器 - nextTick(() => { - setTimeout(() => { - editorVisible.value = true; - console.log('[shopGoodsEdit] Switched to content tab, editorVisible = true'); - }, 100); - }); - } - }, - { immediate: true } -); - -const markdownToolbars = [ - 'bold', - 'underline', - 'italic', - '-', - 'title', - 'strikeThrough', - 'quote', - 'unorderedList', - 'orderedList', - 'task', - '-', - 'codeRow', - 'code', - 'link', - 'image', - 'table', - '-', - 'revoke', - 'next', - '=', - 'pageFullscreen', - 'fullscreen', - 'preview', - 'previewOnly' -]; - -// Markdown 图片上传 -const onMarkdownUploadImg = async ( - files: File[], - callback: (urls: string[]) => void -) => { - try { - const uploadPromises = files.map(async (file) => { - if (file.size > 10 * 1024 * 1024) { - message.error(`图片 ${file.name} 大小超过10MB`); - return null; - } - const res = await uploadOss(file); - return res.url || res.path; - }); - const results = await Promise.all(uploadPromises); - callback(results.filter(Boolean) as string[]); - } catch (err: any) { - message.error(err.message || '图片上传失败'); - } -}; - -// TinyMCE config 已移除,改用 MdEditor -const config = ref({}); - const {resetFields} = useForm(form, rules); const COMMISSION_PERCENT_FIELDS = [ @@ -2164,7 +2043,7 @@ watch( category.value = JSON.parse(props.data.category); } if (props.data.content) { - content.value = props.data.content; + content.value = toEditorContent(props.data.content); } isUpdate.value = true; @@ -2200,17 +2079,4 @@ watch(