Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Office Viewer 支持 Excel #9826

Merged
merged 3 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Next Next commit
feat: Office viewer 支持 Excel
  • Loading branch information
nwind committed Mar 19, 2024
commit 26697d2ab1f4122d66e17f2bbd218a3adf3a21ac
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ indent_size = 4

[*.md]
trim_trailing_whitespace = false

[**.tsv]
indent_style = tab
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
*.ttf binary
*.woff binary
*.docx binary
*.xlsx binary
*.pptx binary
*.TTF binary
66 changes: 66 additions & 0 deletions docs/zh-CN/components/office-viewer-excel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Office Viewer Excel
description:
type: 0
group: ⚙ 组件
menuName: OfficeViewer Excel 渲染
icon:
order: 24
---

> 6.3 及以上版本

## 基本用法

```schema: scope="body"
{
"type": "office-viewer",
"src": "/examples/static/all.xlsx",
"excelOptions": {
"height": 500
}
}
```

除了 `xlsx`,也支持后缀为 `csv` 及 `tsv` 的文件

## 配置项

由于接口可能有变化,这里只列出少量配置项,后续补充

```schema: scope="body"
{
"type": "office-viewer",
"excelOptions": {
"showSheetTabBar": false,
"showFormulaBar": false
},
"src": "/examples/static/all.xlsx"
}
```

| 属性名 | 类型 | 默认值 | 说明 |
| --------------- | --------- | ------ | ------------------------ |
| showFormulaBar | `boolean` | true | 是否显示公式拦 |
| showSheetTabBar | `boolean` | true | 是否显示底部 sheet 切换 |
| fontURL | `object` | | 字体地址,参考下面的说明 |

## 字体配置

由于浏览器中缺少特定字体,将展现会不一致,这些字体都是有版权的,因此本项目中不提供,需要自行准备,然后配置 `fontURL` 映射到对应的地址,渲染时就会加载。

类似如下配置

```json
{
"type": "office-viewer",
"excelOptions": {
"fontURL": {
"等线": "/static/font/DengXian.ttf",
"仿宋": "/static/font/STFANGSO.TTF",
"黑体": "/static/font/simhei.ttf"
}
},
"src": "/examples/static/all.xlsx"
}
```
2 changes: 1 addition & 1 deletion docs/zh-CN/components/office-viewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ order: 23

> 2.9.0 及以上版本

用于渲染 office 文档,目前只支持 docx 格式
用于渲染 office 文档,目前只支持 docx 和 xlsx 格式,本文档只介绍 docx 的配置,xlsx 的配置请参考 [office-viewer-excel](office-viewer-excel)

## 基本用法

Expand Down
11 changes: 10 additions & 1 deletion examples/components/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -991,12 +991,21 @@ export const components = [
)
},
{
label: 'OfficeViewer 文档渲染',
label: 'OfficeViewer Word 渲染',
path: '/zh-CN/components/office-viewer',
component: React.lazy(() =>
import('../../docs/zh-CN/components/office-viewer.md').then(wrapDoc)
)
},
{
label: 'OfficeViewer Excel 渲染',
path: '/zh-CN/components/office-viewer-excel',
component: React.lazy(() =>
import('../../docs/zh-CN/components/office-viewer-excel.md').then(
wrapDoc
)
)
},
{
label: 'PDFViewer 渲染',
path: '/zh-CN/components/pdf-viewer',
Expand Down
9 changes: 6 additions & 3 deletions examples/components/OfficeViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ export default {
{
type: 'input-file',
name: 'file',
label: '选择 Docx 文件预览效果(不会上传到服务器)',
label: '选择 Docx/Excel 文件预览效果(不会上传到服务器)',
asBlob: true,
accept: '.docx'
accept: '.docx,.xlsx,.csv,.tsv'
},
{
type: 'office-viewer',
id: 'office-viewer',
name: 'file'
name: 'file',
excelOptions: {
height: 500
}
}
]
}
Expand Down
Binary file added examples/static/all.xlsx
Binary file not shown.
12 changes: 8 additions & 4 deletions fis-conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'!punycode/**',
'!office-viewer/**',
'!fflate/**',
'!numfmt/**',
'!amis-formula/lib/doc.js'
],

Expand Down Expand Up @@ -579,7 +580,7 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'echarts-wordcloud/**'
],

'office-viewer.js': ['office-viewer/**', 'fflate/**'],
'office-viewer.js': ['office-viewer/**', 'fflate/**', 'numfmt/**'],
'json-view.js': 'react-json-view/**',
'fomula-doc.js': 'amis-formula/lib/doc.js',

Expand Down Expand Up @@ -608,7 +609,8 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'!markdown-it/**',
'!markdown-it-html5-media/**',
'!office-viewer/**',
'!fflate/**'
'!fflate/**',
'!numfmt/**'
]
}),
postpackager: [
Expand Down Expand Up @@ -842,6 +844,7 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'!punycode/**',
'!amis-formula/**',
'!fflate/**',
'!numfmt/**',
'!office-viewer/**',
'!amis-core/**',
'!amis-ui/**',
Expand Down Expand Up @@ -908,7 +911,7 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'!/examples/components/EChartsEditor/Common.tsx'
],

'pkg/office-viewer.js': ['office-viewer/**', 'fflate/**'],
'pkg/office-viewer.js': ['office-viewer/**', 'fflate/**', 'numfmt/**'],

