jvs-docx-ui 0.0.0-stage → 0.1.1
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/README.md +96 -2
- package/dist/lib/index.d.ts +171 -0
- package/dist/lib/jvs-docx-ui.css +1 -0
- package/dist/lib/jvs-docx-ui.js +6288 -0
- package/dist/lib/jvs-docx-ui.umd.cjs +38 -0
- package/package.json +43 -3
package/README.md
CHANGED
|
@@ -1,3 +1,97 @@
|
|
|
1
|
-
#
|
|
1
|
+
# jvs-docx-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
基于 **Vue 3 + TypeScript + Vite + docxjs (`docx-preview`)** 构建的 Word (`.docx`) 文档预览组件库,同时支持 **独立站点部署** 与 **Vue 3 插件 NPM 发布**。
|
|
4
|
+
|
|
5
|
+
## 1. 开发与构建指令
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 安装依赖
|
|
9
|
+
pnpm install
|
|
10
|
+
|
|
11
|
+
# 启动本地开发调试 (支持 0.0.0.0 局域网访问)
|
|
12
|
+
pnpm dev
|
|
13
|
+
|
|
14
|
+
# 构建可独立部署的 Web 应用(产物位于 dist/app)
|
|
15
|
+
pnpm build
|
|
16
|
+
|
|
17
|
+
# 构建可发布的 Vue 3 插件库(产物位于 dist/lib,包含 ES/UMD 与 .d.ts 类型声明)
|
|
18
|
+
pnpm build:lib
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 2. 支持的文档加载方式
|
|
22
|
+
|
|
23
|
+
### 方式一:作为 Vue 3 插件通过 Props 直接传入文件链接或文件流
|
|
24
|
+
|
|
25
|
+
`<JvsDocx />` 同时支持 `fileUrl`、`url`、`src`、`fileContent`、`v-model` 绑定远程/本地链接、`File`、`Blob`、`ArrayBuffer`、`Uint8Array` 或 Base64 字符串:
|
|
26
|
+
|
|
27
|
+
```vue
|
|
28
|
+
<script setup lang="ts">
|
|
29
|
+
import { ref } from 'vue'
|
|
30
|
+
import { JvsDocx } from 'jvs-docx-ui'
|
|
31
|
+
import 'jvs-docx-ui/style.css'
|
|
32
|
+
|
|
33
|
+
const docUrl = ref('https://example.com/files/contract.docx')
|
|
34
|
+
const headers = { Authorization: 'Bearer xxx' }
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<template>
|
|
38
|
+
<div style="height: 100vh">
|
|
39
|
+
<JvsDocx :file-url="docUrl" :request-headers="headers" />
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 方式二:通过组件 Ref 实例方法主动加载(链接或本地文件)
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
import { ref } from 'vue'
|
|
49
|
+
import { JvsDocx, type JvsDocxExpose } from 'jvs-docx-ui'
|
|
50
|
+
import 'jvs-docx-ui/style.css'
|
|
51
|
+
|
|
52
|
+
const docxRef = ref<JvsDocxExpose | null>(null)
|
|
53
|
+
|
|
54
|
+
// 1. 通过文件 URL 链接加载(支持自定义请求头)
|
|
55
|
+
async function loadByUrl(url: string) {
|
|
56
|
+
await docxRef.value?.loadFromUrl(url, {
|
|
57
|
+
fileName: '技术协议.docx',
|
|
58
|
+
headers: { Authorization: 'Bearer xxx' }
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 2. 通过本地 File / Blob / ArrayBuffer / Base64 加载
|
|
63
|
+
async function onFileChange(e: Event) {
|
|
64
|
+
const file = (e.target as HTMLInputElement).files?.[0]
|
|
65
|
+
if (file) {
|
|
66
|
+
await docxRef.value?.importDocxFile(file, file.name)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 3. 导出当前预览的 .docx 文件
|
|
71
|
+
async function onExport() {
|
|
72
|
+
await docxRef.value?.exportDocxFile('导出文档.docx', true)
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<div style="height: 600px">
|
|
78
|
+
<JvsDocx ref="docxRef" />
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 方式三:独立站点部署模式下的外部传参加载
|
|
84
|
+
|
|
85
|
+
1. **URL 查询参数自动加载**:
|
|
86
|
+
直接访问 `http://your-host/?fileUrl=https://example.com/demo.docx&fileName=示例文档.docx`(或 `?url=...`),页面挂载后会自动拉取链接并渲染预览。
|
|
87
|
+
2. **顶部工具栏链接输入**:
|
|
88
|
+
在顶部工具栏输入框中粘贴 `.docx` 链接并点击「加载链接」或按回车即可预览。
|
|
89
|
+
3. **iframe `postMessage` 通信加载**:
|
|
90
|
+
```js
|
|
91
|
+
iframeWindow.postMessage({
|
|
92
|
+
type: 'jvs-docx:load',
|
|
93
|
+
fileUrl: 'https://example.com/demo.docx',
|
|
94
|
+
fileName: '示例文档.docx',
|
|
95
|
+
headers: { Authorization: 'Bearer xxx' }
|
|
96
|
+
}, '*')
|
|
97
|
+
```
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { ComponentOptionsMixin } from 'vue';
|
|
2
|
+
import { ComponentProvideOptions } from 'vue';
|
|
3
|
+
import { defaultOptions } from 'docx-preview';
|
|
4
|
+
import { DefineComponent } from 'vue';
|
|
5
|
+
import { Options as DocxPreviewOptions } from 'docx-preview';
|
|
6
|
+
import { parseAsync } from 'docx-preview';
|
|
7
|
+
import { Plugin as Plugin_2 } from 'vue';
|
|
8
|
+
import { PublicProps } from 'vue';
|
|
9
|
+
import { renderAsync } from 'docx-preview';
|
|
10
|
+
import { renderDocument } from 'docx-preview';
|
|
11
|
+
import { WordDocument } from 'docx-preview';
|
|
12
|
+
|
|
13
|
+
export { defaultOptions }
|
|
14
|
+
|
|
15
|
+
export declare const DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
16
|
+
|
|
17
|
+
export declare type DocxInputSource = File | Blob | ArrayBuffer | Uint8Array | string | {
|
|
18
|
+
url?: string;
|
|
19
|
+
fileUrl?: string;
|
|
20
|
+
content?: File | Blob | ArrayBuffer | Uint8Array | string;
|
|
21
|
+
fileName?: string;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
requestInit?: RequestInit;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export declare interface DocxLoadOptions {
|
|
27
|
+
/** 指定文件名(不传则自动从 File.name / Content-Disposition / URL 路径推断) */
|
|
28
|
+
fileName?: string;
|
|
29
|
+
/** 请求远程文件链接时的自定义请求头(例如 Authorization Token) */
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
/** 请求远程文件链接时的透传 fetch RequestInit 配置 */
|
|
32
|
+
requestInit?: RequestInit;
|
|
33
|
+
/** 自定义文件拉取函数 */
|
|
34
|
+
customFetch?: (url: string, init?: RequestInit) => Promise<Blob | ArrayBuffer | Uint8Array | Response>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { DocxPreviewOptions }
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 触发浏览器下载 .docx Blob
|
|
41
|
+
*/
|
|
42
|
+
export declare function downloadDocxBlob(blob: Blob, fileName?: string): void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 从 URL 或 Content-Disposition 响应头中提取文件名
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractFileNameFromUrl(url: string, contentDisposition?: string | null): string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 通过 URL 拉取远程或本地 .docx 文件并转为 Blob
|
|
51
|
+
*/
|
|
52
|
+
export declare function fetchDocxFromUrl(url: string, options?: DocxLoadOptions): Promise<NormalizedDocxResult>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 判断字符串是否为 URL 或文件路径(而非纯 Base64 字符串)
|
|
56
|
+
*/
|
|
57
|
+
export declare function isLikelyUrlString(str: string): boolean;
|
|
58
|
+
|
|
59
|
+
export declare const JvsDocx: DefineComponent<JvsDocxProps, {
|
|
60
|
+
importDocxFile: (source: DocxInputSource, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
61
|
+
loadFromUrl: (url: string, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
62
|
+
renderDocx: (source: DocxInputSource, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
63
|
+
exportDocxFile: (fileName?: string, download?: boolean) => Promise<Blob>;
|
|
64
|
+
clear: () => void;
|
|
65
|
+
getWordDocument: () => WordDocument | null;
|
|
66
|
+
getBlob: () => Blob | null;
|
|
67
|
+
getFileName: () => string;
|
|
68
|
+
getContainer: () => HTMLElement | null;
|
|
69
|
+
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
70
|
+
error: (error: Error) => any;
|
|
71
|
+
rendered: (document: any) => any;
|
|
72
|
+
loaded: (payload: JvsDocxLoadedPayload) => any;
|
|
73
|
+
change: (blob: Blob | null) => any;
|
|
74
|
+
}, string, PublicProps, Readonly<JvsDocxProps> & Readonly<{
|
|
75
|
+
onError?: ((error: Error) => any) | undefined;
|
|
76
|
+
onRendered?: ((document: any) => any) | undefined;
|
|
77
|
+
onLoaded?: ((payload: JvsDocxLoadedPayload) => any) | undefined;
|
|
78
|
+
onChange?: ((blob: Blob | null) => any) | undefined;
|
|
79
|
+
}>, {
|
|
80
|
+
fileName: string;
|
|
81
|
+
requestInit: RequestInit;
|
|
82
|
+
customFetch: (url: string, init?: RequestInit) => Promise<Blob | ArrayBuffer | Uint8Array | Response>;
|
|
83
|
+
fileUrl: string;
|
|
84
|
+
fileContent: DocxInputSource;
|
|
85
|
+
url: string;
|
|
86
|
+
src: DocxInputSource;
|
|
87
|
+
modelValue: DocxInputSource;
|
|
88
|
+
requestHeaders: Record<string, string>;
|
|
89
|
+
options: Partial<DocxPreviewOptions>;
|
|
90
|
+
}, {}, {}, {}, string, ComponentProvideOptions, false, {
|
|
91
|
+
previewContainerRef: HTMLDivElement;
|
|
92
|
+
}, HTMLDivElement>;
|
|
93
|
+
|
|
94
|
+
export declare interface JvsDocxExpose {
|
|
95
|
+
/** 导入并渲染 .docx 文档(支持 File / Blob / ArrayBuffer / Uint8Array / URL 链接 / Base64 / 配置对象) */
|
|
96
|
+
importDocxFile: (source: DocxInputSource, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
97
|
+
/** 通过远程或本地文件链接地址加载并渲染 .docx 文档 */
|
|
98
|
+
loadFromUrl: (url: string, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
99
|
+
/** 使用 docxjs 渲染加载 .docx 文档(importDocxFile 的别名) */
|
|
100
|
+
renderDocx: (source: DocxInputSource, optionsOrFileName?: string | DocxLoadOptions) => Promise<WordDocument>;
|
|
101
|
+
/** 导出当前预览的 .docx 文件 */
|
|
102
|
+
exportDocxFile: (fileName?: string, download?: boolean) => Promise<Blob>;
|
|
103
|
+
/** 清空当前文档预览内容 */
|
|
104
|
+
clear: () => void;
|
|
105
|
+
/** 获取当前 docxjs 解析后的 WordDocument AST 对象 */
|
|
106
|
+
getWordDocument: () => WordDocument | null;
|
|
107
|
+
/** 获取当前文档的原始 Blob 数据 */
|
|
108
|
+
getBlob: () => Blob | null;
|
|
109
|
+
/** 获取当前加载的文档文件名 */
|
|
110
|
+
getFileName: () => string;
|
|
111
|
+
/** 获取预览容器 DOM 节点 */
|
|
112
|
+
getContainer: () => HTMLElement | null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export declare interface JvsDocxLoadedPayload {
|
|
116
|
+
fileName: string;
|
|
117
|
+
blob: Blob;
|
|
118
|
+
document: WordDocument;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export declare interface JvsDocxProps {
|
|
122
|
+
/** Word (.docx) 文件内容或链接(支持 File / Blob / ArrayBuffer / Uint8Array / URL / Base64 / 配置对象) */
|
|
123
|
+
fileContent?: DocxInputSource;
|
|
124
|
+
/** 远程或本地 .docx 文件链接地址 */
|
|
125
|
+
fileUrl?: string;
|
|
126
|
+
/** 远程或本地 .docx 文件链接地址(fileUrl 的简写别名) */
|
|
127
|
+
url?: string;
|
|
128
|
+
/** 通用文档数据源或链接地址(支持 URL / File / Blob / ArrayBuffer / Base64) */
|
|
129
|
+
src?: DocxInputSource;
|
|
130
|
+
/** 支持 v-model 绑定文档数据源或文件链接 */
|
|
131
|
+
modelValue?: DocxInputSource;
|
|
132
|
+
/** 默认文档名称(用于导出时默认文件名) */
|
|
133
|
+
fileName?: string;
|
|
134
|
+
/** 请求远程文件链接时的自定义请求头(例如 Authorization Token) */
|
|
135
|
+
requestHeaders?: Record<string, string>;
|
|
136
|
+
/** 请求远程文件链接时的 fetch RequestInit 配置(如 credentials: 'include') */
|
|
137
|
+
requestInit?: RequestInit;
|
|
138
|
+
/** 自定义远程文件拉取函数 */
|
|
139
|
+
customFetch?: DocxLoadOptions['customFetch'];
|
|
140
|
+
/** docxjs (docx-preview) 渲染配置项 */
|
|
141
|
+
options?: Partial<DocxPreviewOptions>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
declare const JvsDocxUiPlugin: Plugin_2;
|
|
145
|
+
export { JvsDocxUiPlugin }
|
|
146
|
+
export default JvsDocxUiPlugin;
|
|
147
|
+
|
|
148
|
+
export declare interface NormalizedDocxResult {
|
|
149
|
+
blob: Blob;
|
|
150
|
+
fileName: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 将各种输入源(File / Blob / ArrayBuffer / Uint8Array / URL 链接 / Base64 / 配置对象)统一解析为 Blob 与文件名
|
|
155
|
+
*/
|
|
156
|
+
export declare function normalizeDocxSource(source: DocxInputSource, options?: DocxLoadOptions): Promise<NormalizedDocxResult>;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 兼容旧版 API:将各种输入源统一转换为 Blob
|
|
160
|
+
*/
|
|
161
|
+
export declare function normalizeDocxSourceToBlob(source: DocxInputSource, options?: DocxLoadOptions): Promise<Blob>;
|
|
162
|
+
|
|
163
|
+
export { parseAsync }
|
|
164
|
+
|
|
165
|
+
export { renderAsync }
|
|
166
|
+
|
|
167
|
+
export { renderDocument }
|
|
168
|
+
|
|
169
|
+
export { WordDocument }
|
|
170
|
+
|
|
171
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.jvs-docx-viewer[data-v-34e07d63]{position:relative;width:100%;height:100%;min-height:360px;background-color:#f1f5f9;overflow:hidden;display:flex;flex-direction:column}.jvs-docx-viewer__container[data-v-34e07d63]{flex:1;width:100%;height:100%;overflow:auto}.jvs-docx-viewer__overlay[data-v-34e07d63]{position:absolute;top:0;right:0;bottom:0;left:0;z-index:5;background-color:#f1f5f9;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;color:#64748b;text-align:center;-webkit-user-select:none;user-select:none}.jvs-docx-viewer__overlay--error[data-v-34e07d63]{color:#ef4444}.jvs-docx-viewer__empty-icon[data-v-34e07d63]{display:flex;align-items:center;justify-content:center;width:76px;height:76px;border-radius:16px;background-color:#e2e8f0;color:#64748b;margin-bottom:16px}.jvs-docx-viewer__state-title[data-v-34e07d63]{margin:0 0 6px;font-size:15px;font-weight:600;color:#334155}.jvs-docx-viewer__overlay--error .jvs-docx-viewer__state-title[data-v-34e07d63]{margin-top:12px;color:#dc2626}.jvs-docx-viewer__state-desc[data-v-34e07d63]{margin:0;font-size:13px;color:#94a3b8;max-width:440px;line-height:1.6}.jvs-docx-viewer__state-text[data-v-34e07d63]{margin:14px 0 0;font-size:13px;color:#64748b}.jvs-docx-viewer__spinner[data-v-34e07d63]{width:32px;height:32px;border:3px solid #cbd5e1;border-top-color:#2563eb;border-radius:50%;animation:jvs-docx-spin-34e07d63 .75s linear infinite}@keyframes jvs-docx-spin-34e07d63{to{transform:rotate(360deg)}}.jvs-docx-viewer__container[data-v-34e07d63] .docx-wrapper{background-color:#f1f5f9;padding:24px 16px 40px;display:flex;flex-direction:column;align-items:center;min-height:100%}.jvs-docx-viewer__container[data-v-34e07d63] .docx-wrapper>section.docx{background-color:#fff;box-shadow:0 4px 16px #0f172a14,0 1px 3px #0f172a0a;border-radius:2px;margin-bottom:20px;padding:72pt 90pt}.jvs-docx-viewer__container[data-v-34e07d63] section.docx p[class*=docx-num-]:before{white-space:pre;margin-right:4pt}.jvs-docx-viewer__container[data-v-34e07d63] section.docx table{max-width:100%}.jvs-docx-viewer__container[data-v-34e07d63] section.docx img{max-width:100%}
|