From 7b796cfe238090b32f000d8667bf617470c508ce Mon Sep 17 00:00:00 2001 From: wux_labs Date: Fri, 3 Jan 2025 21:25:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=87=BA=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/index.ts | 10 ++ src/components/menus/toolbar/Classic.ts | 54 ++++++++ src/components/menus/toolbar/Ribbon.ts | 54 ++++++++ .../menus/toolbar/export/ExportDocx.ts | 68 ++++++++++ .../menus/toolbar/export/ExportMarkdown.ts | 68 ++++++++++ .../menus/toolbar/export/ExportOdt.ts | 68 ++++++++++ .../menus/toolbar/export/ExportPdf.ts | 119 ++++++++++++++++++ src/core/UAIExtensions.ts | 5 + 8 files changed, 446 insertions(+) create mode 100644 src/components/menus/toolbar/export/ExportDocx.ts create mode 100644 src/components/menus/toolbar/export/ExportMarkdown.ts create mode 100644 src/components/menus/toolbar/export/ExportOdt.ts create mode 100644 src/components/menus/toolbar/export/ExportPdf.ts diff --git a/src/components/index.ts b/src/components/index.ts index 621b388..2fdaa8d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -78,6 +78,11 @@ import { ToggleToc } from "./menus/toolbar/page/ToggleToc.ts"; import { BackgroundColor } from "./menus/toolbar/page/BackgroundColor.ts"; import { Watermark } from "./menus/toolbar/page/Watermark.ts"; +import { ExportDocx } from "./menus/toolbar/export/ExportDocx.ts"; +import { ExportOdt } from "./menus/toolbar/export/ExportOdt.ts"; +import { ExportPdf } from "./menus/toolbar/export/ExportPdf.ts"; +import { ExportMarkdown } from "./menus/toolbar/export/ExportMarkdown.ts"; + // 注册组件 defineCustomElement('uai-editor-header', Header); defineCustomElement('uai-editor-editor', Editor); @@ -155,3 +160,8 @@ defineCustomElement('uai-editor-tools-menu-diagrams', Diagrams); defineCustomElement('uai-editor-page-menu-toggle-toc', ToggleToc); defineCustomElement('uai-editor-page-menu-background-color', BackgroundColor); defineCustomElement('uai-editor-page-menu-watermark', Watermark); + +defineCustomElement('uai-editor-export-menu-docx', ExportDocx); +defineCustomElement('uai-editor-export-menu-odt', ExportOdt); +defineCustomElement('uai-editor-export-menu-pdf', ExportPdf); +defineCustomElement('uai-editor-export-menu-markdown', ExportMarkdown); diff --git a/src/components/menus/toolbar/Classic.ts b/src/components/menus/toolbar/Classic.ts index 95347d1..6f44274 100644 --- a/src/components/menus/toolbar/Classic.ts +++ b/src/components/menus/toolbar/Classic.ts @@ -71,6 +71,11 @@ import { ToggleToc } from "./page/ToggleToc.ts"; import { BackgroundColor } from "./page/BackgroundColor.ts"; import { Watermark } from "./page/Watermark.ts"; +import { ExportDocx } from "./export/ExportDocx.ts"; +import { ExportOdt } from "./export/ExportOdt.ts"; +import { ExportPdf } from "./export/ExportPdf.ts"; +import { ExportMarkdown } from "./export/ExportMarkdown.ts"; + /** * 传统菜单栏 */ @@ -102,6 +107,10 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { classicMenuPageScrollable!: ScrollableDiv; classicMenuPageGroup!: HTMLElement; + // 导出菜单容器 + classicMenuExportScrollable!: ScrollableDiv; + classicMenuExportGroup!: HTMLElement; + // 基础菜单 baseMenuUndo!: Undo; baseMenuRedo!: Redo; @@ -167,6 +176,12 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { pageMenuBackgroundColor!: BackgroundColor; pageMenuWatermark!: Watermark; + // 导出菜单 + exportMenuExportDocx!: ExportDocx; + exportMenuExportOdt!: ExportOdt; + exportMenuExportPdf!: ExportPdf; + exportMenuExportMarkdown!: ExportMarkdown; + constructor(defaultToolbarMenus: Record[]) { super(); this.defaultToolbarMenus = defaultToolbarMenus; @@ -215,6 +230,7 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { this.classicMenuTableScrollable.style.display = "none"; this.classicMenuToolScrollable.style.display = "none"; this.classicMenuPageScrollable.style.display = "none"; + this.classicMenuExportScrollable.style.display = "none"; if (menu === "base") { this.classicMenuBaseScrollable.style.display = "flex"; } @@ -230,6 +246,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { if (menu === "page") { this.classicMenuPageScrollable.style.display = "flex"; } + if (menu === "export") { + this.classicMenuExportScrollable.style.display = "flex"; + } }) // 创建分组菜单 this.createBaseMenu(event, options); @@ -237,6 +256,7 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { this.createTableMenu(event, options); this.createToolMenu(event, options); this.createPageMenu(event, options); + this.createExportMenu(event, options); this.classicMenuBaseScrollable.style.display = "flex"; } @@ -413,6 +433,18 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { this.pageMenuWatermark = new Watermark({ menuType: "popup", enable: true, header: "classic", hideText: false }); this.eventComponents.push(this.pageMenuWatermark); + + this.exportMenuExportDocx = new ExportDocx({ menuType: "button", enable: true, header: "classic", hideText: false }); + this.eventComponents.push(this.exportMenuExportDocx); + + this.exportMenuExportOdt = new ExportOdt({ menuType: "button", enable: true, header: "classic", hideText: false }); + this.eventComponents.push(this.exportMenuExportOdt); + + this.exportMenuExportPdf = new ExportPdf({ menuType: "button", enable: true, header: "classic", hideText: false }); + this.eventComponents.push(this.exportMenuExportPdf); + + this.exportMenuExportMarkdown = new ExportMarkdown({ menuType: "button", enable: true, header: "classic", hideText: false }); + this.eventComponents.push(this.exportMenuExportMarkdown); } /** * 创建基础菜单 @@ -586,4 +618,26 @@ export class Classic extends HTMLElement implements UAIEditorEventListener { group2.appendChild(this.pageMenuBackgroundColor); group2.appendChild(this.pageMenuWatermark); } + + /** + * 创建导出菜单 + * @param event + * @param options + */ + createExportMenu(event: EditorEvents["create"], options: UAIEditorOptions) { + this.classicMenuExportGroup = document.createElement("div"); + this.classicMenuExportGroup.style.display = "flex"; + this.classicMenuExportScrollable = new ScrollableDiv(this.classicMenuExportGroup); + this.classicMenuExportScrollable.style.display = "none"; + this.classicMenu.appendChild(this.classicMenuExportScrollable); + this.classicMenuExportScrollable.onCreate(event, options); + + const group1 = document.createElement("div"); + group1.classList.add("uai-classic-virtual-group"); + this.classicMenuExportGroup.appendChild(group1); + group1.appendChild(this.exportMenuExportDocx); + group1.appendChild(this.exportMenuExportOdt); + group1.appendChild(this.exportMenuExportPdf); + group1.appendChild(this.exportMenuExportMarkdown); + } } \ No newline at end of file diff --git a/src/components/menus/toolbar/Ribbon.ts b/src/components/menus/toolbar/Ribbon.ts index 860e764..aa1d32f 100644 --- a/src/components/menus/toolbar/Ribbon.ts +++ b/src/components/menus/toolbar/Ribbon.ts @@ -73,6 +73,11 @@ import { ToggleToc } from "./page/ToggleToc.ts"; import { BackgroundColor } from "./page/BackgroundColor.ts"; import { Watermark } from "./page/Watermark.ts"; +import { ExportDocx } from "./export/ExportDocx.ts"; +import { ExportOdt } from "./export/ExportOdt.ts"; +import { ExportPdf } from "./export/ExportPdf.ts"; +import { ExportMarkdown } from "./export/ExportMarkdown.ts"; + /** * 经典菜单栏 */ @@ -105,6 +110,10 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { ribbonMenuPageScrollable!: ScrollableDiv; ribbonMenuPageGroup!: HTMLElement; + // 导出菜单容器 + ribbonMenuExportScrollable!: ScrollableDiv; + ribbonMenuExportGroup!: HTMLElement; + // 基础菜单 baseMenuUndo!: Undo; baseMenuRedo!: Redo; @@ -170,6 +179,12 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { pageMenuBackgroundColor!: BackgroundColor; pageMenuWatermark!: Watermark; + // 导出菜单 + exportMenuExportDocx!: ExportDocx; + exportMenuExportOdt!: ExportOdt; + exportMenuExportPdf!: ExportPdf; + exportMenuExportMarkdown!: ExportMarkdown; + constructor(defaultToolbarMenus: Record[]) { super(); this.defaultToolbarMenus = defaultToolbarMenus; @@ -211,6 +226,7 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { this.ribbonMenuTableScrollable.style.display = "none"; this.ribbonMenuToolScrollable.style.display = "none"; this.ribbonMenuPageScrollable.style.display = "none"; + this.ribbonMenuExportScrollable.style.display = "none"; if (menu.value === "base") { this.ribbonMenuBaseScrollable.style.display = "flex"; } @@ -226,6 +242,9 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { if (menu.value === "page") { this.ribbonMenuPageScrollable.style.display = "flex"; } + if (menu.value === "export") { + this.ribbonMenuExportScrollable.style.display = "flex"; + } }) ribbonTabs.appendChild(tab); }); @@ -248,6 +267,7 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { this.createTableMenu(event, options); this.createToolMenu(event, options); this.createPageMenu(event, options); + this.createExportMenu(event, options); this.ribbonMenuBaseScrollable.style.display = "flex"; } @@ -436,6 +456,18 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { this.pageMenuWatermark = new Watermark({ menuType: "popup", enable: true, huge: true, hideText: false }); this.eventComponents.push(this.pageMenuWatermark); + + this.exportMenuExportDocx = new ExportDocx({ menuType: "button", enable: true, huge: true, hideText: false }); + this.eventComponents.push(this.exportMenuExportDocx); + + this.exportMenuExportOdt = new ExportOdt({ menuType: "button", enable: true, huge: true, hideText: false }); + this.eventComponents.push(this.exportMenuExportOdt); + + this.exportMenuExportPdf = new ExportPdf({ menuType: "button", enable: true, huge: true, hideText: false }); + this.eventComponents.push(this.exportMenuExportPdf); + + this.exportMenuExportMarkdown = new ExportMarkdown({ menuType: "button", enable: true, huge: true, hideText: false }); + this.eventComponents.push(this.exportMenuExportMarkdown); } /** @@ -691,4 +723,26 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener { group2.appendChild(this.pageMenuBackgroundColor); group2.appendChild(this.pageMenuWatermark); } + + /** + * 创建导出菜单 + * @param event + * @param options + */ + createExportMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { + this.ribbonMenuExportGroup = document.createElement("div"); + this.ribbonMenuExportGroup.classList.add("uai-ribbon-container"); + this.ribbonMenuExportGroup.style.display = "flex"; + this.ribbonMenuExportScrollable = new ScrollableDiv(this.ribbonMenuExportGroup); + this.ribbonMenuExportScrollable.style.display = "none"; + this.ribbonScrollableContainer.appendChild(this.ribbonMenuExportScrollable); + + const group1 = document.createElement("div"); + group1.classList.add("uai-ribbon-virtual-group"); + this.ribbonMenuExportGroup.appendChild(group1); + group1.appendChild(this.exportMenuExportDocx); + group1.appendChild(this.exportMenuExportOdt); + group1.appendChild(this.exportMenuExportPdf); + group1.appendChild(this.exportMenuExportMarkdown); + } } \ No newline at end of file diff --git a/src/components/menus/toolbar/export/ExportDocx.ts b/src/components/menus/toolbar/export/ExportDocx.ts new file mode 100644 index 0000000..04522a2 --- /dev/null +++ b/src/components/menus/toolbar/export/ExportDocx.ts @@ -0,0 +1,68 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import icon from "../../../../assets/icons/file-docx.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions, InnerEditor } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 导出菜单:导出Docx + */ +export class ExportDocx extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('export.docx.text'), + tooltip: t('export.docx.title'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,导出文件 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + event.editor.chain().focus().export({ format: 'docx' }).run(); + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/toolbar/export/ExportMarkdown.ts b/src/components/menus/toolbar/export/ExportMarkdown.ts new file mode 100644 index 0000000..ecf8d05 --- /dev/null +++ b/src/components/menus/toolbar/export/ExportMarkdown.ts @@ -0,0 +1,68 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import icon from "../../../../assets/icons/file-markdown.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions, InnerEditor } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 导出菜单:导出Markdown + */ +export class ExportMarkdown extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('export.markdown.text'), + tooltip: t('export.markdown.title'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,导出文件 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + event.editor.chain().focus().export({ format: 'md' }).run(); + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/toolbar/export/ExportOdt.ts b/src/components/menus/toolbar/export/ExportOdt.ts new file mode 100644 index 0000000..338b789 --- /dev/null +++ b/src/components/menus/toolbar/export/ExportOdt.ts @@ -0,0 +1,68 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import icon from "../../../../assets/icons/file-odt.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions, InnerEditor } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 导出菜单:导出Odt + */ +export class ExportOdt extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('export.odt.text'), + tooltip: t('export.odt.title'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,导出文件 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + event.editor.chain().focus().export({ format: 'odt' }).run(); + } + }) + } + + /** + * 定义Transaction监听方法 + * @param event + * @param options + */ + onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { + this.menuButton.onTransaction(event, options); + } + + onEditableChange(editable: boolean) { + this.menuButtonOptions.enable = editable; + this.menuButton.onEditableChange(editable); + } +} + diff --git a/src/components/menus/toolbar/export/ExportPdf.ts b/src/components/menus/toolbar/export/ExportPdf.ts new file mode 100644 index 0000000..53e8911 --- /dev/null +++ b/src/components/menus/toolbar/export/ExportPdf.ts @@ -0,0 +1,119 @@ +// Copyright (c) 2024-present AI-Labs + +// @ ts-nocheck +import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts"; +import icon from "../../../../assets/icons/file-pdf.svg"; +import { t } from "i18next"; +import { UAIEditorEventListener, UAIEditorOptions, InnerEditor } from "../../../../core/UAIEditor.ts"; +import { EditorEvents } from "@tiptap/core"; + +/** + * 导出菜单:导出PDF + */ +export class ExportPdf extends HTMLElement implements UAIEditorEventListener { + // 按钮选项 + menuButtonOptions: MenuButtonOptions = { + menuType: "button", + enable: true, + icon: icon, + hideText: true, + text: t('export.pdf.text'), + tooltip: t('export.pdf.title'), + } + + // 功能按钮 + menuButton: MenuButton; + + constructor(options: MenuButtonOptions) { + super(); + + // 初始化功能按钮选项 + this.menuButtonOptions = { ...this.menuButtonOptions, ...options }; + + // 创建功能按钮 + this.menuButton = new MenuButton(this.menuButtonOptions); + } + + /** + * 定义创建方法 + * @param event + * @param options + */ + onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { + this.menuButton.onCreate(event, options); + this.appendChild(this.menuButton); + + // 定义按钮点击事件,导出文件 + this.addEventListener("click", () => { + if (this.menuButtonOptions.enable) { + event.editor.commands.blur(); + const iframe = document.createElement("iframe"); + iframe.classList.add("uai-print-iframe"); + document.body.appendChild(iframe); + + const printContent = ` + + + + 有爱文档(UAI-Editor) + + + ${Array.from(document.querySelectorAll('link, style')).map((item) => item.outerHTML).join('')} + + + + +
+ ${document.querySelector(`.uai-zoomable-container`)?.outerHTML ?? ''} +
+