'pkg/rest.js': [
'**.{js,jsx,ts,tsx}',
Expand All @@ -933,7 +936,8 @@ if (fis.project.currentMedia() === 'publish-sdk') {
'!uc.micro/**',
'!markdown-it/**',
'!markdown-it-html5-media/**',
'!fflate/**'
'!fflate/**',
'!numfmt/**'
],

'pkg/npm.css': ['node_modules/*/**.css', '!monaco-editor/**', '!amis/**'],
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
/>
<link rel="stylesheet" href="/node_modules/katex/dist/katex.min.css" />
<link rel="stylesheet" href="/node_modules/prismjs/themes/prism.css" />
<link rel="stylesheet" href="/node_modules/office-viewer/dist/office.css" />
<link rel="stylesheet" href="/examples/doc.css" />

<link rel="stylesheet" href="/examples/style.scss" />
Expand Down
4 changes: 2 additions & 2 deletions packages/amis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"moment": "^2.19.4",
"moment-timezone": "^0.5.34",
"mpegts.js": "^1.6.10",
"office-viewer": "^0.2.1",
"office-viewer": "^0.3.5",
"prop-types": "^15.6.1",
"qrcode.react": "^3.1.0",
"react-cropper": "^2.1.8",
Expand Down Expand Up @@ -244,4 +244,4 @@
"react-dom": ">=16.8.6"
},
"gitHead": "37d23b4a8eb1c663bc38e8dd9040889ea1526ec4"
}
}
80 changes: 59 additions & 21 deletions packages/amis/src/renderers/OfficeViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
resolveVariableAndFilter,
ScopedContext
} from 'amis-core';
import type {Word} from 'office-viewer';
import type {Word, Excel} from 'office-viewer';
import {Spinner} from 'amis-ui';
import {Payload} from '../types';

Expand Down Expand Up @@ -55,13 +55,15 @@ export default class OfficeViewer extends React.Component<
> {
rootElement: React.RefObject<HTMLDivElement>;

word: Word;
office: Word | Excel;

fileName?: string;

// 文档数据,避免 update 参数的时候重复加载
document?: any;

finalSrc?: string;

constructor(props: OfficeViewerProps) {
super(props);
this.rootElement = React.createRef();
Expand Down Expand Up @@ -112,7 +114,7 @@ export default class OfficeViewer extends React.Component<
this.renderWord();
} else {
// 默认只更新变量提升性能
this.word?.updateVariable();
this.office?.updateVariable();
}
}
}
Expand All @@ -124,11 +126,11 @@ export default class OfficeViewer extends React.Component<
const actionType = action?.actionType as string;

if (actionType === 'saveAs') {
this.word?.download(args?.name || this.fileName);
this.office?.download(args?.name || this.fileName);
}

if (actionType === 'print') {
this.word?.print();
this.office?.print();
}
}

Expand Down Expand Up @@ -171,6 +173,9 @@ export default class OfficeViewer extends React.Component<
console.warn('file src is empty');
return;
}

this.finalSrc = finalSrc;

let response: Payload;

this.setState({
Expand All @@ -195,32 +200,69 @@ export default class OfficeViewer extends React.Component<
}
}

async initOffice(officeViewer: any, file?: ArrayBuffer) {
const {
wordOptions,
excelOptions,
env,
src,
data,
translate: __
} = this.props;
const createOfficeViewer = officeViewer.createOfficeViewer;
const office = await createOfficeViewer(
file || this.document,
{},
this.finalSrc
);

if (office instanceof officeViewer.Word) {
office.updateOptions({
...wordOptions,
data,
evalVar: this.evalVar.bind(this)
});
} else if (office instanceof officeViewer.Excel) {
office.updateOptions({
...excelOptions,
data,
evalVar: this.evalVar.bind(this)
});
await office.loadExcel();
}

return office;
}

/**
* 渲染远端文件
*/
async renderRemoteWord() {
const {wordOptions, env, src, data, display, translate: __} = this.props;
const {
wordOptions,
excelOptions,
env,
src,
data,
display,
translate: __
} = this.props;

if (!this.document) {
return;
}

import('office-viewer').then(async (officeViewer: any) => {
const Word = officeViewer.Word;
const word = new Word(this.document, {
...wordOptions,
data,
evalVar: this.evalVar.bind(this)
});
const office = await this.initOffice(officeViewer);

if (display !== false) {
word.render(this.rootElement?.current!);
office.render(this.rootElement?.current!);
} else if (display === false && this.rootElement?.current) {
// 设置为 false 后清空
this.rootElement.current.innerHTML = '';
}

this.word = word;
this.office = office;
});
}

Expand All @@ -236,18 +278,14 @@ export default class OfficeViewer extends React.Component<
const data = reader.result as ArrayBuffer;

import('office-viewer').then(async (officeViewer: any) => {
const Word = officeViewer.Word;
const word = new Word(data, {
...wordOptions,
evalVar: this.evalVar.bind(this)
});
const office = await this.initOffice(officeViewer, data);
if (display !== false) {
word.render(this.rootElement?.current!);
office.render(this.rootElement?.current!);
} else if (display === false && this.rootElement?.current) {
// 设置为 false 后清空
this.rootElement.current.innerHTML = '';
}
this.word = word;
this.office = office;
});
};
reader.readAsArrayBuffer(file);
Expand Down
8 changes: 5 additions & 3 deletions packages/office-viewer/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/coverage
/lib
/esm
coverage
lib
esm
.rollup.cache
~$*
Loading
Loading