@wanghe1995/docx-editor-ui-lite 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/docx-editor-lite.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
(function(){"use strict";try{if(typeof document!="undefined"){var e=document.createElement("style");e.appendChild(document.createTextNode("")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
|
|
1
2
|
var i = Object.defineProperty;
|
|
2
3
|
var s = (e, t, r) => t in e ? i(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
|
|
3
4
|
var n = (e, t, r) => s(e, typeof t != "symbol" ? t + "" : t, r);
|
|
@@ -6,21 +7,22 @@ export * from "@wanghe1995/docx-editor-core";
|
|
|
6
7
|
const a = (e) => {
|
|
7
8
|
if (typeof e == "string") {
|
|
8
9
|
const t = document.querySelector(e);
|
|
9
|
-
if (!t)
|
|
10
|
-
throw new Error(`Mount target not found: ${e}`);
|
|
10
|
+
if (!t) throw new Error(`Mount target not found: ${e}`);
|
|
11
11
|
return t;
|
|
12
12
|
}
|
|
13
|
-
if (!e)
|
|
14
|
-
throw new Error("Mount target is required");
|
|
13
|
+
if (!e) throw new Error("Mount target is required");
|
|
15
14
|
return e;
|
|
16
15
|
};
|
|
17
|
-
class
|
|
16
|
+
class l {
|
|
18
17
|
constructor(t) {
|
|
19
|
-
n(this, "config");
|
|
20
18
|
n(this, "editor", null);
|
|
21
19
|
n(this, "_container");
|
|
22
20
|
var r;
|
|
23
|
-
this.config = t, this._container = a(t.container), this._applyDefaultTheme(), this.editor = new h(
|
|
21
|
+
this.config = t, this._container = a(t.container), this._applyDefaultTheme(), this.editor = new h(
|
|
22
|
+
this._container,
|
|
23
|
+
t.data || { main: [] },
|
|
24
|
+
t.options || {}
|
|
25
|
+
), this._bindListeners(), (r = t.onReady) == null || r.call(t, this.editor);
|
|
24
26
|
}
|
|
25
27
|
_applyDefaultTheme() {
|
|
26
28
|
const t = document.documentElement;
|
|
@@ -41,8 +43,7 @@ class f {
|
|
|
41
43
|
return this._container;
|
|
42
44
|
}
|
|
43
45
|
executeCommand(t, ...r) {
|
|
44
|
-
if (!this.editor)
|
|
45
|
-
return;
|
|
46
|
+
if (!this.editor) return;
|
|
46
47
|
const o = this.editor.command[t];
|
|
47
48
|
if (typeof o == "function")
|
|
48
49
|
return o(...r);
|
|
@@ -52,5 +53,5 @@ class f {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
export {
|
|
55
|
-
|
|
56
|
+
l as WordEditor
|
|
56
57
|
};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(){"use strict";try{if(typeof document!="undefined"){var e=document.createElement("style");e.appendChild(document.createTextNode("")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
|
|
2
|
+
(function(t,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("@wanghe1995/docx-editor-core")):typeof define=="function"&&define.amd?define(["exports","@wanghe1995/docx-editor-core"],n):(t=typeof globalThis<"u"?globalThis:t||self,n(t["docx-editor-lite"]={},t.DocxEditorCore))})(this,function(t,n){"use strict";var a=Object.defineProperty;var c=(t,n,o)=>n in t?a(t,n,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[n]=o;var s=(t,n,o)=>c(t,typeof n!="symbol"?n+"":n,o);const o=i=>{if(typeof i=="string"){const e=document.querySelector(i);if(!e)throw new Error(`Mount target not found: ${i}`);return e}if(!i)throw new Error("Mount target is required");return i};class h{constructor(e){s(this,"editor",null);s(this,"_container");var r;this.config=e,this._container=o(e.container),this._applyDefaultTheme(),this.editor=new n(this._container,e.data||{main:[]},e.options||{}),this._bindListeners(),(r=e.onReady)==null||r.call(e,this.editor)}_applyDefaultTheme(){const e=document.documentElement;e.style.setProperty("--tabs-bg-color","#2B579A"),e.style.setProperty("--tabs-text-color","#ffffff")}_bindListeners(){this.editor&&(this.config.onChange&&(this.editor.listener.contentChange=this.config.onChange),this.config.onPageChange&&(this.editor.listener.pageSizeChange=this.config.onPageChange),this.config.onScaleChange&&(this.editor.listener.pageScaleChange=this.config.onScaleChange))}get command(){var e;return(e=this.editor)==null?void 0:e.command}get listener(){var e;return(e=this.editor)==null?void 0:e.listener}get container(){return this._container}executeCommand(e,...r){if(!this.editor)return;const d=this.editor.command[e];if(typeof d=="function")return d(...r)}destroy(){this.editor&&(this.editor.destroy(),this.editor=null)}}t.WordEditor=h,Object.keys(n).forEach(i=>{i!=="default"&&!Object.prototype.hasOwnProperty.call(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:()=>n[i]})}),Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import DocxEditor from '@wanghe1995/docx-editor-core';
|
|
2
|
-
import type { IEditorData, IElement, IEditorOption } from '@wanghe1995/docx-editor-core';
|
|
1
|
+
import { default as DocxEditor, IEditorData, IElement, IEditorOption } from '@wanghe1995/docx-editor-core';
|
|
3
2
|
export interface WordEditorOptions {
|
|
4
3
|
container: string | HTMLElement;
|
|
5
4
|
data?: IEditorData | IElement[];
|
|
@@ -16,8 +15,8 @@ export declare class WordEditor {
|
|
|
16
15
|
constructor(config: WordEditorOptions);
|
|
17
16
|
private _applyDefaultTheme;
|
|
18
17
|
private _bindListeners;
|
|
19
|
-
get command(): import(
|
|
20
|
-
get listener(): import(
|
|
18
|
+
get command(): import('@wanghe1995/docx-editor-transform').Command | undefined;
|
|
19
|
+
get listener(): import('@wanghe1995/docx-editor-state').Listener | undefined;
|
|
21
20
|
get container(): HTMLDivElement;
|
|
22
21
|
executeCommand(command: string, ...args: any[]): any;
|
|
23
22
|
destroy(): void;
|
package/package.json
CHANGED
|
@@ -1,58 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@wanghe1995/docx-editor-ui-lite",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "DocxEditor 精简版UI库(Lite)",
|
|
5
|
-
"author": "wanghe",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "./dist/docx-editor-lite.umd.cjs",
|
|
9
|
-
"module": "./dist/docx-editor-lite.js",
|
|
10
|
-
"types": "./dist/src/editor/index.d.ts",
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"types": "./dist/src/editor/index.d.ts",
|
|
14
|
-
"import": "./dist/docx-editor-lite.js",
|
|
15
|
-
"require": "./dist/docx-editor-lite.umd.cjs"
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
40
|
-
"eslint
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"typescript
|
|
44
|
-
"
|
|
45
|
-
"vite
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@wanghe1995/docx-editor-ui-lite",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "DocxEditor 精简版UI库(Lite)",
|
|
5
|
+
"author": "wanghe",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/docx-editor-lite.umd.cjs",
|
|
9
|
+
"module": "./dist/docx-editor-lite.js",
|
|
10
|
+
"types": "./dist/src/editor/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/src/editor/index.d.ts",
|
|
14
|
+
"import": "./dist/docx-editor-lite.js",
|
|
15
|
+
"require": "./dist/docx-editor-lite.umd.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"static",
|
|
24
|
+
"fonts",
|
|
25
|
+
"README.md",
|
|
26
|
+
"package.json"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"dev": "vite --config vite.config.ts",
|
|
30
|
+
"clean": "node -e \"const fs = require('fs'); if(fs.existsSync('dist')) fs.rmSync('dist', {recursive: true})\"",
|
|
31
|
+
"build": "npm run clean && vite build --config vite.lib.config.ts",
|
|
32
|
+
"lint": "eslint .",
|
|
33
|
+
"type:check": "tsc --noEmit"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@eslint/js": "^10.0.1",
|
|
37
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
38
|
+
"@types/node": "^25.3.3",
|
|
39
|
+
"@vitejs/plugin-vue": "^5.1.4",
|
|
40
|
+
"eslint": "^10.4.0",
|
|
41
|
+
"eslint-plugin-unused-imports": "^4.4.1",
|
|
42
|
+
"tslib": "^2.8.1",
|
|
43
|
+
"typescript": "^5.0.0",
|
|
44
|
+
"typescript-eslint": "^8.59.4",
|
|
45
|
+
"vite": "^5.4.10",
|
|
46
|
+
"vite-plugin-css-injected-by-js": "^2.4.0",
|
|
47
|
+
"vite-plugin-dts": "^4.5.4",
|
|
48
|
+
"vue-tsc": "^2.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=16.0.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@wanghe1995/docx-editor-core": "^3.0.8",
|
|
55
|
+
"vue": "^3.4.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"vue": "^3.4.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2
|
+
html, body { height: 100%; overflow: auto; }
|
|
3
|
+
body { font-family: 'Microsoft YaHei', '微软雅黑', 'Google Sans', Roboto, Arial, sans-serif; background: #f1f3f4; display: flex; flex-direction: column; min-height: 100vh; }
|
|
4
|
+
|
|
5
|
+
.top-fixed-area { position: sticky; top: 0; z-index: 100; background: #fff; }
|
|
6
|
+
|
|
7
|
+
.menu-bar { display: flex; align-items: center; background: #fff; padding: 8px 12px; border-bottom: 1px solid #dadce0; }
|
|
8
|
+
.menu-bar .logo { width: 40px; height: 40px; margin-right: 12px; display: flex; align-items: center; justify-content: center; }
|
|
9
|
+
.menu-bar .doc-info { flex: 1; min-width: 0; }
|
|
10
|
+
.doc-title-row { display: flex; align-items: center; width: fit-content; max-width: 100%; }
|
|
11
|
+
.menu-bar .doc-title { font-size: 18px; font-weight: 500; color: #202124; border: none; outline: none; padding: 4px 8px; border-radius: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
12
|
+
.menu-bar .doc-title:hover { background: #f1f3f4; }
|
|
13
|
+
.menu-bar .menu-items { display: flex; gap: 4px; margin-top: 4px; }
|
|
14
|
+
.menu-bar .menu-item { padding: 4px 8px; font-size: 13px; color: #5f6368; cursor: pointer; border-radius: 4px; position: relative; }
|
|
15
|
+
.menu-bar .menu-item:hover { background: #f1f3f4; }
|
|
16
|
+
|
|
17
|
+
.dropdown-menu { display: none; position: absolute; top: 100%; left: 0; background: #fff; border: 1px solid #dadce0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); min-width: 180px; z-index: 200; padding: 4px 0; }
|
|
18
|
+
.dropdown-menu.show { display: block; }
|
|
19
|
+
.dropdown-item { display: flex; align-items: center; justify-content: space-between; padding: 6px 16px; font-size: 13px; color: #3c4043; cursor: pointer; white-space: nowrap; }
|
|
20
|
+
.dropdown-item:hover { background: #edf2fa; }
|
|
21
|
+
.dropdown-item .shortcut-hint { font-size: 12px; color: #80868b; margin-left: 24px; }
|
|
22
|
+
.dropdown-separator { height: 1px; background: #dadce0; margin: 4px 0; }
|
|
23
|
+
.dropdown-item .sub-arrow { margin-left: auto; font-size: 12px; color: #80868b; }
|
|
24
|
+
.dropdown-submenu { display: none; position: absolute; left: 100%; top: 0; background: #fff; border: 1px solid #dadce0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); min-width: 200px; z-index: 201; padding: 4px 0; }
|
|
25
|
+
.dropdown-item:hover > .dropdown-submenu { display: block; }
|
|
26
|
+
|
|
27
|
+
.toolbar { display: flex; align-items: center; background: #edf2fa; padding: 4px 12px; gap: 2px; flex-wrap: wrap; border-bottom: 1px solid #dadce0; }
|
|
28
|
+
.toolbar-divider { width: 1px; height: 24px; background: #dadce0; margin: 0 4px; }
|
|
29
|
+
.toolbar-btn { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: 4px; cursor: pointer; font-size: 18px; color: #444746; position: relative; }
|
|
30
|
+
.toolbar-btn:hover { background: #d3e3fd; }
|
|
31
|
+
.toolbar-btn[title]:hover::after { content: attr(title); position: absolute; bottom: -28px; left: 50%; transform: translateX(-50%); background: #3c4043; color: #fff; font-size: 11px; padding: 4px 8px; border-radius: 4px; white-space: nowrap; z-index: 1000; }
|
|
32
|
+
.toolbar-select { height: 32px; padding: 0 8px; border: none; background: transparent; border-radius: 4px; font-size: 13px; color: #444746; cursor: pointer; outline: none; }
|
|
33
|
+
.toolbar-select:hover { background: #d3e3fd; }
|
|
34
|
+
.color-picker { width: 32px; height: 32px; padding: 4px; border: none; background: transparent; border-radius: 4px; cursor: pointer; }
|
|
35
|
+
.color-picker:hover { background: #d3e3fd; }
|
|
36
|
+
|
|
37
|
+
.body-area { display: flex; flex: 1; min-height: 0; }
|
|
38
|
+
|
|
39
|
+
.catalog-sidebar { width: 0; overflow: hidden; background: #fff; border-right: 1px solid #dadce0; transition: width 0.2s ease; flex-shrink: 0; margin-left: 8px; }
|
|
40
|
+
.catalog-sidebar.open { width: 300px; }
|
|
41
|
+
.catalog-sidebar-inner { height: 100%; display: flex; flex-direction: column; }
|
|
42
|
+
.catalog-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid #e8eaed; }
|
|
43
|
+
.catalog-header h3 { font-size: 14px; font-weight: 500; color: #202124; }
|
|
44
|
+
.catalog-close { background: none; border: none; cursor: pointer; color: #5f6368; font-size: 18px; padding: 2px; border-radius: 4px; }
|
|
45
|
+
.catalog-close:hover { background: #f1f3f4; }
|
|
46
|
+
.catalog-tree { flex: 1; overflow-y: auto; padding: 8px 0; }
|
|
47
|
+
.catalog-empty { padding: 20px 12px; font-size: 13px; color: #80868b; text-align: center; }
|
|
48
|
+
|
|
49
|
+
.catalog-node { padding: 4px 8px; cursor: pointer; border-radius: 4px; margin: 1px 8px; font-size: 13px; color: #3c4043; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
50
|
+
.catalog-node:hover { background: #edf2fa; }
|
|
51
|
+
.catalog-node.level-1 { font-weight: 500; font-size: 14px; }
|
|
52
|
+
.catalog-node.level-2 { padding-left: 20px; }
|
|
53
|
+
.catalog-node.level-3 { padding-left: 32px; }
|
|
54
|
+
.catalog-node.level-4 { padding-left: 44px; }
|
|
55
|
+
.catalog-node.level-5 { padding-left: 56px; }
|
|
56
|
+
.catalog-node.level-6 { padding-left: 68px; }
|
|
57
|
+
|
|
58
|
+
.editor-wrapper { display: flex; justify-content: center; padding: 20px; flex: 1; overflow-y: auto; min-height: 0; }
|
|
59
|
+
#editor-container { background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
|
|
60
|
+
|
|
61
|
+
.status-bar { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 1px solid #dadce0; padding: 4px 12px; font-size: 12px; color: #5f6368; display: flex; justify-content: space-between; z-index: 50; align-items: center; }
|
|
62
|
+
.status-left { display: flex; align-items: center; gap: 12px; }
|
|
63
|
+
.status-right { display: flex; align-items: center; gap: 4px; }
|
|
64
|
+
.status-btn { background: none; border: none; color: #5f6368; font-size: 12px; cursor: pointer; padding: 2px 6px; border-radius: 3px; }
|
|
65
|
+
.status-btn:hover { background: #f1f3f4; }
|
|
66
|
+
.status-icon-btn { display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; }
|
|
67
|
+
.status-divider { width: 1px; height: 14px; background: #dadce0; }
|
|
68
|
+
.zoom-display { min-width: 36px; text-align: center; font-size: 12px; color: #444746; }
|
|
69
|
+
.catalog-toggle-label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; }
|
|
70
|
+
.catalog-toggle-label input[type="checkbox"] { margin: 0; cursor: pointer; }
|
|
71
|
+
.catalog-toggle-label span { font-size: 12px; }
|
|
72
|
+
.paper-size-wrap { position: relative; }
|
|
73
|
+
.paper-size-dropdown { display: none; position: absolute; bottom: 100%; left: 0; background: #fff; border: 1px solid #dadce0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); min-width: 180px; max-height: 240px; overflow-y: auto; z-index: 200; padding: 4px 0; margin-bottom: 4px; }
|
|
74
|
+
.paper-size-dropdown.show { display: block; }
|
|
75
|
+
.paper-size-item { padding: 6px 12px; font-size: 12px; color: #3c4043; cursor: pointer; white-space: nowrap; }
|
|
76
|
+
.paper-size-item:hover { background: #edf2fa; }
|
|
77
|
+
.paper-size-item.active { background: #d3e3fd; color: #1a73e8; font-weight: 500; }
|
|
78
|
+
|
|
79
|
+
.popup-panel { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #fff; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.2); padding: 20px; z-index: 1000; min-width: 320px; }
|
|
80
|
+
.popup-panel.show { display: block; }
|
|
81
|
+
.popup-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.3); z-index: 999; }
|
|
82
|
+
.popup-overlay.show { display: block; }
|
|
83
|
+
.popup-title { font-size: 16px; font-weight: 500; margin-bottom: 16px; }
|
|
84
|
+
.popup-row { margin-bottom: 12px; }
|
|
85
|
+
.popup-row label { display: block; font-size: 13px; color: #5f6368; margin-bottom: 4px; }
|
|
86
|
+
.popup-row input, .popup-row select { width: 100%; padding: 8px 12px; border: 1px solid #dadce0; border-radius: 4px; font-size: 14px; }
|
|
87
|
+
.popup-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
|
|
88
|
+
.popup-btn { padding: 8px 20px; border: none; border-radius: 4px; font-size: 14px; cursor: pointer; }
|
|
89
|
+
.popup-btn-primary { background: #1a73e8; color: #fff; }
|
|
90
|
+
.popup-btn-primary:hover { background: #1557b0; }
|
|
91
|
+
.popup-btn-secondary { background: #f1f3f4; color: #3c4043; }
|
|
92
|
+
.popup-btn-secondary:hover { background: #e8eaed; }
|
|
93
|
+
|
|
94
|
+
.zoom-control { display: flex; align-items: center; gap: 4px; }
|
|
95
|
+
.zoom-value { font-size: 13px; color: #444746; min-width: 40px; text-align: center; }
|
|
96
|
+
|
|
97
|
+
.shortcuts-content { max-height: 60vh; overflow-y: auto; padding: 0 8px; }
|
|
98
|
+
.shortcut-group { margin-bottom: 20px; }
|
|
99
|
+
.shortcut-group h3 { margin: 0 0 10px 0; font-size: 15px; font-weight: 600; color: #202124; padding-bottom: 8px; border-bottom: 1px solid #e8eaed; }
|
|
100
|
+
.shortcut-row { display: flex; align-items: center; justify-content: space-between; font-size: 13px; color: #5f6368; padding: 3px 0; }
|
|
101
|
+
.shortcut-row kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 24px; height: 22px; padding: 0 6px; background: #f1f3f4; border: 1px solid #dadce0; border-radius: 4px; font-size: 12px; font-family: inherit; color: #202124; margin: 0 2px; }
|
|
102
|
+
|
|
103
|
+
.save-indicator { display: inline-flex; align-items: center; font-size: 12px; color: #80868b; margin-left: 12px; }
|
|
104
|
+
.save-indicator.saving { color: #1a73e8; }
|
|
105
|
+
|
|
106
|
+
.import-notification { position: fixed; bottom: 60px; right: 20px; background: #fff; border: 1px solid #dadce0; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.15); padding: 16px; z-index: 500; min-width: 280px; display: none; }
|
|
107
|
+
.import-notification.show { display: block; }
|
|
108
|
+
.import-notification h4 { font-size: 14px; font-weight: 500; margin-bottom: 8px; color: #202124; }
|
|
109
|
+
.import-notification p { font-size: 12px; color: #5f6368; margin-bottom: 12px; }
|
|
110
|
+
.import-notification .import-actions { display: flex; gap: 8px; justify-content: flex-end; }
|
|
111
|
+
.import-notification .import-btn { padding: 6px 16px; border: none; border-radius: 4px; font-size: 13px; cursor: pointer; min-width: 64px; }
|
|
112
|
+
.import-notification .import-btn-primary { background: #1a73e8; color: #fff; }
|
|
113
|
+
.import-notification .import-btn-primary:hover { background: #1557b0; }
|
|
114
|
+
.import-notification .import-btn-secondary { background: #f1f3f4; color: #3c4043; }
|
|
115
|
+
.import-notification .import-btn-secondary:hover { background: #e8eaed; }
|
package/static/js/app.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { WordEditor, RowFlex, TitleLevel, ListType, ListStyle, parseDocx } from '../../src/editor/index.ts'
|
|
2
|
+
|
|
3
|
+
const testData = {
|
|
4
|
+
main: []
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let documentMeta = {
|
|
8
|
+
id: 'DEU' + Array.from({length: 4}, () => Math.random().toString(16).slice(2).toUpperCase().padEnd(4, '0').slice(0, 4)).join(''),
|
|
9
|
+
name: '新建文档',
|
|
10
|
+
createdAt: new Date().toISOString(),
|
|
11
|
+
submittedAt: ''
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let importModeResolver = null
|
|
15
|
+
|
|
16
|
+
const editor = new WordEditor({
|
|
17
|
+
container: '#editor-container',
|
|
18
|
+
data: testData,
|
|
19
|
+
options: {
|
|
20
|
+
width: 794,
|
|
21
|
+
height: 1123,
|
|
22
|
+
margins: [96, 120, 96, 120],
|
|
23
|
+
defaultFont: '微软雅黑',
|
|
24
|
+
defaultSize: 14,
|
|
25
|
+
marginIndicatorDisabled: true,
|
|
26
|
+
lineBreak: { disabled: false, color: '#AAAAAA' }
|
|
27
|
+
},
|
|
28
|
+
onPageChange: (pageNo) => {
|
|
29
|
+
const el = document.getElementById('status-page')
|
|
30
|
+
if (el) el.textContent = `第 ${pageNo} 页`
|
|
31
|
+
},
|
|
32
|
+
onChange: () => {
|
|
33
|
+
updateWordCount()
|
|
34
|
+
debounceRefreshCatalog()
|
|
35
|
+
},
|
|
36
|
+
onScaleChange: (scale) => {
|
|
37
|
+
const pct = `${Math.round(scale * 100)}%`
|
|
38
|
+
document.getElementById('zoom-value').textContent = pct
|
|
39
|
+
const statusZoom = document.getElementById('status-zoom')
|
|
40
|
+
if (statusZoom) statusZoom.textContent = pct
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
function updateWordCount() {
|
|
45
|
+
try {
|
|
46
|
+
const result = editor.command.getWordCount()
|
|
47
|
+
const count = result?.count ?? 0
|
|
48
|
+
document.getElementById('status-words').textContent = `${count} 字`
|
|
49
|
+
} catch (e) {
|
|
50
|
+
// ignore
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setTimeout(() => updateWordCount(), 500)
|
|
55
|
+
|
|
56
|
+
window.editor = editor
|
|
57
|
+
window.RowFlex = RowFlex
|
|
58
|
+
window.TitleLevel = TitleLevel
|
|
59
|
+
window.ListType = ListType
|
|
60
|
+
window.ListStyle = ListStyle
|
|
61
|
+
|
|
62
|
+
window.execCmd = (cmd, ...args) => {
|
|
63
|
+
try {
|
|
64
|
+
focusEditorAgent()
|
|
65
|
+
editor.command[cmd](...args)
|
|
66
|
+
} catch (e) { console.error(`执行失败: ${cmd}`, e) }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function focusEditorAgent() {
|
|
70
|
+
try {
|
|
71
|
+
const container = document.getElementById('editor-container')
|
|
72
|
+
const agentDom = container?.querySelector('textarea')
|
|
73
|
+
if (agentDom && typeof agentDom.focus === 'function') {
|
|
74
|
+
agentDom.focus()
|
|
75
|
+
}
|
|
76
|
+
} catch (e) { /* ignore */ }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
window.setRowFlex = (flex) => { editor.command.executeRowFlex(RowFlex[flex]) }
|
|
80
|
+
window.setTitle = (level) => {
|
|
81
|
+
if (!level) { editor.command.executeTitle(null); return }
|
|
82
|
+
const levels = {
|
|
83
|
+
'1': TitleLevel.FIRST, '2': TitleLevel.SECOND, '3': TitleLevel.THIRD,
|
|
84
|
+
'4': TitleLevel.FOURTH, '5': TitleLevel.FIFTH, '6': TitleLevel.SIXTH
|
|
85
|
+
}
|
|
86
|
+
editor.command.executeTitle(levels[level])
|
|
87
|
+
}
|
|
88
|
+
window.setList = (type) => {
|
|
89
|
+
if (type === 'OL') { editor.command.executeList(ListType.OL, ListStyle.DECIMAL) }
|
|
90
|
+
else { editor.command.executeList(ListType.UL, ListStyle.DISC) }
|
|
91
|
+
}
|
|
92
|
+
window.setLineHeight = (value) => { editor.command.executeLineHeight(parseFloat(value)) }
|
|
93
|
+
|
|
94
|
+
window.showPopup = (id) => { document.getElementById('popup-overlay').classList.add('show'); document.getElementById(id).classList.add('show') }
|
|
95
|
+
window.closePopup = () => { document.getElementById('popup-overlay').classList.remove('show'); document.querySelectorAll('.popup-panel').forEach(p => p.classList.remove('show')) }
|
|
96
|
+
|
|
97
|
+
window.insertTable = () => showPopup('table-popup')
|
|
98
|
+
window.confirmInsertTable = () => { const rows = parseInt(document.getElementById('table-rows').value) || 3; const cols = parseInt(document.getElementById('table-cols').value) || 4; editor.command.executeInsertTable(rows, cols); closePopup() }
|
|
99
|
+
|
|
100
|
+
window.insertHyperlink = () => showPopup('link-popup')
|
|
101
|
+
window.confirmInsertLink = () => { const text = document.getElementById('link-text').value; const url = document.getElementById('link-url').value; if (url) { editor.command.executeHyperlink({ type: 'hyperlink', value: text || url, url }); } closePopup() }
|
|
102
|
+
|
|
103
|
+
window.insertImage = () => {
|
|
104
|
+
const input = document.createElement('input'); input.type = 'file'; input.accept = 'image/*'
|
|
105
|
+
input.onchange = (e) => {
|
|
106
|
+
const file = e.target.files[0]; if (!file) return
|
|
107
|
+
const reader = new FileReader()
|
|
108
|
+
reader.onload = (event) => {
|
|
109
|
+
const img = new Image(); img.onload = () => { const maxWidth = 400; const scale = img.width > maxWidth ? maxWidth / img.width : 1; editor.command.executeImage({ value: event.target.result, width: img.width * scale, height: img.height * scale }) }; img.src = event.target.result
|
|
110
|
+
}
|
|
111
|
+
reader.readAsDataURL(file)
|
|
112
|
+
}
|
|
113
|
+
input.click()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
window.searchReplace = () => showPopup('search-popup')
|
|
117
|
+
window.doSearch = () => { const text = document.getElementById('search-text').value; if (text) { const result = editor.command.executeSearch(text); alert(`找到 ${result?.count || 0} 处匹配`) } }
|
|
118
|
+
window.doReplace = () => { const search = document.getElementById('search-text').value; const replace = document.getElementById('replace-text').value; if (search) { editor.command.executeReplace(replace) } }
|
|
119
|
+
window.doReplaceAll = () => { const search = document.getElementById('search-text').value; const replace = document.getElementById('replace-text').value; if (search) { editor.command.executeSearch(search); let count = 0; while (editor.command.executeReplace(replace)) { count++; if (count > 1000) break; } alert(`已替换 ${count} 处`) } }
|
|
120
|
+
|
|
121
|
+
window.showShortcutsDialog = () => showPopup('shortcuts-popup')
|
|
122
|
+
|
|
123
|
+
// 菜单下拉交互
|
|
124
|
+
let activeDropdown = null
|
|
125
|
+
document.addEventListener('click', (e) => {
|
|
126
|
+
if (activeDropdown) {
|
|
127
|
+
activeDropdown.classList.remove('show')
|
|
128
|
+
activeDropdown = null
|
|
129
|
+
}
|
|
130
|
+
const menuItem = e.target.closest('.menu-item')
|
|
131
|
+
if (menuItem) {
|
|
132
|
+
const dropdown = menuItem.querySelector('.dropdown-menu')
|
|
133
|
+
if (dropdown) {
|
|
134
|
+
e.stopPropagation()
|
|
135
|
+
if (dropdown !== activeDropdown) {
|
|
136
|
+
if (activeDropdown) activeDropdown.classList.remove('show')
|
|
137
|
+
dropdown.classList.add('show')
|
|
138
|
+
activeDropdown = dropdown
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// 确保编辑器保持焦点(core快捷键监听在agentDom上)
|
|
145
|
+
const editorContainer = document.getElementById('editor-container')
|
|
146
|
+
if (editorContainer) {
|
|
147
|
+
const focusEditor = () => {
|
|
148
|
+
try {
|
|
149
|
+
const agentDom = editor.instance?.command?.__proxyGetAgentDom?.()
|
|
150
|
+
|| editorContainer.querySelector('textarea')
|
|
151
|
+
if (agentDom && typeof agentDom.focus === 'function') {
|
|
152
|
+
agentDom.focus()
|
|
153
|
+
}
|
|
154
|
+
} catch (e) { /* ignore */ }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
document.addEventListener('mousedown', (e) => {
|
|
158
|
+
const target = e.target
|
|
159
|
+
if (target && !editorContainer.contains(target) && !target.closest('.toolbar') && !target.closest('.menu-bar') && !target.closest('.popup-panel') && !target.closest('.status-bar') && !target.closest('.catalog-sidebar')) {
|
|
160
|
+
setTimeout(focusEditor, 0)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 快捷键全局监听
|
|
166
|
+
const editorContainerEl = document.getElementById('editor-container')
|
|
167
|
+
document.addEventListener('keydown', (e) => {
|
|
168
|
+
// 如果事件已被core库处理(焦点在编辑器内),则跳过编辑器内置快捷键
|
|
169
|
+
const inEditor = editorContainerEl && editorContainerEl.contains(e.target)
|
|
170
|
+
const ctrl = e.ctrlKey || e.metaKey
|
|
171
|
+
const shift = e.shiftKey
|
|
172
|
+
const key = e.key.toLowerCase()
|
|
173
|
+
|
|
174
|
+
// 应用级快捷键(始终拦截)
|
|
175
|
+
if (ctrl && key === 's') { e.preventDefault(); handleSave(); return }
|
|
176
|
+
if (ctrl && key === 'p') { e.preventDefault(); execCmd('executePrint'); return }
|
|
177
|
+
if (ctrl && key === 'f') { e.preventDefault(); searchReplace(); return }
|
|
178
|
+
if (ctrl && key === 'h') { e.preventDefault(); searchReplace(); return }
|
|
179
|
+
|
|
180
|
+
// 编辑器内置快捷键:仅焦点不在编辑器时兜底处理
|
|
181
|
+
if (inEditor) return
|
|
182
|
+
if (ctrl && !shift && key === 'z') { e.preventDefault(); execCmd('executeUndo'); return }
|
|
183
|
+
if (ctrl && shift && key === 'z') { e.preventDefault(); execCmd('executeRedo'); return }
|
|
184
|
+
if (ctrl && key === 'y') { e.preventDefault(); execCmd('executeRedo'); return }
|
|
185
|
+
if (ctrl && key === 'b') { e.preventDefault(); execCmd('executeBold'); return }
|
|
186
|
+
if (ctrl && key === 'i') { e.preventDefault(); execCmd('executeItalic'); return }
|
|
187
|
+
if (ctrl && key === 'u') { e.preventDefault(); execCmd('executeUnderline'); return }
|
|
188
|
+
if (ctrl && key === 'k') { e.preventDefault(); insertHyperlink(); return }
|
|
189
|
+
if (ctrl && key === '\\') { e.preventDefault(); execCmd('executeFormat'); return }
|
|
190
|
+
if (ctrl && key === 'enter') { e.preventDefault(); execCmd('executePageBreak'); return }
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
// 保存功能
|
|
194
|
+
window.handleSave = () => {
|
|
195
|
+
const indicator = document.getElementById('save-indicator')
|
|
196
|
+
try {
|
|
197
|
+
const content = editor.command.getValue()
|
|
198
|
+
if (!content) return
|
|
199
|
+
const snapshot = { meta: { ...documentMeta }, content }
|
|
200
|
+
documentMeta.submittedAt = new Date().toISOString()
|
|
201
|
+
indicator.textContent = '保存中...'
|
|
202
|
+
indicator.classList.add('saving')
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
indicator.textContent = `已保存 ${formatTime(new Date())}`
|
|
205
|
+
indicator.classList.remove('saving')
|
|
206
|
+
console.log('[save] 保存快照:', snapshot)
|
|
207
|
+
}, 300)
|
|
208
|
+
} catch (e) {
|
|
209
|
+
indicator.textContent = '保存失败'
|
|
210
|
+
indicator.classList.remove('saving')
|
|
211
|
+
console.error('保存失败:', e)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function formatTime(date) {
|
|
216
|
+
return `${String(date.getHours()).padStart(2,'0')}:${String(date.getMinutes()).padStart(2,'0')}:${String(date.getSeconds()).padStart(2,'0')}`
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 导入文档功能
|
|
220
|
+
window.handleImportDoc = () => {
|
|
221
|
+
const input = document.createElement('input')
|
|
222
|
+
input.type = 'file'
|
|
223
|
+
input.accept = '.docx,.doc'
|
|
224
|
+
input.onchange = (e) => {
|
|
225
|
+
const file = e.target.files[0]
|
|
226
|
+
if (!file) return
|
|
227
|
+
const fileSize = file.size < 1024 * 1024
|
|
228
|
+
? `${(file.size / 1024).toFixed(1)} KB`
|
|
229
|
+
: `${(file.size / 1024 / 1024).toFixed(1)} MB`
|
|
230
|
+
|
|
231
|
+
const notification = document.getElementById('import-notification')
|
|
232
|
+
document.getElementById('import-info').textContent = `${file.name} (${fileSize})`
|
|
233
|
+
notification.classList.add('show')
|
|
234
|
+
|
|
235
|
+
importModeResolver = (mode) => {
|
|
236
|
+
notification.classList.remove('show')
|
|
237
|
+
if (mode === 'cancel') return
|
|
238
|
+
|
|
239
|
+
const hex = () => Math.random().toString(16).slice(2).toUpperCase().padEnd(4, '0').slice(0, 4)
|
|
240
|
+
const newId = 'DEU' + hex() + hex() + hex() + hex()
|
|
241
|
+
documentMeta.id = newId
|
|
242
|
+
documentMeta.name = file.name.replace(/\.\w+$/, '')
|
|
243
|
+
const titleInput = document.getElementById('doc-title')
|
|
244
|
+
titleInput.value = documentMeta.name
|
|
245
|
+
titleInput.title = documentMeta.name
|
|
246
|
+
|
|
247
|
+
const reader = new FileReader()
|
|
248
|
+
reader.onload = async (event) => {
|
|
249
|
+
try {
|
|
250
|
+
const arrayBuffer = event.target.result
|
|
251
|
+
const result = await parseDocx(arrayBuffer)
|
|
252
|
+
|
|
253
|
+
if (!result.success || !result.elements || result.elements.length === 0) {
|
|
254
|
+
alert('文档解析失败: ' + (result.error || '未知错误'))
|
|
255
|
+
return
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (mode === 'overwrite') {
|
|
259
|
+
editor.command.executeSetValue({ main: result.elements })
|
|
260
|
+
} else {
|
|
261
|
+
const current = editor.command.getValue()
|
|
262
|
+
const currentElements = current?.data?.main || current?.main || []
|
|
263
|
+
const merged = [...currentElements, ...result.elements]
|
|
264
|
+
editor.command.executeSetValue({ main: merged })
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
updateWordCount()
|
|
268
|
+
refreshCatalog()
|
|
269
|
+
handleSave()
|
|
270
|
+
} catch (err) {
|
|
271
|
+
console.error('导入失败:', err)
|
|
272
|
+
alert('导入失败: ' + (err.message || '未知错误'))
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
reader.readAsArrayBuffer(file)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
input.click()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
window.handleImportAction = (mode) => {
|
|
282
|
+
if (importModeResolver) {
|
|
283
|
+
const resolver = importModeResolver
|
|
284
|
+
importModeResolver = null
|
|
285
|
+
resolver(mode)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// 文档标题同步
|
|
290
|
+
document.getElementById('doc-title').addEventListener('input', (e) => {
|
|
291
|
+
documentMeta.name = e.target.value
|
|
292
|
+
e.target.title = e.target.value
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// 目录功能
|
|
296
|
+
const levelOrderMap = {
|
|
297
|
+
first: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let catalogOpen = true
|
|
301
|
+
let catalogRefreshTimer = null
|
|
302
|
+
|
|
303
|
+
const debounceRefreshCatalog = () => {
|
|
304
|
+
if (catalogRefreshTimer) clearTimeout(catalogRefreshTimer)
|
|
305
|
+
catalogRefreshTimer = setTimeout(() => refreshCatalog(), 1000)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function refreshCatalog() {
|
|
309
|
+
try {
|
|
310
|
+
const catalog = await editor.command.getCatalog()
|
|
311
|
+
renderCatalog(Array.isArray(catalog) ? catalog : [])
|
|
312
|
+
} catch (e) {
|
|
313
|
+
// ignore
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function getLevelNumber(level) {
|
|
318
|
+
if (typeof level === 'number') return level
|
|
319
|
+
return levelOrderMap[level] || 1
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function renderCatalog(catalog) {
|
|
323
|
+
const treeEl = document.getElementById('catalog-tree')
|
|
324
|
+
const emptyEl = document.getElementById('catalog-empty')
|
|
325
|
+
|
|
326
|
+
treeEl.querySelectorAll('.catalog-node').forEach(n => n.remove())
|
|
327
|
+
|
|
328
|
+
if (!catalog || catalog.length === 0) {
|
|
329
|
+
emptyEl.style.display = 'block'
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
emptyEl.style.display = 'none'
|
|
333
|
+
|
|
334
|
+
const renderItems = (items) => {
|
|
335
|
+
for (const item of items) {
|
|
336
|
+
const node = document.createElement('div')
|
|
337
|
+
node.className = `catalog-node level-${getLevelNumber(item.level)}`
|
|
338
|
+
node.textContent = item.name || ''
|
|
339
|
+
node.title = item.name || ''
|
|
340
|
+
if (item.id) {
|
|
341
|
+
node.addEventListener('click', () => {
|
|
342
|
+
try { editor.command.executeLocationCatalog(item.id) } catch (e) { console.error('定位失败:', e) }
|
|
343
|
+
})
|
|
344
|
+
}
|
|
345
|
+
treeEl.appendChild(node)
|
|
346
|
+
if (item.subCatalog && item.subCatalog.length > 0) {
|
|
347
|
+
renderItems(item.subCatalog)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
renderItems(catalog)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
window.toggleCatalog = (checked) => {
|
|
355
|
+
catalogOpen = typeof checked === 'boolean' ? checked : !catalogOpen
|
|
356
|
+
const sidebar = document.getElementById('catalog-sidebar')
|
|
357
|
+
const cb = document.getElementById('catalog-toggle-cb')
|
|
358
|
+
if (catalogOpen) {
|
|
359
|
+
sidebar.classList.add('open')
|
|
360
|
+
if (cb) cb.checked = true
|
|
361
|
+
refreshCatalog()
|
|
362
|
+
} else {
|
|
363
|
+
sidebar.classList.remove('open')
|
|
364
|
+
if (cb) cb.checked = false
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 初始化时打开目录并刷新
|
|
369
|
+
setTimeout(() => {
|
|
370
|
+
const sidebar = document.getElementById('catalog-sidebar')
|
|
371
|
+
if (sidebar) sidebar.classList.add('open')
|
|
372
|
+
refreshCatalog()
|
|
373
|
+
}, 800)
|
|
374
|
+
|
|
375
|
+
// 纸张方向切换
|
|
376
|
+
let paperDirection = 'vertical'
|
|
377
|
+
window.togglePaperDirection = () => {
|
|
378
|
+
paperDirection = paperDirection === 'vertical' ? 'horizontal' : 'vertical'
|
|
379
|
+
document.getElementById('paper-direction-btn').textContent = paperDirection === 'vertical' ? '纵向' : '横向'
|
|
380
|
+
try {
|
|
381
|
+
editor.command.executePaperDirection(paperDirection)
|
|
382
|
+
} catch (e) { console.error('切换纸张方向失败:', e) }
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// 纸张大小选择
|
|
386
|
+
let paperSizeMenuOpen = false
|
|
387
|
+
window.togglePaperSizeMenu = () => {
|
|
388
|
+
paperSizeMenuOpen = !paperSizeMenuOpen
|
|
389
|
+
const dropdown = document.getElementById('paper-size-dropdown')
|
|
390
|
+
if (paperSizeMenuOpen) {
|
|
391
|
+
dropdown.classList.add('show')
|
|
392
|
+
} else {
|
|
393
|
+
dropdown.classList.remove('show')
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
document.addEventListener('click', (e) => {
|
|
398
|
+
if (paperSizeMenuOpen && !e.target.closest('.paper-size-wrap')) {
|
|
399
|
+
paperSizeMenuOpen = false
|
|
400
|
+
document.getElementById('paper-size-dropdown').classList.remove('show')
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
window.setPaperSize = (width, height, label) => {
|
|
405
|
+
document.getElementById('paper-size-btn').textContent = label
|
|
406
|
+
paperSizeMenuOpen = false
|
|
407
|
+
document.getElementById('paper-size-dropdown').classList.remove('show')
|
|
408
|
+
document.querySelectorAll('.paper-size-item').forEach(item => {
|
|
409
|
+
item.classList.toggle('active', item.dataset.label === label)
|
|
410
|
+
})
|
|
411
|
+
try {
|
|
412
|
+
const w = paperDirection === 'horizontal' ? height : width
|
|
413
|
+
const h = paperDirection === 'horizontal' ? width : height
|
|
414
|
+
editor.command.executePaperSize(w, h)
|
|
415
|
+
} catch (e) { console.error('设置纸张大小失败:', e) }
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
console.log('DocxEditor UI Lite 初始化成功!')
|
|
File without changes
|