mirror of
https://github.com/501351981/vue-office.git
synced 2025-06-15 07:00:00 +08:00
即日起不再免费提供源码
This commit is contained in:
parent
eceb244bf1
commit
dd2f71d6e4
@ -235,6 +235,8 @@ export default {
|
||||
|
||||
<img src="https://501351981.github.io/vue-office/examples/dist/static/wx.png" alt="赞助二维码" width="260"/>
|
||||
|
||||
## 打赏50及以上可向作者索要源码(仅限自己项目使用,不能复制开源)
|
||||
|
||||
<span style="color: red;">打赏的朋友欢迎**添加微信**</span>,交流前端开发中遇到的技术、问题和困惑。
|
||||
|
||||
>【<span style="color:red;">**仅添加**打赏过的用户,不定期删除屏蔽朋友圈的好友</span>(为什么打赏了才能微信问问题?那别人为什么要先付出时间去解答你的问题?都是成年人了,人与人之间是价值交换,不是单向付出)】
|
||||
@ -242,10 +244,3 @@ export default {
|
||||
|
||||
<img src="https://501351981.github.io/vue-office/examples/dist/static/wxqrcode.png" alt="个人微信" width="260"/>
|
||||
|
||||
|
||||
### 恳请各位大佬不吝点赞,开源不易,感谢支持~~
|
||||
|
||||
|
||||
## 我的其他库
|
||||
|
||||
- HowToCode:前端编程之道,探讨如何写出高质量的前端代码,总结前端编程的各种方法论、原则、思维模型等。[《前端编程之道》](https://github.com/501351981/HowToCode)
|
||||
|
@ -1,3 +0,0 @@
|
||||
node_modules/
|
||||
lib/
|
||||
dist/
|
@ -1,24 +0,0 @@
|
||||
module.exports = {
|
||||
'env': {
|
||||
'node': true,
|
||||
'es2021': true
|
||||
},
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-essential'
|
||||
],
|
||||
'overrides': [
|
||||
],
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 'latest',
|
||||
'sourceType': 'module'
|
||||
},
|
||||
'plugins': [
|
||||
'vue'
|
||||
],
|
||||
'rules': {
|
||||
'semi': ['error','always'],
|
||||
'no-multi-spaces': ['error', { ignoreEOLComments: false }],
|
||||
'quotes': ['error', 'single']
|
||||
}
|
||||
};
|
3
core/.gitattributes
vendored
3
core/.gitattributes
vendored
@ -1,3 +0,0 @@
|
||||
*.js linguist-language=JavaScript
|
||||
*.css linguist-language=JavaScript
|
||||
*.html linguist-language=JavaScript
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
21
core/LICENSE
21
core/LICENSE
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 hit757
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<title>@vue-office演示demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +0,0 @@
|
||||
51 error Error: Command failed with exit code 128: git tag v0.1.5 -m v0.1.5
|
||||
51 error fatal: tag 'v0.1.5' already exists
|
||||
51 error at makeError (/Users/liyulin/.nvm/versions/node/v16.15.0/lib/node_modules/lerna/node_modules/_execa@5.1.1@execa/lib/error.js:60:11)
|
||||
51 error at handlePromise (/Users/liyulin/.nvm/versions/node/v16.15.0/lib/node_modules/lerna/node_modules/_execa@5.1.1@execa/index.js:118:26)
|
||||
51 error at processTicksAndRejections (node:internal/process/task_queues:96:5)
|
||||
51 error at async Promise.all (index 0)
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.2.2"
|
||||
}
|
31249
core/package-lock.json
generated
31249
core/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,79 +0,0 @@
|
||||
{
|
||||
"name": "vue-office",
|
||||
"version": "1.0.0",
|
||||
"description": "通过Vue开发的办公文档预览组件,支持docx、pdf、ppt、excel(已实现)的预览",
|
||||
"scripts": {
|
||||
"dev": "node script/bak-vue.js && vite",
|
||||
"build": "node script/bak-vue.js && vite build",
|
||||
"lib": "node script/bak-vue.js bak && lerna run build",
|
||||
"lib:js-excel": "node script/bak-vue.js bak && lerna run build --scope @js-preview/excel",
|
||||
"lib:js-docx": "node script/bak-vue.js bak && lerna run build --scope @js-preview/docx",
|
||||
"lib:vue-excel": "node script/bak-vue.js bak && lerna run build --scope @vue-office/excel",
|
||||
"lib:vue-docx": "node script/bak-vue.js bak && lerna run build --scope @vue-office/docx",
|
||||
"lib:js-pdf": "node script/bak-vue.js bak && lerna run build --scope @js-preview/pdf",
|
||||
"lib:vue-pdf": "node script/bak-vue.js bak && lerna run build --scope @vue-office/pdf"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-runtime": "^7.23.6",
|
||||
"@babel/plugin-transform-template-literals": "^7.23.3",
|
||||
"@babel/preset-env": "^7.22.5",
|
||||
"@babel/runtime": "^7.23.6",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"ant-design-vue": "^3.2.17",
|
||||
"dayjs": "^1.11.7",
|
||||
"docx-preview": "^0.1.20",
|
||||
"exceljs": "^4.3.0",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "^8.4.24",
|
||||
"rimraf": "^4.1.2",
|
||||
"rollup": "^3.26.0",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"vue-demi": "^0.14.6",
|
||||
"x-data-spreadsheet": "^1.1.9",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^25.0.2",
|
||||
"@rollup/plugin-node-resolve": "^15.1.0",
|
||||
"@rollup/plugin-terser": "^0.4.3",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/composition-api": "^1.7.1",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"lerna": "^6.4.1",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.0",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-less": "^1.1.3",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"vite": "^4.0.0",
|
||||
"vite-plugin-require-transform": "^1.0.9",
|
||||
"vite-plugin-vue2": "^2.0.3",
|
||||
"vue": "3.2.45",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-template-compiler": "2.6.14",
|
||||
"vue2": "npm:vue@2.6.14",
|
||||
"vue3": "npm:vue@3.2.45"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_"
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
@ -1 +0,0 @@
|
||||
.vue-office-docx{height:100%;overflow-y:auto}.vue-office-docx .docx-wrapper>section.docx{margin-bottom:5px}@media screen and (max-width: 800px){.vue-office-docx .docx-wrapper{padding:10px}.vue-office-docx .docx-wrapper>section.docx{padding:10px!important;width:100%!important}}
|
31
core/packages/js-docx/index.d.ts
vendored
31
core/packages/js-docx/index.d.ts
vendored
@ -1,31 +0,0 @@
|
||||
export interface Options {
|
||||
inWrapper?: boolean;
|
||||
ignoreWidth?: boolean;
|
||||
ignoreHeight?: boolean;
|
||||
ignoreFonts?: boolean;
|
||||
breakPages?: boolean;
|
||||
debug?: boolean;
|
||||
experimental?: boolean;
|
||||
className?: string;
|
||||
trimXmlDeclaration?: boolean;
|
||||
renderHeaders?: boolean;
|
||||
renderFooters?: boolean;
|
||||
renderFootnotes?: boolean;
|
||||
renderEndnotes?: boolean;
|
||||
ignoreLastRenderedPageBreak?: boolean;
|
||||
useBase64URL?: boolean;
|
||||
useMathMLPolyfill?: boolean;
|
||||
renderChanges?: boolean;
|
||||
}
|
||||
|
||||
export interface JsDocxPreview {
|
||||
preview: (src: string | ArrayBuffer | Blob) => Promise<any>;
|
||||
save: (fileName?: string) => void;
|
||||
setOptions: (options: Options) => void;
|
||||
setRequestOptions: (requestOptions?: any) => void;
|
||||
destroy: ()=> void;
|
||||
}
|
||||
declare const jsPreviewDocx: {
|
||||
init: (container: HTMLElement, options?: Options, requestOptions?: any) => JsDocxPreview;
|
||||
};
|
||||
export default jsPreviewDocx;
|
@ -1,5 +0,0 @@
|
||||
import {init} from './src/main';
|
||||
|
||||
export default {
|
||||
init
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "@js-preview/docx",
|
||||
"type" :"module",
|
||||
"version": "1.6.0",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copyCss": "cp ./index.css ./lib/index.css",
|
||||
"copy": "npm run copyCss && npm run copyType && npm run copyReadme",
|
||||
"build": "npm run clean && rollup --config rollup.config.js && npm run copy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import {getBabelOutputPlugin} from '@rollup/plugin-babel';
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import terser from '@rollup/plugin-terser';
|
||||
|
||||
export default {
|
||||
input: 'index.js',
|
||||
output:[
|
||||
{
|
||||
file: 'lib/index.js',
|
||||
name: 'jsPreviewDocx',
|
||||
format: 'es',
|
||||
plugins: [getBabelOutputPlugin({ presets: ['@babel/preset-env'] })]
|
||||
},
|
||||
{
|
||||
file: 'lib/index.umd.js',
|
||||
name: 'jsPreviewDocx',
|
||||
format: 'umd'
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
commonjs(),
|
||||
terser()
|
||||
]
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
if(typeof window.setImmediate === 'undefined' ){
|
||||
window.setImmediate = function (func, ...args){
|
||||
setTimeout(()=>func(args));
|
||||
};
|
||||
}
|
||||
|
||||
export default {}
|
@ -1,63 +0,0 @@
|
||||
import hack from './hack.js';
|
||||
import docx from '../../vue-docx/src/docx';
|
||||
import {download as downloadFile} from '../../../utils/url.js';
|
||||
class JsDocxPreview {
|
||||
container = null;
|
||||
wrapper = null;
|
||||
wrapperMain = null;
|
||||
options = {};
|
||||
requestOptions = {};
|
||||
fileData = null;
|
||||
|
||||
constructor(container, options={}, requestOptions={}) {
|
||||
this.container = container;
|
||||
this.options = options;
|
||||
this.requestOptions = requestOptions;
|
||||
this.createWrapper();
|
||||
}
|
||||
createWrapper(){
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.className = 'vue-office-docx';
|
||||
this.wrapperMain = document.createElement('div');
|
||||
this.wrapperMain.className = 'vue-office-docx-main';
|
||||
this.wrapper.appendChild(this.wrapperMain);
|
||||
this.container.appendChild(this.wrapper);
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
this.options = options;
|
||||
}
|
||||
setRequestOptions(requestOptions) {
|
||||
this.requestOptions = requestOptions;
|
||||
}
|
||||
preview(src){
|
||||
return new Promise((resolve, reject) => {
|
||||
docx.getData(src, this.requestOptions).then(async res =>{
|
||||
this.fileData = await docx.getBlob(res);
|
||||
docx.render(this.fileData, this.wrapperMain, this.options).then(() => {
|
||||
resolve();
|
||||
}).catch(e => {
|
||||
docx.render('', this.wrapperMain, this.options);
|
||||
reject(e);
|
||||
});
|
||||
}).catch(err=>{
|
||||
docx.render('', this.wrapperMain, this.options);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
save(fileName){
|
||||
downloadFile(fileName || `js-preview-docx-${new Date().getTime()}.docx`,this.fileData);
|
||||
}
|
||||
destroy(){
|
||||
this.container.removeChild(this.wrapper);
|
||||
this.container = null;
|
||||
this.wrapper = null;
|
||||
this.wrapperMain = null;
|
||||
this.options = null;
|
||||
this.requestOptions = null;
|
||||
}
|
||||
}
|
||||
export function init(container, options, requestOptions){
|
||||
return new JsDocxPreview(container, options, requestOptions);
|
||||
}
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
@ -1,762 +0,0 @@
|
||||
.x-spreadsheet {
|
||||
font-size: 13px;
|
||||
line-height: normal;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
|
||||
box-sizing: content-box;
|
||||
background: #fff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.x-spreadsheet textarea {
|
||||
font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
|
||||
}
|
||||
.x-spreadsheet-sheet {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.x-spreadsheet-table {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.x-spreadsheet-tooltip {
|
||||
font-family: inherit;
|
||||
position: absolute;
|
||||
padding: 5px 10px;
|
||||
color: #fff;
|
||||
border-radius: 1px;
|
||||
background: #000000;
|
||||
font-size: 12px;
|
||||
z-index: 201;
|
||||
}
|
||||
.x-spreadsheet-tooltip:before {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
left: calc(50% - 4px);
|
||||
top: -4px;
|
||||
content: "";
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: inherit;
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
z-index: 1;
|
||||
box-shadow: 1px 1px 3px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.x-spreadsheet-color-palette {
|
||||
padding: 5px;
|
||||
}
|
||||
.x-spreadsheet-color-palette table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 2;
|
||||
background: #fff;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td {
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td:hover {
|
||||
border-color: #ddd;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.x-spreadsheet-border-palette {
|
||||
padding: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
background: #fff;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.x-spreadsheet-border-palette table td {
|
||||
margin: 0;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left {
|
||||
border-right: 1px solid #eee;
|
||||
padding-right: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right {
|
||||
padding-left: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
}
|
||||
.x-spreadsheet-dropdown {
|
||||
position: relative;
|
||||
}
|
||||
.x-spreadsheet-dropdown .x-spreadsheet-dropdown-content {
|
||||
position: absolute;
|
||||
z-index: 200;
|
||||
background: #fff;
|
||||
box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
|
||||
}
|
||||
.x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content {
|
||||
top: calc(100% + 5px);
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content {
|
||||
top: calc(100% + 5px);
|
||||
right: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content {
|
||||
bottom: calc(100% + 5px);
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content {
|
||||
bottom: calc(100% + 5px);
|
||||
right: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown .x-spreadsheet-dropdown-title {
|
||||
padding: 0 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
/* resizer **/
|
||||
.x-spreadsheet-resizer {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
}
|
||||
.x-spreadsheet-resizer .x-spreadsheet-resizer-hover {
|
||||
background-color: rgba(75, 137, 255, 0.25);
|
||||
}
|
||||
.x-spreadsheet-resizer .x-spreadsheet-resizer-line {
|
||||
position: absolute;
|
||||
}
|
||||
.x-spreadsheet-resizer.horizontal {
|
||||
cursor: row-resize;
|
||||
}
|
||||
.x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line {
|
||||
border-bottom: 2px dashed #4b89ff;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.x-spreadsheet-resizer.vertical {
|
||||
cursor: col-resize;
|
||||
}
|
||||
.x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line {
|
||||
border-right: 2px dashed #4b89ff;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
/* scrollbar */
|
||||
.x-spreadsheet-scrollbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #f4f5f8;
|
||||
opacity: 0.9;
|
||||
z-index: 12;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.horizontal {
|
||||
right: 15px;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.horizontal > div {
|
||||
height: 1px;
|
||||
background: #ddd;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.vertical {
|
||||
bottom: 15px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.vertical > div {
|
||||
width: 1px;
|
||||
background: #ddd;
|
||||
}
|
||||
/* @{css-prefix}-overlayer */
|
||||
.x-spreadsheet-overlayer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.x-spreadsheet-overlayer .x-spreadsheet-overlayer-content {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.x-spreadsheet-editor,
|
||||
.x-spreadsheet-selector {
|
||||
box-sizing: content-box;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/* @{css-prefix}-selector */
|
||||
.x-spreadsheet-selector .hide-input {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
}
|
||||
.x-spreadsheet-selector .hide-input input {
|
||||
padding: 0;
|
||||
width: 0;
|
||||
border: none!important;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-area {
|
||||
position: absolute;
|
||||
border: 2px solid #4b89ff;
|
||||
background: rgba(75, 137, 255, 0.1);
|
||||
z-index: 5;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-clipboard,
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
|
||||
position: absolute;
|
||||
background: transparent;
|
||||
z-index: 100;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-clipboard {
|
||||
border: 2px dashed #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
|
||||
border: 1px dashed rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-corner {
|
||||
pointer-events: auto;
|
||||
position: absolute;
|
||||
cursor: crosshair;
|
||||
font-size: 0;
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
border: 2px solid #ffffff;
|
||||
background: #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-editor {
|
||||
z-index: 20;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
border: 2px solid #4b89ff;
|
||||
line-height: 0;
|
||||
z-index: 100;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area textarea {
|
||||
box-sizing: content-box;
|
||||
border: none;
|
||||
padding: 0 3px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
text-align: start;
|
||||
overflow-y: hidden;
|
||||
font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
|
||||
color: inherit;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
line-height: 22px;
|
||||
margin: 0;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area .textline {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-item {
|
||||
user-select: none;
|
||||
background: 0;
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
height: 26px;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 26px;
|
||||
list-style: none;
|
||||
padding: 2px 10px;
|
||||
cursor: default;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.x-spreadsheet-item.disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.x-spreadsheet-item:hover,
|
||||
.x-spreadsheet-item.active {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.x-spreadsheet-item.divider {
|
||||
height: 0;
|
||||
padding: 0;
|
||||
margin: 5px 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.x-spreadsheet-item .label {
|
||||
float: right;
|
||||
opacity: 0.65;
|
||||
font-size: 1em;
|
||||
}
|
||||
.x-spreadsheet-item.state,
|
||||
.x-spreadsheet-header.state {
|
||||
padding-left: 35px!important;
|
||||
position: relative;
|
||||
}
|
||||
.x-spreadsheet-item.state:before,
|
||||
.x-spreadsheet-header.state:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
left: 12px;
|
||||
top: calc(50% - 5px);
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-item.state.checked:before,
|
||||
.x-spreadsheet-header.state.checked:before {
|
||||
background: #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-checkbox {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
backface-visibility: hidden;
|
||||
outline: 0;
|
||||
vertical-align: baseline;
|
||||
font-style: normal;
|
||||
font-size: 1rem;
|
||||
line-height: 1em;
|
||||
}
|
||||
.x-spreadsheet-checkbox > input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0!important;
|
||||
outline: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
.x-spreadsheet-suggest,
|
||||
.x-spreadsheet-contextmenu,
|
||||
.x-spreadsheet-sort-filter {
|
||||
position: absolute;
|
||||
box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
|
||||
background: #fff;
|
||||
z-index: 100;
|
||||
width: 260px;
|
||||
pointer-events: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
.x-spreadsheet-suggest {
|
||||
width: 200px;
|
||||
}
|
||||
.x-spreadsheet-filter {
|
||||
border: 1px solid #e9e9e9;
|
||||
font-size: 12px;
|
||||
margin: 10px;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-header {
|
||||
padding: 0.5em 0.75em;
|
||||
background: #f8f8f9;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-body {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.x-spreadsheet-sort-filter .x-spreadsheet-buttons {
|
||||
margin: 10px;
|
||||
}
|
||||
.x-spreadsheet-bottombar {
|
||||
height: 40px;
|
||||
padding: 0 30px;
|
||||
text-align: left;
|
||||
background: #f5f6f7;
|
||||
display: flex;
|
||||
}
|
||||
.x-spreadsheet-bottombar {
|
||||
position: relative;
|
||||
border-top: 1px solid #e0e2e4;
|
||||
}
|
||||
.x-spreadsheet-bottombar .x-spreadsheet-menu > li {
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #e8eaed;
|
||||
}
|
||||
.x-spreadsheet-menu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
.x-spreadsheet-menu > li {
|
||||
float: left;
|
||||
line-height: 1.25em;
|
||||
padding: 0.785em 1em;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
color: #80868b;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-weight: bold;
|
||||
}
|
||||
.x-spreadsheet-menu > li.active {
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
.x-spreadsheet-menu > li .x-spreadsheet-dropdown {
|
||||
display: inline-block;
|
||||
}
|
||||
.x-spreadsheet-print {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.x-spreadsheet-print-bar {
|
||||
background: #424242;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
padding: 0 30px;
|
||||
}
|
||||
.x-spreadsheet-print-bar .-title {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
float: left;
|
||||
}
|
||||
.x-spreadsheet-print-bar .-right {
|
||||
float: right;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.x-spreadsheet-print-content {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
flex-direction: row;
|
||||
background: #d0d0d0;
|
||||
height: calc(100% - 60px);
|
||||
}
|
||||
.x-spreadsheet-print-content .-sider {
|
||||
flex: 0 0 300px;
|
||||
width: 300px;
|
||||
border-left: 2px solid #ccc;
|
||||
background: #fff;
|
||||
}
|
||||
.x-spreadsheet-print-content .-content {
|
||||
flex: auto;
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
.x-spreadsheet-canvas-card-wraper {
|
||||
margin: 40px 20px;
|
||||
}
|
||||
.x-spreadsheet-canvas-card {
|
||||
background: #fff;
|
||||
margin: auto;
|
||||
page-break-before: auto;
|
||||
page-break-after: always;
|
||||
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 3px rgba(0, 0, 0, 0.12), 0 4px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.x-spreadsheet-calendar {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
background: #ffffff;
|
||||
user-select: none;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header {
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
float: left;
|
||||
background: #f9fafb;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-left {
|
||||
padding-left: 5px;
|
||||
float: left;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right {
|
||||
float: right;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right a {
|
||||
padding: 3px 0;
|
||||
margin-right: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover {
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body th,
|
||||
.x-spreadsheet-calendar .calendar-body td {
|
||||
width: 14.28571429%;
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell:hover {
|
||||
background: #ecf6fd;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.active,
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.active:hover {
|
||||
background: #ecf6fd;
|
||||
color: #2185D0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.x-spreadsheet-datepicker {
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(100% + 5px);
|
||||
z-index: 10;
|
||||
width: auto;
|
||||
}
|
||||
.x-spreadsheet-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.x-spreadsheet-buttons .x-spreadsheet-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.x-spreadsheet-button {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
line-height: 1em;
|
||||
min-height: 1em;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
padding: 0.75em 1em;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
background: #E0E1E2;
|
||||
text-decoration: none;
|
||||
font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif;
|
||||
outline: none;
|
||||
vertical-align: baseline;
|
||||
zoom: 1;
|
||||
user-select: none;
|
||||
transition: all 0.1s linear;
|
||||
}
|
||||
.x-spreadsheet-button.active,
|
||||
.x-spreadsheet-button:hover {
|
||||
background-color: #C0C1C2;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.x-spreadsheet-button.primary {
|
||||
color: #fff;
|
||||
background-color: #2185D0;
|
||||
}
|
||||
.x-spreadsheet-button.primary:hover,
|
||||
.x-spreadsheet-button.primary.active {
|
||||
color: #fff;
|
||||
background-color: #1678c2;
|
||||
}
|
||||
.x-spreadsheet-form-input {
|
||||
font-size: 1em;
|
||||
position: relative;
|
||||
font-weight: 400;
|
||||
display: inline-flex;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.x-spreadsheet-form-input input {
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
flex: 1 0 auto;
|
||||
outline: 0;
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||
text-align: left;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
padding: 0 8px;
|
||||
background: #fff;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 3px;
|
||||
transition: box-shadow 0.1s ease, border-color 0.1s ease;
|
||||
box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
|
||||
}
|
||||
.x-spreadsheet-form-input input:focus {
|
||||
border-color: #4b89ff;
|
||||
box-shadow: inset 0 1px 2px rgba(75, 137, 255, 0.2);
|
||||
}
|
||||
.x-spreadsheet-form-select {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
user-select: none;
|
||||
box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
|
||||
}
|
||||
.x-spreadsheet-form-select .input-text {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 60px;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.x-spreadsheet-form-fields {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.x-spreadsheet-form-fields .x-spreadsheet-form-field {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.x-spreadsheet-form-fields .x-spreadsheet-form-field .label {
|
||||
display: inline-block;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
.x-spreadsheet-form-field {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.x-spreadsheet-form-field:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.x-spreadsheet-form-field.error .x-spreadsheet-form-select,
|
||||
.x-spreadsheet-form-field.error input {
|
||||
border-color: #f04134;
|
||||
}
|
||||
.x-spreadsheet-form-field .tip {
|
||||
color: #f04134;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.x-spreadsheet-dimmer {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
opacity: 0;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-duration: 0.5s;
|
||||
animation-duration: 0.5s;
|
||||
transition: background-color 0.5s linear;
|
||||
user-select: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
.x-spreadsheet-dimmer.active {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
form fieldset {
|
||||
border: none;
|
||||
}
|
||||
form fieldset label {
|
||||
display: block;
|
||||
margin-bottom: 0.5em;
|
||||
font-size: 1em;
|
||||
color: #666;
|
||||
}
|
||||
form fieldset select {
|
||||
font-size: 1.1em;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: none;
|
||||
border-bottom: 2px solid #ddd;
|
||||
padding: 0.5em 0.85em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-modal,
|
||||
.x-spreadsheet-toast {
|
||||
font-size: 13px;
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
text-align: left;
|
||||
line-height: 1.25em;
|
||||
min-width: 360px;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 8px;
|
||||
}
|
||||
.x-spreadsheet-toast {
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.x-spreadsheet-modal-header,
|
||||
.x-spreadsheet-toast-header {
|
||||
font-weight: 600;
|
||||
background-clip: padding-box;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.x-spreadsheet-toast-header {
|
||||
color: #F2711C;
|
||||
}
|
||||
.x-spreadsheet-modal-header {
|
||||
border-bottom: 1px solid #e0e2e4;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
font-size: 1.0785em;
|
||||
}
|
||||
.x-spreadsheet-modal-header,
|
||||
.x-spreadsheet-modal-content,
|
||||
.x-spreadsheet-toast-header,
|
||||
.x-spreadsheet-toast-content {
|
||||
padding: 0.75em 1em;
|
||||
}
|
||||
|
||||
.x-spreadsheet-menu li:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vue-office-excel {
|
||||
height: 100%;
|
||||
}
|
17
core/packages/js-excel/index.d.ts
vendored
17
core/packages/js-excel/index.d.ts
vendored
@ -1,17 +0,0 @@
|
||||
export interface Options {
|
||||
minColLength?: number;
|
||||
minRowLength?: number;
|
||||
showContextmenu?: boolean;
|
||||
}
|
||||
|
||||
export interface JsExcelPreview {
|
||||
preview: (src: string | ArrayBuffer | Blob) => Promise<any>;
|
||||
save: (fileName?: string) => void;
|
||||
setOptions: (options: Options) => void;
|
||||
setRequestOptions: (requestOptions?: any) => void;
|
||||
destroy: ()=> void;
|
||||
}
|
||||
declare const jsPreviewExcel: {
|
||||
init: (container: HTMLElement, options?: Options, requestOptions?: any) => JsExcelPreview;
|
||||
};
|
||||
export default jsPreviewExcel;
|
@ -1,5 +0,0 @@
|
||||
import {init} from './src/main';
|
||||
|
||||
export default {
|
||||
init
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "@js-preview/excel",
|
||||
"type" :"module",
|
||||
"version": "1.7.3",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copyCss": "cp ./index.css ./lib/index.css",
|
||||
"copy": "npm run copyCss && npm run copyType && npm run copyReadme",
|
||||
"build": "npm run clean && rollup --config rollup.config.js && npm run copy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import { getBabelOutputPlugin } from '@rollup/plugin-babel';
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import terser from '@rollup/plugin-terser';
|
||||
|
||||
export default {
|
||||
input: 'index.js',
|
||||
output:[
|
||||
{
|
||||
file: 'lib/index.js',
|
||||
name: 'jsPreviewExcel',
|
||||
format: 'es',
|
||||
plugins: [getBabelOutputPlugin({ presets: ['@babel/preset-env'] })]
|
||||
},
|
||||
{
|
||||
file: 'lib/index.umd.js',
|
||||
name: 'jsPreviewExcel',
|
||||
format: 'umd'
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
commonjs(),
|
||||
postcss(),
|
||||
terser()
|
||||
]
|
||||
};
|
@ -1,180 +0,0 @@
|
||||
import Spreadsheet from 'x-data-spreadsheet';
|
||||
import {getData, readExcelData, transferExcelToSpreadSheet} from '../../vue-excel/src/excel';
|
||||
import {renderImage, clearCache} from '../../vue-excel/src/media';
|
||||
import {readOnlyInput} from '../../vue-excel/src/hack';
|
||||
import {debounce} from 'lodash';
|
||||
import {download as downloadFile} from '../../../utils/url.js';
|
||||
const defaultOptions = {
|
||||
xls: false,
|
||||
minColLength: 20
|
||||
};
|
||||
class JsExcelPreview {
|
||||
container = null;
|
||||
wrapper = null;
|
||||
wrapperMain = null;
|
||||
options = {};
|
||||
requestOptions = {};
|
||||
mediasSource = [];
|
||||
workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
sheetIndex = 1;
|
||||
ctx = null;
|
||||
xs = null;
|
||||
offset = null;
|
||||
observer = null;
|
||||
fileData = null;
|
||||
|
||||
constructor(container, options={}, requestOptions={}) {
|
||||
this.container = container;
|
||||
this.options = {...defaultOptions, ...options};
|
||||
this.requestOptions = requestOptions;
|
||||
this.createWrapper();
|
||||
this.initSpreadsheet();
|
||||
this.hack();
|
||||
}
|
||||
createWrapper(){
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.className = 'vue-office-excel';
|
||||
this.wrapperMain = document.createElement('div');
|
||||
this.wrapperMain.className = 'vue-office-excel-main';
|
||||
this.wrapper.appendChild(this.wrapperMain);
|
||||
this.container.appendChild(this.wrapper);
|
||||
}
|
||||
initSpreadsheet(){
|
||||
this.xs = new Spreadsheet(this.wrapperMain, {
|
||||
mode: 'read',
|
||||
showToolbar: false,
|
||||
showContextmenu: this.options.showContextmenu || false,
|
||||
view: {
|
||||
height: () => this.wrapper && this.wrapper.clientHeight || 300,
|
||||
width: () => this.wrapper && this.wrapper.clientWidth || 1200,
|
||||
},
|
||||
row: {
|
||||
height: 24,
|
||||
len: 100
|
||||
},
|
||||
col: {
|
||||
len: 26,
|
||||
width: 80,
|
||||
indexWidth: 60,
|
||||
minWidth: 60,
|
||||
},
|
||||
autoFocus: false
|
||||
}).loadData({});
|
||||
|
||||
let that = this;
|
||||
|
||||
let swapFunc = this.xs.bottombar.swapFunc;
|
||||
this.xs.bottombar.swapFunc = function (index) {
|
||||
swapFunc.call(that.xs.bottombar, index);
|
||||
that.sheetIndex = index;
|
||||
setTimeout(()=>{
|
||||
that.xs.reRender();
|
||||
renderImage(that.ctx, that.mediasSource,that.workbookDataSource._worksheets[that.sheetIndex], that.offset);
|
||||
});
|
||||
|
||||
};
|
||||
let clear = this.xs.sheet.editor.clear;
|
||||
this.xs.sheet.editor.clear = function (...args){
|
||||
clear.apply(that.xs.sheet.editor, args);
|
||||
setTimeout(()=>{
|
||||
renderImage(that.ctx, that.mediasSource,that.workbookDataSource._worksheets[that.sheetIndex], that.offset);
|
||||
});
|
||||
};
|
||||
let setOffset = this.xs.sheet.editor.setOffset;
|
||||
this.xs.sheet.editor.setOffset = function (...args){
|
||||
setOffset.apply(that.xs.sheet.editor, args);
|
||||
that.offset = args[0];
|
||||
renderImage(that.ctx, that.mediasSource,that.workbookDataSource._worksheets[that.sheetIndex], that.offset);
|
||||
};
|
||||
const canvas = this.wrapperMain.querySelector('canvas');
|
||||
this.ctx = canvas.getContext('2d');
|
||||
}
|
||||
renderExcel(buffer){
|
||||
this.fileData = buffer;
|
||||
return readExcelData(buffer, this.options.xls).then(workbook => {
|
||||
if (!workbook._worksheets || workbook._worksheets.length === 0) {
|
||||
throw new Error('未获取到数据,可能文件格式不正确或文件已损坏');
|
||||
}
|
||||
if(this.options.beforeTransformData && typeof this.options.beforeTransformData === 'function' ){
|
||||
workbook = this.options.beforeTransformData(workbook);
|
||||
}
|
||||
let {workbookData, medias, workbookSource} = transferExcelToSpreadSheet(workbook, this.options);
|
||||
if(this.options.transformData && typeof this.options.transformData === 'function' ){
|
||||
workbookData = this.options.transformData(workbookData);
|
||||
}
|
||||
this.mediasSource = medias;
|
||||
this.workbookDataSource = workbookSource;
|
||||
this.offset = null;
|
||||
this.sheetIndex = 0;
|
||||
clearCache();
|
||||
this.xs.loadData(workbookData);
|
||||
renderImage(this.ctx, this.mediasSource,this.workbookDataSource._worksheets[this.sheetIndex], this.offset);
|
||||
|
||||
}).catch(e => {
|
||||
this.mediasSource = [];
|
||||
this.workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
clearCache();
|
||||
this.xs.loadData({});
|
||||
return Promise.reject(e);
|
||||
});
|
||||
}
|
||||
hack(){
|
||||
const observerCallback = debounce(readOnlyInput, 200).bind(this, this.wrapperMain);
|
||||
this.observer = new MutationObserver(observerCallback);
|
||||
const observerConfig = { attributes: true, childList: true, subtree: true };
|
||||
this.observer.observe(this.wrapperMain, observerConfig);
|
||||
observerCallback(this.wrapperMain);
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
this.options = options;
|
||||
}
|
||||
setRequestOptions(requestOptions) {
|
||||
this.requestOptions = requestOptions;
|
||||
}
|
||||
preview(src){
|
||||
return new Promise(((resolve, reject) => {
|
||||
getData(src, this.requestOptions).then((res)=>{
|
||||
this.renderExcel(res).then(resolve).catch(e =>{
|
||||
this.mediasSource = [];
|
||||
this.workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
this.xs.loadData({});
|
||||
reject(e);
|
||||
});
|
||||
}).catch(e => {
|
||||
this.mediasSource = [];
|
||||
this.workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
this.xs.loadData({});
|
||||
reject(e);
|
||||
});
|
||||
}));
|
||||
}
|
||||
save(fileName){
|
||||
downloadFile(fileName || `js-preview-excel-${new Date().getTime()}.xlsx`,this.fileData);
|
||||
}
|
||||
destroy(){
|
||||
this.observer.disconnect();
|
||||
this.container.removeChild(this.wrapper);
|
||||
this.container = null;
|
||||
this.wrapper = null;
|
||||
this.wrapperMain = null;
|
||||
this.ctx = null;
|
||||
this.xs = null;
|
||||
this.observer = null;
|
||||
this.options = null;
|
||||
this.requestOptions = null;
|
||||
this.mediasSource = null;
|
||||
this.workbookDataSource = null;
|
||||
}
|
||||
}
|
||||
export function init(container, options, requestOptions){
|
||||
return new JsExcelPreview(container, options, requestOptions);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"edge": "17",
|
||||
"firefox": "60",
|
||||
"chrome": "67",
|
||||
"safari": "11.1",
|
||||
"ios": "8"
|
||||
},
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.32.0"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
27
core/packages/js-pdf/index.d.ts
vendored
27
core/packages/js-pdf/index.d.ts
vendored
@ -1,27 +0,0 @@
|
||||
export interface Options {
|
||||
staticFileUrl?: string;
|
||||
width?: number;
|
||||
data?: BinaryData;
|
||||
httpHeaders?: Object;
|
||||
withCredentials?: boolean;
|
||||
password?: string;
|
||||
length?: number;
|
||||
docBaseUrl?: string;
|
||||
cMapUrl?: string;
|
||||
cMapPacked?: boolean;
|
||||
CMapReaderFactory?: Object;
|
||||
useSystemFonts?: boolean;
|
||||
}
|
||||
|
||||
export interface JsPdfPreview {
|
||||
preview: (src: string | ArrayBuffer | Blob) => Promise<any>;
|
||||
rerender: () => Promise<any>;
|
||||
save: (fileName?: string) => void;
|
||||
setOptions: (options: Options) => void;
|
||||
setRequestOptions: (requestOptions?: any) => void;
|
||||
destroy: ()=> void;
|
||||
}
|
||||
declare const jsPreviewPdf: {
|
||||
init: (container: HTMLElement, options?: Options, requestOptions?: any) => JsPdfPreview;
|
||||
};
|
||||
export default jsPreviewPdf;
|
@ -1,5 +0,0 @@
|
||||
import {init} from './src/main';
|
||||
|
||||
export default {
|
||||
init
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "@js-preview/pdf",
|
||||
"type" :"module",
|
||||
"version": "1.6.5",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copy": "npm run copyType && npm run copyReadme",
|
||||
"build": "npm run clean && rollup --config rollup.config.js && npm run copy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import {getBabelOutputPlugin} from '@rollup/plugin-babel';
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import terser from '@rollup/plugin-terser';
|
||||
|
||||
export default {
|
||||
input: 'index.js',
|
||||
output:[
|
||||
{
|
||||
file: 'lib/index.js',
|
||||
name: 'jsPreviewPdf',
|
||||
format: 'es',
|
||||
plugins: [getBabelOutputPlugin({ presets: ['@babel/preset-env'] })]
|
||||
},
|
||||
{
|
||||
file: 'lib/index.umd.js',
|
||||
name: 'jsPreviewPdf',
|
||||
format: 'umd'
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
commonjs(),
|
||||
terser()
|
||||
]
|
||||
};
|
@ -1,215 +0,0 @@
|
||||
import {workerStr} from './worker.js';
|
||||
import {pdfLibJsStr} from './pdf.js';
|
||||
import {download as downloadFile, getUrl, loadScript} from '../../../utils/url';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
const pdfJsLibSrc = `data:text/javascript;base64,${pdfLibJsStr}`;
|
||||
const PdfJsWorkerSrc = `data:text/javascript;base64,${workerStr}`;
|
||||
let pdfJsLibLoaded = false;
|
||||
let workerLoaded = false;
|
||||
class JsPdfPreview{
|
||||
container = null;
|
||||
wrapper = null;
|
||||
wrapperMain = null;
|
||||
options = {};
|
||||
requestOptions = {};
|
||||
pdfDocument = null;
|
||||
loopCheckTimer = null;
|
||||
constructor(container, options={}, requestOptions={}) {
|
||||
this.container = container;
|
||||
this.options = {
|
||||
staticFileUrl: 'https://unpkg.com/pdfjs-dist@3.1.81/',
|
||||
...options
|
||||
};
|
||||
this.requestOptions = requestOptions;
|
||||
this.createWrapper();
|
||||
}
|
||||
createWrapper(){
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.className = 'vue-office-pdf';
|
||||
this.wrapper.setAttribute('style', 'text-align: center;overflow-y: auto;');
|
||||
this.container.appendChild(this.wrapper);
|
||||
}
|
||||
createWrapperMain(){
|
||||
this.wrapperMain = document.createElement('div');
|
||||
this.wrapperMain.className = 'vue-office-pdf-wrapper';
|
||||
this.wrapperMain.setAttribute('style', 'background: gray; padding: 30px 0;position: relative;');
|
||||
this.wrapper.appendChild(this.wrapperMain);
|
||||
}
|
||||
createCanvas(num){
|
||||
let existCanvas = this.wrapperMain.querySelectorAll('canvas');
|
||||
if(existCanvas[num -1]){
|
||||
return [existCanvas[num -1], existCanvas[num -1].getContext('2d')];
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.setAttribute('style', 'width:100%');
|
||||
this.wrapperMain.appendChild(canvas);
|
||||
return [canvas, canvas.getContext('2d')];
|
||||
}
|
||||
installPdfScript() {
|
||||
return loadScript(pdfJsLibSrc).then(() => {
|
||||
if (window.pdfjsLib && !workerLoaded) {
|
||||
workerLoaded = true;
|
||||
window.pdfjsLib.GlobalWorkerOptions.workerSrc = PdfJsWorkerSrc;
|
||||
} else {
|
||||
return Promise.reject('window.pdfjsLib未找到');
|
||||
}
|
||||
});
|
||||
}
|
||||
waitPdfjsLoad(){
|
||||
return new Promise((resolve)=>{
|
||||
const loopCheck = () =>{
|
||||
if(window.pdfjsLib) {
|
||||
resolve();
|
||||
}else{
|
||||
this.loopCheckTimer = setTimeout(loopCheck, 10);
|
||||
}
|
||||
};
|
||||
loopCheck();
|
||||
});
|
||||
}
|
||||
checkPdfLib() {
|
||||
if (window.pdfjsLib) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if(!pdfJsLibLoaded){
|
||||
pdfJsLibLoaded = true;
|
||||
return this.installPdfScript();
|
||||
}else{
|
||||
return this.waitPdfjsLoad();
|
||||
}
|
||||
}
|
||||
getDocument(src){
|
||||
const loadingTask = window.pdfjsLib.getDocument({
|
||||
url: getUrl(src),
|
||||
httpHeaders: this.requestOptions && this.requestOptions.headers,
|
||||
withCredentials: this.requestOptions && this.requestOptions.withCredentials,
|
||||
cMapUrl: `${this.options.staticFileUrl.endsWith('/') ? this.options.staticFileUrl : this.options.staticFileUrl + '/'}cmaps/`,
|
||||
cMapPacked: true,
|
||||
enableXfa: true,
|
||||
...omit(this.options, ['width', 'staticFileUrl'])
|
||||
});
|
||||
return loadingTask.promise;
|
||||
}
|
||||
renderSinglePage(num){
|
||||
return this.pdfDocument.getPage(num).then((pdfPage) => {
|
||||
const viewport = pdfPage.getViewport({scale: 2});
|
||||
const outputScale = window.devicePixelRatio > 2 ? 1.5 : 2;
|
||||
let [canvas, ctx] = this.createCanvas(num);
|
||||
|
||||
canvas.width = Math.floor(viewport.width * outputScale);
|
||||
canvas.height = Math.floor(viewport.height * outputScale);
|
||||
|
||||
let domWidth = Math.floor(viewport.width);
|
||||
let domHeight = Math.floor(viewport.height);
|
||||
if (this.options.width) {
|
||||
let scale = this.options.width / domWidth;
|
||||
domWidth = Math.floor(this.options.width);
|
||||
domHeight = Math.floor(domHeight * scale);
|
||||
}
|
||||
let wrapperWidth = this.wrapperMain.getBoundingClientRect().width - 20;
|
||||
if(domWidth > wrapperWidth){
|
||||
let scale = wrapperWidth / domWidth;
|
||||
domWidth = Math.floor(wrapperWidth);
|
||||
domHeight = Math.floor(domHeight * scale);
|
||||
}
|
||||
|
||||
canvas.style.width = domWidth + 'px';
|
||||
canvas.style.height = domHeight + 'px';
|
||||
|
||||
const transform = outputScale !== 1
|
||||
? [outputScale, 0, 0, outputScale, 0, 0]
|
||||
: null;
|
||||
|
||||
const renderTask = pdfPage.render({
|
||||
canvasContext: ctx,
|
||||
transform,
|
||||
viewport
|
||||
});
|
||||
return renderTask.promise.then(() => {
|
||||
if (this.pdfDocument.numPages > num) {
|
||||
return this.renderSinglePage(num + 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
renderPage(){
|
||||
if(!this.wrapperMain){
|
||||
this.createWrapperMain();
|
||||
}else{
|
||||
let canvas = this.wrapperMain.querySelectorAll('canvas');
|
||||
if(canvas.length > this.pdfDocument.numPages){
|
||||
for(let i = canvas.length-1; i >= this.pdfDocument.numPages; i--){
|
||||
this.wrapperMain.removeChild(canvas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.renderSinglePage(1);
|
||||
}
|
||||
clearAllCanvas(){
|
||||
if(this.wrapperMain){
|
||||
this.wrapper.removeChild(this.wrapperMain);
|
||||
this.wrapperMain = null;
|
||||
}
|
||||
}
|
||||
setOptions(options) {
|
||||
this.options = options;
|
||||
}
|
||||
setRequestOptions(requestOptions) {
|
||||
this.requestOptions = requestOptions;
|
||||
}
|
||||
preview(src){
|
||||
return new Promise(((resolve, reject) => {
|
||||
if(!src){
|
||||
this.clearAllCanvas();
|
||||
reject(new Error('预览地址不能为空'));
|
||||
return;
|
||||
}
|
||||
this.checkPdfLib().then(_=>{
|
||||
this.getDocument(src).then(pdf=>{
|
||||
this.pdfDocument && this.pdfDocument.destroy();
|
||||
this.pdfDocument = pdf;
|
||||
this.renderPage().then(_=>{
|
||||
resolve();
|
||||
}).catch(e=>{
|
||||
this.clearAllCanvas();
|
||||
reject(e);
|
||||
});
|
||||
}).catch(e=>{
|
||||
this.clearAllCanvas();
|
||||
reject(e);
|
||||
});
|
||||
}).catch(e=>{
|
||||
this.clearAllCanvas();
|
||||
reject(e);
|
||||
});
|
||||
}));
|
||||
}
|
||||
rerender(){
|
||||
return this.renderPage().then(_=>{
|
||||
return Promise.resolve();
|
||||
}).catch(e=>{
|
||||
this.clearAllCanvas();
|
||||
return Promise.reject(e);
|
||||
});
|
||||
}
|
||||
save(fileName){
|
||||
this.pdfDocument && this.pdfDocument._transport && this.pdfDocument._transport.getData().then(fileData=>{
|
||||
downloadFile(fileName || `js-preview-pdf-${new Date().getTime()}.pdf`,fileData.buffer);
|
||||
});
|
||||
}
|
||||
destroy(){
|
||||
this.container.removeChild(this.wrapper);
|
||||
this.container = null;
|
||||
this.wrapper = null;
|
||||
this.wrapperMain = null;
|
||||
this.options = {};
|
||||
this.requestOptions = {};
|
||||
this.pdfDocument && this.pdfDocument.destroy();
|
||||
this.pdfDocument = null;
|
||||
this.loopCheckTimer && clearTimeout(this.loopCheckTimer);
|
||||
}
|
||||
}
|
||||
export function init(container, options, requestOptions){
|
||||
return new JsPdfPreview(container, options, requestOptions);
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
7
core/packages/vue-docx/index.d.ts
vendored
7
core/packages/vue-docx/index.d.ts
vendored
@ -1,7 +0,0 @@
|
||||
declare const VueOfficeDocx: {
|
||||
install?: (vue: any) => void;
|
||||
src: string|ArrayBuffer|Blob;
|
||||
requestOptions?: any;
|
||||
options?: any
|
||||
};
|
||||
export default VueOfficeDocx;
|
@ -1,8 +0,0 @@
|
||||
import hack from './src/hack';
|
||||
import VueOfficeDocx from './src/main.vue';
|
||||
|
||||
VueOfficeDocx.install = function (Vue) {
|
||||
Vue.component(VueOfficeDocx.name, VueOfficeDocx);
|
||||
};
|
||||
|
||||
export default VueOfficeDocx;
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"name": "@vue-office/docx",
|
||||
"version": "1.6.0",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyFile2": "cp lib/v2/vue-office-docx.umd.js lib/v2/index.js && cp lib/v2/style.css lib/v2/index.css",
|
||||
"copyFile3": "cp lib/v3/vue-office-docx.umd.js lib/v3/index.js && cp lib/v3/style.css lib/v3/index.css",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copyScripts": "mkdir lib/script/ && cp ../../script/postinstall.js lib/script/postinstall.js && cp ../../script/switch-cli.js lib/script/switch-cli.js && cp ../../script/utils.js lib/script/utils.js",
|
||||
"build:2": "npx vue-demi-switch 2 vue2 && vite build && npm run copyFile2",
|
||||
"build:3": "npx vue-demi-switch 3 vue3 && vite build && npm run copyFile3",
|
||||
"build": "npm run clean && npm run build:2 && npm run build:3 && npm run copyScripts && npm run copyReadme && npm run copyType",
|
||||
"postinstall": "node lib/script/postinstall.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.7.1",
|
||||
"vue": "^2.0.0 || >=3.0.0",
|
||||
"vue-demi": "^0.14.6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15"
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*eslint-disable*/
|
||||
import {renderAsync} from 'docx-preview';
|
||||
|
||||
const defaultOptions = {
|
||||
ignoreLastRenderedPageBreak: false
|
||||
};
|
||||
|
||||
function getData(src, options = {}) {
|
||||
if (typeof src === 'string') {
|
||||
return fetchDocx(src, options);
|
||||
}
|
||||
return Promise.resolve(src);
|
||||
}
|
||||
|
||||
function fetchDocx(src, options) {
|
||||
return fetch(src, options).then(res => {
|
||||
if (res.status !== 200) {
|
||||
return Promise.reject(res);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
async function getBlob(data){
|
||||
let blob;
|
||||
if (data instanceof Blob) {
|
||||
blob = data;
|
||||
} else if (data instanceof Response) {
|
||||
blob = await data.blob();
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
blob = new Blob([data]);
|
||||
}
|
||||
return blob
|
||||
}
|
||||
|
||||
function render(data, container, options = {}) {
|
||||
if (!data) {
|
||||
container.innerHTML = '';
|
||||
return Promise.resolve();
|
||||
}
|
||||
let blob;
|
||||
if (data instanceof Blob) {
|
||||
blob = data;
|
||||
} else if (data instanceof Response) {
|
||||
blob = data.blob();
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
blob = new Blob([data]);
|
||||
}
|
||||
return renderAsync(blob, container, container, {...defaultOptions, ...options});
|
||||
}
|
||||
|
||||
export default {
|
||||
getData,
|
||||
render,
|
||||
getBlob
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
//乾坤下不能渲染问题兼容
|
||||
if(typeof window.setImmediate === 'undefined' ){
|
||||
window.setImmediate = function (func, ...args){
|
||||
setTimeout(()=>func(args));
|
||||
};
|
||||
}
|
||||
|
||||
export default {}
|
@ -1,95 +0,0 @@
|
||||
<script>
|
||||
import {defineComponent, ref, onMounted, watch} from 'vue-demi';
|
||||
import docx from './docx';
|
||||
import {download as downloadFile} from '../../../utils/url';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VueOfficeDocx',
|
||||
props: {
|
||||
src: [String, ArrayBuffer, Blob],
|
||||
requestOptions: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
options:{
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
emits: ['rendered', 'error'],
|
||||
setup(props, {emit}) {
|
||||
const rootRef = ref(null);
|
||||
let fileData = null;
|
||||
function init() {
|
||||
let container = rootRef.value;
|
||||
docx.getData(props.src, props.requestOptions).then(async res => {
|
||||
fileData = await docx.getBlob(res);
|
||||
docx.render(fileData, container, props.options).then(() => {
|
||||
emit('rendered');
|
||||
}).catch(e => {
|
||||
docx.render('', container, props.options);
|
||||
emit('error', e);
|
||||
});
|
||||
}).catch(e => {
|
||||
docx.render('', container, props.options);
|
||||
emit('error', e);
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.src) {
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.src, () => {
|
||||
if (props.src) {
|
||||
init();
|
||||
} else {
|
||||
docx.render('', rootRef.value, props.options).then(() => {
|
||||
emit('rendered');
|
||||
});
|
||||
}
|
||||
});
|
||||
function save(fileName){
|
||||
downloadFile(fileName || `vue-office-docx-${new Date().getTime()}.docx`,fileData);
|
||||
}
|
||||
return {
|
||||
rootRef,
|
||||
save
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vue-office-docx">
|
||||
<div class="vue-office-docx-main" ref="rootRef"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.vue-office-docx {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.docx-wrapper {
|
||||
> section.docx {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.vue-office-docx {
|
||||
.docx-wrapper {
|
||||
padding: 10px;
|
||||
|
||||
> section.docx {
|
||||
padding: 10px !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -1,37 +0,0 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { createVuePlugin } from 'vite-plugin-vue2';
|
||||
import vue3 from '@vitejs/plugin-vue';
|
||||
import * as compiler from '@vue/compiler-sfc';
|
||||
import { isVue2 } from 'vue-demi';
|
||||
const { resolve } = require('path');
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
isVue2
|
||||
? createVuePlugin()
|
||||
: vue3({
|
||||
compiler: compiler
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
target: 'es2015',
|
||||
outDir: 'lib/v' + (isVue2 ? '2' : '3'),
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.js'), //指定组件编译入口文件
|
||||
name: 'vue-office-docx',
|
||||
fileName: 'vue-office-docx',
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: ['vue-demi']
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['vue-demi','vue'],
|
||||
output: {
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
'vue-demi': 'VueDemi'
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
12
core/packages/vue-excel/index.d.ts
vendored
12
core/packages/vue-excel/index.d.ts
vendored
@ -1,12 +0,0 @@
|
||||
export interface Options {
|
||||
minColLength?: number;
|
||||
minRowLength?: number;
|
||||
showContextmenu?: boolean;
|
||||
}
|
||||
declare const VueOfficeExcel: {
|
||||
install?: (vue: any) => void;
|
||||
src: string|ArrayBuffer|Blob;
|
||||
requestOptions?: any;
|
||||
options?: Options;
|
||||
};
|
||||
export default VueOfficeExcel;
|
@ -1,7 +0,0 @@
|
||||
import VueOfficeExcel from './src/main.vue';
|
||||
|
||||
VueOfficeExcel.install = function (Vue) {
|
||||
Vue.component(VueOfficeExcel.name, VueOfficeExcel);
|
||||
};
|
||||
|
||||
export default VueOfficeExcel;
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"name": "@vue-office/excel",
|
||||
"version": "1.7.3",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyFile2": "cp lib/v2/vue-office-excel.umd.js lib/v2/index.js && cp src/index.css lib/v2/index.css",
|
||||
"copyFile3": "cp lib/v3/vue-office-excel.umd.js lib/v3/index.js && cp src/index.css lib/v3/index.css",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copyScripts": "mkdir lib/script/ && cp ../../script/postinstall.js lib/script/postinstall.js && cp ../../script/switch-cli.js lib/script/switch-cli.js && cp ../../script/utils.js lib/script/utils.js",
|
||||
"build:2": "npx vue-demi-switch 2 vue2 && vite build && npm run copyFile2",
|
||||
"build:3": "npx vue-demi-switch 3 vue3 && vite build && npm run copyFile3",
|
||||
"build": "npm run clean && npm run build:2 && npm run build:3 && npm run copyScripts && npm run copyReadme && npm run copyType",
|
||||
"postinstall": "node lib/script/postinstall.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.7.1",
|
||||
"vue": "^2.0.0 || >=3.0.0",
|
||||
"vue-demi": "^0.14.6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15"
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
function HexToRgb (str) {
|
||||
str = str.replace('#', '');
|
||||
var hxs = str.match(/../g);
|
||||
for (var i = 0; i < 3; i++) hxs[i] = parseInt(hxs[i], 16);
|
||||
return hxs;
|
||||
}
|
||||
|
||||
function RgbToHex (a, b, c) {
|
||||
var hexs = [a.toString(16), b.toString(16), c.toString(16)];
|
||||
for (var i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = '0' + hexs[i];
|
||||
return '#' + hexs.join('');
|
||||
}
|
||||
|
||||
|
||||
export function getDarkColor(color, level) {
|
||||
var rgbc = HexToRgb(color);
|
||||
for (var i = 0; i < 3; i++) rgbc[i] = Math.floor(rgbc[i] * (1 - level));
|
||||
return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
|
||||
}
|
||||
export function getLightColor(color, level) {
|
||||
var rgbc = HexToRgb(color);
|
||||
for (var i = 0; i < 3; i++) rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i]);
|
||||
return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
|
||||
}
|
@ -1,430 +0,0 @@
|
||||
import * as Excel from 'exceljs/dist/exceljs';
|
||||
import {getUrl} from '../../../utils/url';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import {cloneDeep, get, find} from 'lodash';
|
||||
import {getDarkColor, getLightColor} from './color';
|
||||
import dayjs from 'dayjs';
|
||||
import {read, write} from 'xlsx';
|
||||
|
||||
const themeColor = [
|
||||
'#FFFFFF',
|
||||
'#000000',
|
||||
'#BFBFBF',
|
||||
'#323232',
|
||||
'#4472C4',
|
||||
'#ED7D31',
|
||||
'#A5A5A5',
|
||||
'#FFC000',
|
||||
'#5B9BD5',
|
||||
'#71AD47'
|
||||
];
|
||||
|
||||
const indexedColor = [
|
||||
'#000000',
|
||||
'#FFFFFF',
|
||||
'#FF0000',
|
||||
'#00FF00',
|
||||
'#0000FF',
|
||||
'#FFFF00',
|
||||
'#FF00FF',
|
||||
'#00FFFF',
|
||||
'#000000',
|
||||
'#FFFFFF',
|
||||
'#FF0000',
|
||||
'#00FF00',
|
||||
'#0000FF',
|
||||
'#FFFF00',
|
||||
'#FF00FF',
|
||||
'#00FFFF',
|
||||
'#800000',
|
||||
'#008000',
|
||||
'#000080',
|
||||
'#808000',
|
||||
'#800080',
|
||||
'#008080',
|
||||
'#C0C0C0',
|
||||
'#808080',
|
||||
'#9999FF',
|
||||
'#993366',
|
||||
'#FFFFCC',
|
||||
'#CCFFFF',
|
||||
'#660066',
|
||||
'#FF8080',
|
||||
'#0066CC',
|
||||
'#CCCCFF',
|
||||
'#000080',
|
||||
'#FF00FF',
|
||||
'#FFFF00',
|
||||
'#00FFFF',
|
||||
'#800080',
|
||||
'#800000',
|
||||
'#008080',
|
||||
'#0000FF',
|
||||
'#00CCFF',
|
||||
'#CCFFFF',
|
||||
'#CCFFCC',
|
||||
'#FFFF99',
|
||||
'#99CCFF',
|
||||
'#FF99CC',
|
||||
'#CC99FF',
|
||||
'#FFCC99',
|
||||
'#3366FF',
|
||||
'#33CCCC',
|
||||
'#99CC00',
|
||||
'#FFCC00',
|
||||
'#FF9900',
|
||||
'#FF6600',
|
||||
'#666699',
|
||||
'#969696',
|
||||
'#003366',
|
||||
'#339966',
|
||||
'#003300',
|
||||
'#333300',
|
||||
'#993300',
|
||||
'#993366',
|
||||
'#333399',
|
||||
'#333333',
|
||||
'#FFFFFF'
|
||||
];
|
||||
|
||||
let defaultColWidth = 80;
|
||||
let defaultRowHeight = 24;
|
||||
export function getData(src, options={}) {
|
||||
return requestExcel(getUrl(src), options);
|
||||
}
|
||||
|
||||
function requestExcel(src, options) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(options.method || 'GET', src, true);
|
||||
xhr.responseType = options.responseType || 'arraybuffer';
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(xhr.status);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
reject(xhr.status);
|
||||
};
|
||||
xhr.withCredentials = options.withCredentials || false;
|
||||
if(options.headers) {
|
||||
Object.keys(options.headers).forEach(function(key) {
|
||||
xhr.setRequestHeader(key, options.headers[key]);
|
||||
});
|
||||
}
|
||||
|
||||
xhr.send(options.body);
|
||||
});
|
||||
}
|
||||
|
||||
export function readExcelData(buffer, xls){
|
||||
try {
|
||||
if(xls){
|
||||
const workbook = read(buffer, {type: 'array'});
|
||||
buffer = write(workbook, { bookType: 'xlsx', type: 'array' });
|
||||
}
|
||||
const wb = new Excel.Workbook();
|
||||
return wb.xlsx.load(buffer);
|
||||
|
||||
}catch (e){
|
||||
console.warn(e);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function transferColumns(excelSheet, spreadSheet, options){
|
||||
for(let i = 0;i < (excelSheet.columns || []).length; i++){
|
||||
spreadSheet.cols[i.toString()] = {};
|
||||
if(excelSheet.columns[i].width) {
|
||||
spreadSheet.cols[i.toString()].width = excelSheet.columns[i].width * 6 + (options.widthOffset || 0);
|
||||
} else {
|
||||
spreadSheet.cols[i.toString()].width = defaultColWidth + (options.widthOffset || 0);
|
||||
}
|
||||
}
|
||||
|
||||
spreadSheet.cols.len = Math.max(Object.keys(spreadSheet.cols).length, options.minColLength || 0);
|
||||
}
|
||||
|
||||
function getCellText(cell){
|
||||
//console.log(cell);
|
||||
let {numFmt, value, type} = cell;
|
||||
switch (type){
|
||||
case 2: //数字
|
||||
try {
|
||||
//numFmt:
|
||||
// "0.00%"
|
||||
// "0.00_);(0.00)"
|
||||
// "#,##0.000_);(#,##0.000)" 千分位
|
||||
// "#,##0.000;[Red]#,##0.000"
|
||||
if(cell.style.numFmt){
|
||||
if(cell.style.numFmt.endsWith('%')){
|
||||
let precision = cell.style.numFmt.match(/\.(\d+)%/);
|
||||
if(precision){
|
||||
return (value * 100).toFixed(precision[1].length) + '%';
|
||||
}else {
|
||||
return value * 100 + '%';
|
||||
}
|
||||
}else if(/0(\.0+)?/.test(cell.style.numFmt)){
|
||||
let prefix = '';
|
||||
if(cell.style.numFmt.startsWith('$')){
|
||||
prefix = '$';
|
||||
}else if(cell.style.numFmt.startsWith('"¥')){
|
||||
prefix = '¥';
|
||||
}
|
||||
|
||||
if(value === 0 && cell.style.numFmt.startsWith('_')){
|
||||
return '-';
|
||||
}
|
||||
let precision = cell.style.numFmt.match(/0\.(0+)(_|;|$)/);
|
||||
if(precision){
|
||||
precision = precision[1].length;
|
||||
}else{
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
let result = value.toFixed(precision) + '';
|
||||
if(cell.style.numFmt.includes('#,##')){
|
||||
//千分位
|
||||
result = result.split('.');
|
||||
let number = result[0].split('').reverse();
|
||||
let newNumber = [];
|
||||
for(let i = 0; i< number.length; i++){
|
||||
newNumber.push(number[i]);
|
||||
if((i+1) % 3 === 0 && i < number.length - 1 && number[i+1] !== '-'){
|
||||
newNumber.push(',');
|
||||
}
|
||||
|
||||
}
|
||||
result[0] = newNumber.reverse().join('');
|
||||
result = result.join('.');
|
||||
}
|
||||
return prefix + result;
|
||||
}
|
||||
|
||||
}
|
||||
return value + '';
|
||||
}catch (e){
|
||||
return value;
|
||||
}
|
||||
|
||||
case 3: //字符串
|
||||
return value;
|
||||
case 4: //日期
|
||||
switch (numFmt){
|
||||
case 'yyyy-mm-dd;@':
|
||||
return dayjs(value).format('YYYY-MM-DD');
|
||||
case 'mm-dd-yy':
|
||||
return dayjs(value).format('YYYY/MM/DD');
|
||||
case '[$-F800]dddd, mmmm dd, yyyy':
|
||||
return dayjs(value).format('YYYY年M月D日 ddd');
|
||||
case 'm"月"d"日";@':
|
||||
return dayjs(value).format('M月D日');
|
||||
case 'yyyy/m/d h:mm;@':
|
||||
case 'm/d/yy "h":mm':
|
||||
return dayjs(value).subtract(8, 'hour').format('YYYY/M/DD HH:mm');
|
||||
case 'h:mm;@':
|
||||
return dayjs(value).format('HH:mm');
|
||||
default:
|
||||
return dayjs(value).format('YYYY-MM-DD');
|
||||
}
|
||||
|
||||
case 5: //超链接
|
||||
return value.text;
|
||||
case 6: //公式
|
||||
return get(value, 'result.error') || value.result;
|
||||
case 8: //富文本
|
||||
return cell.text;
|
||||
case 9: //Boolean
|
||||
return cell.text.toUpperCase();
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function transferArgbColor(originColor){
|
||||
if(typeof originColor === 'object'){
|
||||
return '#000000';
|
||||
}
|
||||
if(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.test(originColor)){
|
||||
return originColor.startsWith('#') ? originColor : '#' + originColor;
|
||||
}
|
||||
originColor = originColor.trim().toLowerCase(); //去掉前后空格
|
||||
let color = {};
|
||||
try {
|
||||
let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(originColor);
|
||||
color.r = parseInt(argb[2], 16);
|
||||
color.g = parseInt(argb[3], 16);
|
||||
color.b = parseInt(argb[4], 16);
|
||||
color.a = parseInt(argb[1], 16) / 255;
|
||||
return tinycolor(`rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`).toHexString();
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
function transferThemeColor(themeIndex, tint){
|
||||
|
||||
if(themeIndex > 9){
|
||||
return '#C7C9CC';
|
||||
}
|
||||
if(typeof tint === 'undefined'){
|
||||
return themeColor[themeIndex];
|
||||
}else if(tint > 0){
|
||||
return getLightColor(themeColor[themeIndex], tint);
|
||||
}else{
|
||||
return getDarkColor(themeColor[themeIndex],Math.abs(tint));
|
||||
}
|
||||
}
|
||||
function getStyle(cell){
|
||||
cell.style = cloneDeep(cell.style);
|
||||
let backGroundColor = null;
|
||||
if(cell.style.fill && cell.style.fill.fgColor) {
|
||||
// 8位字符颜色先转rgb再转16进制颜色
|
||||
if(cell.style.fill.fgColor.argb){
|
||||
backGroundColor = transferArgbColor(cell.style.fill.fgColor.argb);
|
||||
}else if(cell.style.fill.fgColor.hasOwnProperty('theme')){
|
||||
backGroundColor = transferThemeColor(cell.style.fill.fgColor.theme, cell.style.fill.fgColor.tint);
|
||||
}else if(cell.style.fill.fgColor.indexed){
|
||||
backGroundColor = indexedColor[cell.style.fill.fgColor.indexed] || '#C7C9CC';
|
||||
}else{
|
||||
backGroundColor = '#C7C9CC';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(backGroundColor) {
|
||||
cell.style.bgcolor = backGroundColor;
|
||||
}
|
||||
//*************************************************************************** */
|
||||
|
||||
//*********************字体存在背景色******************************
|
||||
// 字体颜色
|
||||
let fontColor = null;
|
||||
if(cell.style.font && cell.style.font.color ) {
|
||||
if(cell.style.font.color.argb){
|
||||
fontColor = transferArgbColor(cell.style.font.color.argb);
|
||||
}else if(cell.style.font.color.hasOwnProperty('theme')){
|
||||
fontColor = transferThemeColor(cell.style.font.color.theme, cell.style.font.color.tint);
|
||||
}else if(cell.style.font.color.indexed){
|
||||
fontColor = indexedColor[cell.style.font.color.indexed] || '#000000';
|
||||
}else {
|
||||
fontColor = '#000000';
|
||||
}
|
||||
|
||||
}
|
||||
if(fontColor) {
|
||||
cell.style.color = fontColor;
|
||||
}
|
||||
|
||||
// exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
|
||||
if(cell.style.alignment ) {
|
||||
if(cell.style.alignment.horizontal){
|
||||
cell.style.align = cell.style.alignment.horizontal;
|
||||
}
|
||||
if(cell.style.alignment.vertical){
|
||||
cell.style.valign = cell.style.alignment.vertical;
|
||||
}
|
||||
}
|
||||
if(cell.style.alignment && cell.style.alignment.wrapText) {
|
||||
cell.style.textwrap = true;
|
||||
}
|
||||
|
||||
if(cell.style.border){
|
||||
let styleBorder = {};
|
||||
Object.keys(cell.style.border).forEach(position =>{
|
||||
let originBorder = cell.style.border[position];
|
||||
let bordColor = '#000000';
|
||||
|
||||
if(typeof originBorder.color === 'string'){
|
||||
bordColor = originBorder.color;
|
||||
}else if(originBorder.color){
|
||||
if(originBorder.color.argb){
|
||||
bordColor = transferArgbColor(originBorder.color.argb);
|
||||
}else if(originBorder.color.hasOwnProperty('theme')){
|
||||
bordColor = transferThemeColor(originBorder.color.theme, originBorder.color.tint);
|
||||
}else if(originBorder.color.indexed){
|
||||
bordColor = indexedColor[originBorder.color.indexed];
|
||||
}
|
||||
}
|
||||
styleBorder[position] = [originBorder.style || 'thin', bordColor];
|
||||
});
|
||||
cell.style.border2 = {...cell.style.border};
|
||||
cell.style.border = styleBorder;
|
||||
}
|
||||
|
||||
if(cell.style.font && cell.style.font.size && typeof cell.style.font.size === 'number'){
|
||||
cell.style.font.size = Math.round(cell.style.font.size / 1.333333);
|
||||
}
|
||||
return cell.style;
|
||||
}
|
||||
|
||||
export function transferExcelToSpreadSheet(workbook, options){
|
||||
let workbookData = [];
|
||||
// console.log(workbook, 'workbook');
|
||||
let sheets = [];
|
||||
workbook.eachSheet((sheet) => {
|
||||
sheets.push(sheet);
|
||||
//console.log(sheet,'sheet');
|
||||
// 构造x-data-spreadsheet 的 sheet 数据源结构
|
||||
let sheetData = { name: sheet.name,styles : [], rows: {},cols:{}, merges:[],media:[] };
|
||||
// 收集合并单元格信息
|
||||
let mergeAddressData = [];
|
||||
for(let mergeRange in sheet._merges) {
|
||||
sheetData.merges.push(sheet._merges[mergeRange].shortRange);
|
||||
let mergeAddress = {};
|
||||
// 合并单元格起始地址
|
||||
mergeAddress.startAddress = sheet._merges[mergeRange].tl;
|
||||
// 合并单元格终止地址
|
||||
mergeAddress.endAddress = sheet._merges[mergeRange].br;
|
||||
// Y轴方向跨度
|
||||
mergeAddress.YRange = sheet._merges[mergeRange].model.bottom - sheet._merges[mergeRange].model.top;
|
||||
// X轴方向跨度
|
||||
mergeAddress.XRange = sheet._merges[mergeRange].model.right - sheet._merges[mergeRange].model.left;
|
||||
mergeAddressData.push(mergeAddress);
|
||||
}
|
||||
|
||||
transferColumns(sheet,sheetData, options);
|
||||
// 遍历行
|
||||
(sheet._rows || []).forEach((row,spreadSheetRowIndex) =>{
|
||||
sheetData.rows[spreadSheetRowIndex] = { cells: {} };
|
||||
|
||||
if(row.height){
|
||||
sheetData.rows[spreadSheetRowIndex].height = row.height + (options.heightOffset || 0);
|
||||
}else{
|
||||
sheetData.rows[spreadSheetRowIndex].height = defaultRowHeight + (options.heightOffset || 0);
|
||||
}
|
||||
//includeEmpty = false 不包含空白单元格
|
||||
(row._cells || []).forEach((cell, spreadSheetColIndex) =>{
|
||||
sheetData.rows[spreadSheetRowIndex].cells[spreadSheetColIndex] = {};
|
||||
|
||||
let mergeAddress = find(mergeAddressData, function(o) { return o.startAddress == cell._address; });
|
||||
if(mergeAddress && cell.master.address != mergeAddress.startAddress) {
|
||||
return;
|
||||
}
|
||||
if(mergeAddress){
|
||||
sheetData.rows[spreadSheetRowIndex].cells[spreadSheetColIndex].merge = [mergeAddress.YRange, mergeAddress.XRange];
|
||||
}
|
||||
sheetData.rows[spreadSheetRowIndex].cells[spreadSheetColIndex].text = getCellText(cell);
|
||||
sheetData.styles.push(getStyle(cell));
|
||||
sheetData.rows[spreadSheetRowIndex].cells[spreadSheetColIndex].style = sheetData.styles.length - 1;
|
||||
});
|
||||
});
|
||||
if(sheetData._media){
|
||||
sheetData.media = sheetData._media;
|
||||
}
|
||||
|
||||
let tempRowsKeys = Object.keys(sheetData.rows);
|
||||
|
||||
sheetData.rows.len = Math.max(+tempRowsKeys[tempRowsKeys.length-1] + 1,
|
||||
options.hasOwnProperty('minRowLength') ? options.minRowLength : 100);
|
||||
workbookData.push(sheetData);
|
||||
});
|
||||
// console.log(workbookData, 'workbookData');
|
||||
workbook._worksheets = sheets;
|
||||
return {
|
||||
workbookData,
|
||||
workbookSource: workbook,
|
||||
medias: workbook.media || []
|
||||
};
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
export function readOnlyInput(root){
|
||||
if(root){
|
||||
let nodes = root.querySelectorAll('input');
|
||||
for(let node of nodes){
|
||||
node && !node.readOnly && (node.readOnly = true);
|
||||
}
|
||||
document.activeElement && document.activeElement.blur();
|
||||
}
|
||||
}
|
@ -1,767 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
.x-spreadsheet {
|
||||
font-size: 13px;
|
||||
line-height: normal;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
|
||||
box-sizing: content-box;
|
||||
background: #fff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.x-spreadsheet textarea {
|
||||
font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
|
||||
}
|
||||
.x-spreadsheet-sheet {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.x-spreadsheet-table {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.x-spreadsheet-tooltip {
|
||||
font-family: inherit;
|
||||
position: absolute;
|
||||
padding: 5px 10px;
|
||||
color: #fff;
|
||||
border-radius: 1px;
|
||||
background: #000000;
|
||||
font-size: 12px;
|
||||
z-index: 201;
|
||||
}
|
||||
.x-spreadsheet-tooltip:before {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
left: calc(50% - 4px);
|
||||
top: -4px;
|
||||
content: "";
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: inherit;
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
z-index: 1;
|
||||
box-shadow: 1px 1px 3px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.x-spreadsheet-color-palette {
|
||||
padding: 5px;
|
||||
}
|
||||
.x-spreadsheet-color-palette table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 2;
|
||||
background: #fff;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td {
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td:hover {
|
||||
border-color: #ddd;
|
||||
}
|
||||
.x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.x-spreadsheet-border-palette {
|
||||
padding: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
background: #fff;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.x-spreadsheet-border-palette table td {
|
||||
margin: 0;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left {
|
||||
border-right: 1px solid #eee;
|
||||
padding-right: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right {
|
||||
padding-left: 6px;
|
||||
}
|
||||
.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
}
|
||||
.x-spreadsheet-dropdown {
|
||||
position: relative;
|
||||
}
|
||||
.x-spreadsheet-dropdown .x-spreadsheet-dropdown-content {
|
||||
position: absolute;
|
||||
z-index: 200;
|
||||
background: #fff;
|
||||
box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
|
||||
}
|
||||
.x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content {
|
||||
top: calc(100% + 5px);
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content {
|
||||
top: calc(100% + 5px);
|
||||
right: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content {
|
||||
bottom: calc(100% + 5px);
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content {
|
||||
bottom: calc(100% + 5px);
|
||||
right: 0;
|
||||
}
|
||||
.x-spreadsheet-dropdown .x-spreadsheet-dropdown-title {
|
||||
padding: 0 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
/* resizer **/
|
||||
.x-spreadsheet-resizer {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
}
|
||||
.x-spreadsheet-resizer .x-spreadsheet-resizer-hover {
|
||||
background-color: rgba(75, 137, 255, 0.25);
|
||||
}
|
||||
.x-spreadsheet-resizer .x-spreadsheet-resizer-line {
|
||||
position: absolute;
|
||||
}
|
||||
.x-spreadsheet-resizer.horizontal {
|
||||
cursor: row-resize;
|
||||
}
|
||||
.x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line {
|
||||
border-bottom: 2px dashed #4b89ff;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.x-spreadsheet-resizer.vertical {
|
||||
cursor: col-resize;
|
||||
}
|
||||
.x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line {
|
||||
border-right: 2px dashed #4b89ff;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
/* scrollbar */
|
||||
.x-spreadsheet-scrollbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #f4f5f8;
|
||||
opacity: 0.9;
|
||||
z-index: 12;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.horizontal {
|
||||
right: 15px;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.horizontal > div {
|
||||
height: 1px;
|
||||
background: #ddd;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.vertical {
|
||||
bottom: 15px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.x-spreadsheet-scrollbar.vertical > div {
|
||||
width: 1px;
|
||||
background: #ddd;
|
||||
}
|
||||
/* @{css-prefix}-overlayer */
|
||||
.x-spreadsheet-overlayer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.x-spreadsheet-overlayer .x-spreadsheet-overlayer-content {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.x-spreadsheet-editor,
|
||||
.x-spreadsheet-selector {
|
||||
box-sizing: content-box;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/* @{css-prefix}-selector */
|
||||
.x-spreadsheet-selector .hide-input {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
}
|
||||
.x-spreadsheet-selector .hide-input input {
|
||||
padding: 0;
|
||||
width: 0;
|
||||
border: none!important;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-area {
|
||||
position: absolute;
|
||||
border: 2px solid #4b89ff;
|
||||
background: rgba(75, 137, 255, 0.1);
|
||||
z-index: 5;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-clipboard,
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
|
||||
position: absolute;
|
||||
background: transparent;
|
||||
z-index: 100;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-clipboard {
|
||||
border: 2px dashed #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
|
||||
border: 1px dashed rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.x-spreadsheet-selector .x-spreadsheet-selector-corner {
|
||||
pointer-events: auto;
|
||||
position: absolute;
|
||||
cursor: crosshair;
|
||||
font-size: 0;
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
border: 2px solid #ffffff;
|
||||
background: #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-editor {
|
||||
z-index: 20;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
border: 2px solid #4b89ff;
|
||||
line-height: 0;
|
||||
z-index: 100;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area textarea {
|
||||
box-sizing: content-box;
|
||||
border: none;
|
||||
padding: 0 3px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
text-align: start;
|
||||
overflow-y: hidden;
|
||||
font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
|
||||
color: inherit;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
line-height: 22px;
|
||||
margin: 0;
|
||||
}
|
||||
.x-spreadsheet-editor .x-spreadsheet-editor-area .textline {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.x-spreadsheet-item {
|
||||
user-select: none;
|
||||
background: 0;
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
height: 26px;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 26px;
|
||||
list-style: none;
|
||||
padding: 2px 10px;
|
||||
cursor: default;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.x-spreadsheet-item.disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.x-spreadsheet-item:hover,
|
||||
.x-spreadsheet-item.active {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.x-spreadsheet-item.divider {
|
||||
height: 0;
|
||||
padding: 0;
|
||||
margin: 5px 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.x-spreadsheet-item .label {
|
||||
float: right;
|
||||
opacity: 0.65;
|
||||
font-size: 1em;
|
||||
}
|
||||
.x-spreadsheet-item.state,
|
||||
.x-spreadsheet-header.state {
|
||||
padding-left: 35px!important;
|
||||
position: relative;
|
||||
}
|
||||
.x-spreadsheet-item.state:before,
|
||||
.x-spreadsheet-header.state:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
left: 12px;
|
||||
top: calc(50% - 5px);
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-item.state.checked:before,
|
||||
.x-spreadsheet-header.state.checked:before {
|
||||
background: #4b89ff;
|
||||
}
|
||||
.x-spreadsheet-checkbox {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
backface-visibility: hidden;
|
||||
outline: 0;
|
||||
vertical-align: baseline;
|
||||
font-style: normal;
|
||||
font-size: 1rem;
|
||||
line-height: 1em;
|
||||
}
|
||||
.x-spreadsheet-checkbox > input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0!important;
|
||||
outline: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
.x-spreadsheet-suggest,
|
||||
.x-spreadsheet-contextmenu,
|
||||
.x-spreadsheet-sort-filter {
|
||||
position: absolute;
|
||||
box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
|
||||
background: #fff;
|
||||
z-index: 100;
|
||||
width: 260px;
|
||||
pointer-events: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
.x-spreadsheet-suggest {
|
||||
width: 200px;
|
||||
}
|
||||
.x-spreadsheet-filter {
|
||||
border: 1px solid #e9e9e9;
|
||||
font-size: 12px;
|
||||
margin: 10px;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-header {
|
||||
padding: 0.5em 0.75em;
|
||||
background: #f8f8f9;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-body {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.x-spreadsheet-sort-filter .x-spreadsheet-buttons {
|
||||
margin: 10px;
|
||||
}
|
||||
.x-spreadsheet-bottombar {
|
||||
height: 40px;
|
||||
padding: 0 30px;
|
||||
text-align: left;
|
||||
background: #f5f6f7;
|
||||
display: flex;
|
||||
}
|
||||
.x-spreadsheet-bottombar {
|
||||
position: relative;
|
||||
border-top: 1px solid #e0e2e4;
|
||||
}
|
||||
.x-spreadsheet-bottombar .x-spreadsheet-menu > li {
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #e8eaed;
|
||||
}
|
||||
.x-spreadsheet-menu {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
.x-spreadsheet-menu > li {
|
||||
float: left;
|
||||
line-height: 1.25em;
|
||||
padding: 0.785em 1em;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
color: #80868b;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-weight: bold;
|
||||
}
|
||||
.x-spreadsheet-menu > li.active {
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
.x-spreadsheet-menu > li .x-spreadsheet-dropdown {
|
||||
display: inline-block;
|
||||
}
|
||||
.x-spreadsheet-print {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.x-spreadsheet-print-bar {
|
||||
background: #424242;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
padding: 0 30px;
|
||||
}
|
||||
.x-spreadsheet-print-bar .-title {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
float: left;
|
||||
}
|
||||
.x-spreadsheet-print-bar .-right {
|
||||
float: right;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.x-spreadsheet-print-content {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
flex-direction: row;
|
||||
background: #d0d0d0;
|
||||
height: calc(100% - 60px);
|
||||
}
|
||||
.x-spreadsheet-print-content .-sider {
|
||||
flex: 0 0 300px;
|
||||
width: 300px;
|
||||
border-left: 2px solid #ccc;
|
||||
background: #fff;
|
||||
}
|
||||
.x-spreadsheet-print-content .-content {
|
||||
flex: auto;
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
.x-spreadsheet-canvas-card-wraper {
|
||||
margin: 40px 20px;
|
||||
}
|
||||
.x-spreadsheet-canvas-card {
|
||||
background: #fff;
|
||||
margin: auto;
|
||||
page-break-before: auto;
|
||||
page-break-after: always;
|
||||
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 3px rgba(0, 0, 0, 0.12), 0 4px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.x-spreadsheet-calendar {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
background: #ffffff;
|
||||
user-select: none;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header {
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
float: left;
|
||||
background: #f9fafb;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-left {
|
||||
padding-left: 5px;
|
||||
float: left;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right {
|
||||
float: right;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right a {
|
||||
padding: 3px 0;
|
||||
margin-right: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover {
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body th,
|
||||
.x-spreadsheet-calendar .calendar-body td {
|
||||
width: 14.28571429%;
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell:hover {
|
||||
background: #ecf6fd;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.active,
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.active:hover {
|
||||
background: #ecf6fd;
|
||||
color: #2185D0;
|
||||
}
|
||||
.x-spreadsheet-calendar .calendar-body td > .cell.disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.x-spreadsheet-datepicker {
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(100% + 5px);
|
||||
z-index: 10;
|
||||
width: auto;
|
||||
}
|
||||
.x-spreadsheet-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.x-spreadsheet-buttons .x-spreadsheet-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.x-spreadsheet-button {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
line-height: 1em;
|
||||
min-height: 1em;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
padding: 0.75em 1em;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
background: #E0E1E2;
|
||||
text-decoration: none;
|
||||
font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif;
|
||||
outline: none;
|
||||
vertical-align: baseline;
|
||||
zoom: 1;
|
||||
user-select: none;
|
||||
transition: all 0.1s linear;
|
||||
}
|
||||
.x-spreadsheet-button.active,
|
||||
.x-spreadsheet-button:hover {
|
||||
background-color: #C0C1C2;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.x-spreadsheet-button.primary {
|
||||
color: #fff;
|
||||
background-color: #2185D0;
|
||||
}
|
||||
.x-spreadsheet-button.primary:hover,
|
||||
.x-spreadsheet-button.primary.active {
|
||||
color: #fff;
|
||||
background-color: #1678c2;
|
||||
}
|
||||
.x-spreadsheet-form-input {
|
||||
font-size: 1em;
|
||||
position: relative;
|
||||
font-weight: 400;
|
||||
display: inline-flex;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.x-spreadsheet-form-input input {
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
flex: 1 0 auto;
|
||||
outline: 0;
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||
text-align: left;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
padding: 0 8px;
|
||||
background: #fff;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 3px;
|
||||
transition: box-shadow 0.1s ease, border-color 0.1s ease;
|
||||
box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
|
||||
}
|
||||
.x-spreadsheet-form-input input:focus {
|
||||
border-color: #4b89ff;
|
||||
box-shadow: inset 0 1px 2px rgba(75, 137, 255, 0.2);
|
||||
}
|
||||
.x-spreadsheet-form-select {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
user-select: none;
|
||||
box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
|
||||
}
|
||||
.x-spreadsheet-form-select .input-text {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 60px;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.x-spreadsheet-form-fields {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.x-spreadsheet-form-fields .x-spreadsheet-form-field {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.x-spreadsheet-form-fields .x-spreadsheet-form-field .label {
|
||||
display: inline-block;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
.x-spreadsheet-form-field {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.x-spreadsheet-form-field:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.x-spreadsheet-form-field.error .x-spreadsheet-form-select,
|
||||
.x-spreadsheet-form-field.error input {
|
||||
border-color: #f04134;
|
||||
}
|
||||
.x-spreadsheet-form-field .tip {
|
||||
color: #f04134;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.x-spreadsheet-dimmer {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
opacity: 0;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-duration: 0.5s;
|
||||
animation-duration: 0.5s;
|
||||
transition: background-color 0.5s linear;
|
||||
user-select: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
.x-spreadsheet-dimmer.active {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
form fieldset {
|
||||
border: none;
|
||||
}
|
||||
form fieldset label {
|
||||
display: block;
|
||||
margin-bottom: 0.5em;
|
||||
font-size: 1em;
|
||||
color: #666;
|
||||
}
|
||||
form fieldset select {
|
||||
font-size: 1.1em;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: none;
|
||||
border-bottom: 2px solid #ddd;
|
||||
padding: 0.5em 0.85em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.x-spreadsheet-modal,
|
||||
.x-spreadsheet-toast {
|
||||
font-size: 13px;
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
text-align: left;
|
||||
line-height: 1.25em;
|
||||
min-width: 360px;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 8px;
|
||||
}
|
||||
.x-spreadsheet-toast {
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.x-spreadsheet-modal-header,
|
||||
.x-spreadsheet-toast-header {
|
||||
font-weight: 600;
|
||||
background-clip: padding-box;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.x-spreadsheet-toast-header {
|
||||
color: #F2711C;
|
||||
}
|
||||
.x-spreadsheet-modal-header {
|
||||
border-bottom: 1px solid #e0e2e4;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
font-size: 1.0785em;
|
||||
}
|
||||
.x-spreadsheet-modal-header,
|
||||
.x-spreadsheet-modal-content,
|
||||
.x-spreadsheet-toast-header,
|
||||
.x-spreadsheet-toast-content {
|
||||
padding: 0.75em 1em;
|
||||
}
|
||||
|
||||
.x-spreadsheet-menu li:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vue-office-excel {
|
||||
height: 100%;
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
<script>
|
||||
import {defineComponent, ref, onMounted, onBeforeUnmount, watch, nextTick} from 'vue-demi';
|
||||
import Spreadsheet from 'x-data-spreadsheet';
|
||||
import {getData, readExcelData, transferExcelToSpreadSheet} from './excel';
|
||||
import {renderImage, clearCache} from './media';
|
||||
import {readOnlyInput} from './hack';
|
||||
import {debounce} from 'lodash';
|
||||
import {download as downloadFile} from '../../../utils/url';
|
||||
|
||||
const defaultOptions = {
|
||||
xls: false,
|
||||
minColLength: 20
|
||||
};
|
||||
export default defineComponent({
|
||||
name: 'VueOfficeExcel',
|
||||
props: {
|
||||
src: [String, ArrayBuffer, Blob],
|
||||
requestOptions: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
...defaultOptions
|
||||
})
|
||||
}
|
||||
},
|
||||
emits: ['rendered', 'error'],
|
||||
setup(props, {emit}) {
|
||||
const wrapperRef = ref(null);
|
||||
const rootRef = ref(null);
|
||||
let workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
let mediasSource = [];
|
||||
let sheetIndex = 0;
|
||||
let ctx = null;
|
||||
let xs = null;
|
||||
let offset = null;
|
||||
let fileData = null;
|
||||
|
||||
function renderExcel(buffer) {
|
||||
fileData = buffer;
|
||||
readExcelData(buffer, props.options.xls).then(workbook => {
|
||||
if (!workbook._worksheets || workbook._worksheets.length === 0) {
|
||||
throw new Error('未获取到数据,可能文件格式不正确或文件已损坏');
|
||||
}
|
||||
if(props.options.beforeTransformData && typeof props.options.beforeTransformData === 'function' ){
|
||||
workbook = props.options.beforeTransformData(workbook);
|
||||
}
|
||||
let {workbookData, medias, workbookSource} = transferExcelToSpreadSheet(workbook, {...defaultOptions, ...props.options});
|
||||
if(props.options.transformData && typeof props.options.transformData === 'function' ){
|
||||
workbookData = props.options.transformData(workbookData);
|
||||
}
|
||||
mediasSource = medias;
|
||||
workbookDataSource = workbookSource;
|
||||
offset = null;
|
||||
sheetIndex = 0;
|
||||
clearCache();
|
||||
xs.loadData(workbookData);
|
||||
renderImage(ctx, mediasSource, workbookDataSource._worksheets[sheetIndex], offset, props.options);
|
||||
emit('rendered');
|
||||
//涉及clear和offset
|
||||
|
||||
}).catch(e => {
|
||||
console.warn(e);
|
||||
mediasSource = [];
|
||||
workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
clearCache();
|
||||
xs && xs.loadData({});
|
||||
emit('error', e);
|
||||
});
|
||||
}
|
||||
const observerCallback = debounce(readOnlyInput, 200).bind(this,rootRef.value);
|
||||
const observer = new MutationObserver(observerCallback);
|
||||
const observerConfig = { attributes: true, childList: true, subtree: true };
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(()=>{
|
||||
observer.observe(rootRef.value, observerConfig);
|
||||
observerCallback(rootRef);
|
||||
|
||||
xs = new Spreadsheet(rootRef.value, {
|
||||
mode: 'read',
|
||||
showToolbar: false,
|
||||
showContextmenu: props.options.showContextmenu || false,
|
||||
view: {
|
||||
height: () => wrapperRef.value && wrapperRef.value.clientHeight || 300,
|
||||
width: () => wrapperRef.value && wrapperRef.value.clientWidth || 1200,
|
||||
},
|
||||
row: {
|
||||
height: 24,
|
||||
len: 100
|
||||
},
|
||||
col: {
|
||||
len: 26,
|
||||
width: 80,
|
||||
indexWidth: 60,
|
||||
minWidth: 60,
|
||||
},
|
||||
autoFocus: false
|
||||
}).loadData({});
|
||||
|
||||
let swapFunc = xs.bottombar.swapFunc;
|
||||
xs.bottombar.swapFunc = function (index) {
|
||||
swapFunc.call(xs.bottombar, index);
|
||||
sheetIndex = index;
|
||||
setTimeout(()=>{
|
||||
xs.reRender();
|
||||
renderImage(ctx, mediasSource, workbookDataSource._worksheets[sheetIndex], offset, props.options);
|
||||
});
|
||||
|
||||
};
|
||||
let clear = xs.sheet.editor.clear;
|
||||
xs.sheet.editor.clear = function (...args){
|
||||
clear.apply(xs.sheet.editor, args);
|
||||
setTimeout(()=>{
|
||||
renderImage(ctx, mediasSource, workbookDataSource._worksheets[sheetIndex], offset, props.options);
|
||||
});
|
||||
};
|
||||
let setOffset = xs.sheet.editor.setOffset;
|
||||
xs.sheet.editor.setOffset = function (...args){
|
||||
setOffset.apply(xs.sheet.editor, args);
|
||||
offset = args[0];
|
||||
renderImage(ctx, mediasSource, workbookDataSource._worksheets[sheetIndex], offset, props.options);
|
||||
};
|
||||
const canvas = rootRef.value.querySelector('canvas');
|
||||
ctx = canvas.getContext('2d');
|
||||
if (props.src) {
|
||||
getData(props.src, props.requestOptions).then(renderExcel).catch(e => {
|
||||
mediasSource = [];
|
||||
workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
xs.loadData({});
|
||||
emit('error', e);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(()=>{
|
||||
observer.disconnect();
|
||||
xs = null;
|
||||
});
|
||||
watch(() => props.src, () => {
|
||||
if (props.src) {
|
||||
getData(props.src, props.requestOptions).then(renderExcel).catch(e => {
|
||||
mediasSource = [];
|
||||
workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
xs.loadData({});
|
||||
emit('error', e);
|
||||
});
|
||||
} else {
|
||||
mediasSource = [];
|
||||
workbookDataSource = {
|
||||
_worksheets:[]
|
||||
};
|
||||
xs.loadData({});
|
||||
emit('error', new Error('src属性不能为空'));
|
||||
}
|
||||
});
|
||||
function save(fileName){
|
||||
downloadFile(fileName || `vue-office-excel-${new Date().getTime()}.xlsx`,fileData);
|
||||
}
|
||||
return {
|
||||
wrapperRef,
|
||||
rootRef,
|
||||
save
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vue-office-excel" ref="wrapperRef">
|
||||
<div class="vue-office-excel-main" ref="rootRef"></div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less">
|
||||
|
||||
</style>
|
@ -1,136 +0,0 @@
|
||||
let cache = [];
|
||||
export function renderImage(ctx, medias, sheet, offset, options={}){
|
||||
// console.log('medias', medias);
|
||||
// console.log('sheet', sheet);
|
||||
// console.log('offset', offset)
|
||||
if(sheet && sheet._media.length){
|
||||
sheet._media.forEach(media => {
|
||||
let {imageId, range, type} = media;
|
||||
if(type === 'image'){
|
||||
let position = calcPosition(sheet,range,offset, options);
|
||||
drawImage(ctx,imageId, medias[imageId], position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
let clipWidth = 60; //左侧序号列宽
|
||||
let clipHeight = 25; //顶部序号行高
|
||||
let defaultColWidth = 80;
|
||||
let defaultRowHeight = 24;
|
||||
let devicePixelRatio = window.devicePixelRatio;
|
||||
|
||||
function calcPosition(sheet, range, offset, options){
|
||||
let {widthOffset, heightOffset} = options;
|
||||
let {tl, br, ext} = range;
|
||||
let {nativeCol=0, nativeColOff=0, nativeRow=0, nativeRowOff=0} = tl || {};
|
||||
|
||||
let basicX = clipWidth;
|
||||
let basicY = clipHeight;
|
||||
for(let i=0; i < nativeCol; i++){
|
||||
basicX += sheet?._columns?.[i]?.width*6 || defaultColWidth;
|
||||
basicX += widthOffset || 0;
|
||||
}
|
||||
for(let i=0; i < nativeRow; i++){
|
||||
basicY += sheet?._rows?.[i]?.height || defaultRowHeight;
|
||||
basicY += heightOffset || 0;
|
||||
}
|
||||
let x = basicX + nativeColOff/12700;
|
||||
let y = basicY + nativeRowOff/12700;
|
||||
|
||||
let {
|
||||
nativeCol: nativeColEnd=0,
|
||||
nativeColOff: nativeColOffEnd=0,
|
||||
nativeRow: nativeRowEnd=0,
|
||||
nativeRowOff: nativeRowOffEnd=0
|
||||
} = br||{};
|
||||
let width =0;
|
||||
if(nativeCol === nativeColEnd){
|
||||
width = (nativeColOffEnd - nativeColOff) / 12700;
|
||||
}else if(br) {
|
||||
width = (sheet?._columns?.[nativeCol]?.width*6 || defaultColWidth) - nativeColOff/12700;
|
||||
|
||||
for(let i = nativeCol+1; i < nativeColEnd; i++){
|
||||
width += sheet?._columns?.[i]?.width*6 || defaultColWidth;
|
||||
}
|
||||
width += nativeColOffEnd / 12700;
|
||||
}else if(ext?.width){
|
||||
width = ext.width / 1.333333;
|
||||
}
|
||||
let height;
|
||||
if(nativeRow === nativeRowEnd){
|
||||
height = (nativeRowOffEnd - nativeRowOff) / 12700;
|
||||
}else if(br) {
|
||||
height = (sheet?._rows?.[nativeRow]?.height || defaultRowHeight) - nativeRowOff/12700;
|
||||
for(let i = nativeRow+1; i < nativeRowEnd; i++){
|
||||
height += sheet?._rows?.[i]?.height || defaultRowHeight;
|
||||
}
|
||||
height += nativeRowOffEnd / 12700;
|
||||
}else if(ext?.height){
|
||||
height = ext.height / 1.333333;
|
||||
}
|
||||
|
||||
return {
|
||||
x: (x - (offset?.scroll?.x || 0)) * devicePixelRatio,
|
||||
y: (y - (offset?.scroll?.y || 0)) * devicePixelRatio,
|
||||
width: width * devicePixelRatio,
|
||||
height: height * devicePixelRatio
|
||||
};
|
||||
}
|
||||
export function clearCache(){
|
||||
cache = [];
|
||||
}
|
||||
|
||||
function drawImage(ctx,index, data, position){
|
||||
getImage(index, data).then(image=>{
|
||||
let sx = 0;
|
||||
let sy = 0;
|
||||
let sWidth = image.width;
|
||||
let sHeight = image.height;
|
||||
let dx = position.x;
|
||||
let dy = position.y;
|
||||
let dWidth = position.width;
|
||||
let dHeight = position.height;
|
||||
let scaleX = dWidth / sWidth;
|
||||
let scaleY = dHeight / sHeight;
|
||||
|
||||
if(dx < clipWidth * devicePixelRatio){
|
||||
let diff = clipWidth * devicePixelRatio - dx;
|
||||
dx = clipWidth * devicePixelRatio;
|
||||
dWidth -= diff;
|
||||
sWidth -= diff/scaleX;
|
||||
sx += diff/scaleX;
|
||||
}
|
||||
if(dy < clipHeight * devicePixelRatio){
|
||||
let diff = clipHeight * devicePixelRatio - dy;
|
||||
dy = clipHeight * devicePixelRatio;
|
||||
dHeight -= diff;
|
||||
sHeight -= diff/scaleY;
|
||||
sy += diff/scaleY;
|
||||
}
|
||||
// console.log('=>', sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
||||
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
|
||||
}).catch(e=>{
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
function getImage(index, data){
|
||||
return new Promise(((resolve, reject) => {
|
||||
if(cache[index]){
|
||||
return resolve(cache[index]);
|
||||
}
|
||||
const {buffer} = data.buffer;
|
||||
let blob = new Blob([buffer], { type: 'image/' + data.extension});
|
||||
let url = URL.createObjectURL(blob);
|
||||
let image = new Image();
|
||||
image.src = url;
|
||||
image.onload = function (){
|
||||
resolve(image);
|
||||
cache[index] = image;
|
||||
};
|
||||
image.onerror = function (e){
|
||||
reject(e);
|
||||
};
|
||||
}));
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { createVuePlugin } from 'vite-plugin-vue2';
|
||||
import vue3 from '@vitejs/plugin-vue';
|
||||
import * as compiler from '@vue/compiler-sfc';
|
||||
import { isVue2 } from 'vue-demi';
|
||||
const { resolve } = require('path');
|
||||
import babel from '@rollup/plugin-babel';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
isVue2
|
||||
? createVuePlugin()
|
||||
: vue3({
|
||||
compiler: compiler
|
||||
})
|
||||
],
|
||||
build: {
|
||||
minify: 'terser',
|
||||
target: 'es2015',
|
||||
outDir: 'lib/v' + (isVue2 ? '2' : '3'),
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.js'), //指定组件编译入口文件
|
||||
name: 'vue-office-excel',
|
||||
fileName: 'vue-office-excel',
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: ['vue-demi']
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['vue-demi','vue'],
|
||||
output: {
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
'vue-demi': 'VueDemi'
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
babel({
|
||||
extensions: ['.js', '.ts', '.vue'],
|
||||
babelHelpers: 'runtime',
|
||||
plugins: [
|
||||
'@babel/plugin-transform-runtime',
|
||||
'@babel/plugin-transform-template-literals'
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
useBuiltIns: false,
|
||||
targets: {
|
||||
chrome: '40'
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
@ -1 +0,0 @@
|
||||
registry=https://registry.npmjs.org
|
9
core/packages/vue-pdf/index.d.ts
vendored
9
core/packages/vue-pdf/index.d.ts
vendored
@ -1,9 +0,0 @@
|
||||
declare const VueOfficePdf: {
|
||||
install?: (vue: any) => void;
|
||||
src: string|ArrayBuffer|Blob;
|
||||
rerender?: () => any;
|
||||
staticFileUrl?: string,
|
||||
requestOptions?: any;
|
||||
options?: any
|
||||
};
|
||||
export default VueOfficePdf;
|
@ -1,7 +0,0 @@
|
||||
import VueOfficePdf from './src/main.vue';
|
||||
|
||||
VueOfficePdf.install = function (Vue) {
|
||||
Vue.component(VueOfficePdf.name, VueOfficePdf);
|
||||
};
|
||||
|
||||
export default VueOfficePdf;
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"name": "@vue-office/pdf",
|
||||
"version": "1.6.5",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf lib",
|
||||
"copyFile2": "cp lib/v2/vue-office-pdf.umd.js lib/v2/index.js",
|
||||
"copyFile3": "cp lib/v3/vue-office-pdf.umd.js lib/v3/index.js",
|
||||
"copyReadme": "cp ../../../README.md README.md",
|
||||
"copyType": "cp index.d.ts lib/index.d.ts",
|
||||
"copyScripts": "mkdir lib/script/ && cp ../../script/postinstall.js lib/script/postinstall.js && cp ../../script/switch-cli.js lib/script/switch-cli.js && cp ../../script/utils.js lib/script/utils.js",
|
||||
"build:2": "npx vue-demi-switch 2 vue2 && vite build && npm run copyFile2",
|
||||
"build:3": "npx vue-demi-switch 3 vue3 && vite build && npm run copyFile3",
|
||||
"build": "npm run clean && npm run build:2 && npm run build:3 && npm run copyScripts && npm run copyReadme && npm run copyType",
|
||||
"postinstall": "node lib/script/postinstall.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.7.1",
|
||||
"vue": "^2.0.0 || >=3.0.0",
|
||||
"vue-demi": "^0.14.6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:501351981/vue-office.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"docx",
|
||||
"pdf",
|
||||
"ppt",
|
||||
"excel",
|
||||
"docx-preview",
|
||||
"excel-preview",
|
||||
"pdf-preview"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "微信: _hit757_",
|
||||
"gitHead": "d20568113bec480f6ca72924f6d0c1e3b0f1fe15"
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
<script>
|
||||
import { defineComponent, ref, onMounted, watch, onBeforeUnmount } from 'vue-demi';
|
||||
import workerStr from './worker?raw';
|
||||
import pdfjsLib from './pdf?raw';
|
||||
import { download as downloadFile, getUrl, loadScript } from '../../../utils/url';
|
||||
import { base64_encode } from '../../../utils/base64';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
const pdfJsLibSrc = `data:text/javascript;base64,${(base64_encode(pdfjsLib))}`;
|
||||
const PdfJsWorkerSrc = `data:text/javascript;base64,${(base64_encode(workerStr))}`;
|
||||
let pdfJsLibLoaded = false;
|
||||
let workerLoaded = false;
|
||||
export default defineComponent({
|
||||
name: 'VueOfficePdf',
|
||||
props: {
|
||||
src: [String, ArrayBuffer, Blob],
|
||||
requestOptions: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
staticFileUrl: {
|
||||
type: String,
|
||||
default: 'https://unpkg.com/pdfjs-dist@3.1.81/'
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
emits: ['rendered', 'error'],
|
||||
setup(props, { emit }) {
|
||||
let pdfDocument = null;
|
||||
let loadingTask = null;
|
||||
const wrapperRef = ref(null);
|
||||
const rootRef = ref([]);
|
||||
const numPages = ref(0);
|
||||
|
||||
const lazySize = 5;
|
||||
let loopCheckTimer = null;
|
||||
|
||||
onBeforeUnmount(()=>{
|
||||
if(pdfDocument === null){
|
||||
return;
|
||||
}
|
||||
pdfDocument.destroy();
|
||||
pdfDocument = null;
|
||||
loadingTask = null;
|
||||
loopCheckTimer && clearTimeout(loopCheckTimer);
|
||||
});
|
||||
function installPdfScript() {
|
||||
return loadScript(pdfJsLibSrc).then(() => {
|
||||
if (window.pdfjsLib && !workerLoaded) {
|
||||
workerLoaded = true;
|
||||
window.pdfjsLib.GlobalWorkerOptions.workerSrc = PdfJsWorkerSrc;
|
||||
} else {
|
||||
return Promise.reject('window.pdfjsLib未找到');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function waitPdfjsLoad(){
|
||||
return new Promise((resolve)=>{
|
||||
const loopCheck = () =>{
|
||||
if(window.pdfjsLib) {
|
||||
resolve();
|
||||
}else{
|
||||
loopCheckTimer = setTimeout(loopCheck, 10);
|
||||
}
|
||||
};
|
||||
loopCheck();
|
||||
});
|
||||
}
|
||||
function checkPdfLib() {
|
||||
if (window.pdfjsLib) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if(!pdfJsLibLoaded){
|
||||
pdfJsLibLoaded = true;
|
||||
return installPdfScript();
|
||||
}else{
|
||||
return waitPdfjsLoad();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (!props.src) {
|
||||
numPages.value = 0;
|
||||
return;
|
||||
}
|
||||
loadingTask = window.pdfjsLib.getDocument({
|
||||
url: getUrl(props.src),
|
||||
httpHeaders: props.requestOptions && props.requestOptions.headers,
|
||||
withCredentials: props.requestOptions && props.requestOptions.withCredentials,
|
||||
cMapUrl: `${props.staticFileUrl.endsWith('/') ? props.staticFileUrl : props.staticFileUrl + '/'}cmaps/`,
|
||||
cMapPacked: true,
|
||||
enableXfa: true,
|
||||
...omit(props.options, ['width'])
|
||||
});
|
||||
loadingTask.promise.then((pdf) => {
|
||||
pdfDocument && pdfDocument.destroy();
|
||||
pdfDocument = pdf;
|
||||
numPages.value = props.options.lazy ? Math.min(pdfDocument.numPages, lazySize) : pdfDocument.numPages;
|
||||
setTimeout(()=>{
|
||||
renderPage(1);
|
||||
});
|
||||
}).catch((e) => {
|
||||
emit('error', e);
|
||||
});
|
||||
}
|
||||
|
||||
function onScrollPdf(e) {
|
||||
if(!props.options.lazy){
|
||||
return;
|
||||
}
|
||||
const { scrollTop, scrollHeight, clientHeight } = e.target;
|
||||
if (scrollTop + clientHeight >= scrollHeight) {
|
||||
if (numPages.value >= pdfDocument.numPages) {
|
||||
return;
|
||||
}
|
||||
let oldNum = numPages.value;
|
||||
numPages.value = Math.min(pdfDocument.numPages, oldNum + lazySize);
|
||||
if (numPages.value > oldNum) {
|
||||
renderPage(oldNum + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderPage(num) {
|
||||
pdfDocument.getPage(num).then((pdfPage) => {
|
||||
const viewport = pdfPage.getViewport({ scale: 2 });
|
||||
const outputScale = window.devicePixelRatio > 2 ? 1.5 : 2;
|
||||
|
||||
const canvas = rootRef.value[num - 1];
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = Math.floor(viewport.width * outputScale);
|
||||
canvas.height = Math.floor(viewport.height * outputScale);
|
||||
|
||||
let domWidth = Math.floor(viewport.width);
|
||||
let domHeight = Math.floor(viewport.height);
|
||||
if (props.options.width) {
|
||||
let scale = props.options.width / domWidth;
|
||||
domWidth = Math.floor(props.options.width);
|
||||
domHeight = Math.floor(domHeight * scale);
|
||||
}
|
||||
let wrapperWidth = wrapperRef.value.getBoundingClientRect().width - 20;
|
||||
if (domWidth > wrapperWidth) {
|
||||
let scale = wrapperWidth / domWidth;
|
||||
domWidth = Math.floor(wrapperWidth);
|
||||
domHeight = Math.floor(domHeight * scale);
|
||||
}
|
||||
|
||||
canvas.style.width = domWidth + 'px';
|
||||
canvas.style.height = domHeight + 'px';
|
||||
|
||||
const transform = outputScale !== 1
|
||||
? [outputScale, 0, 0, outputScale, 0, 0]
|
||||
: null;
|
||||
|
||||
const renderTask = pdfPage.render({
|
||||
canvasContext: ctx,
|
||||
transform,
|
||||
viewport
|
||||
});
|
||||
renderTask.promise.then(() => {
|
||||
if (numPages.value > num) {
|
||||
renderPage(num + 1);
|
||||
} else {
|
||||
emit('rendered');
|
||||
}
|
||||
}).catch((e) => {
|
||||
emit('error', e);
|
||||
});
|
||||
}).catch((e) => {
|
||||
emit('error', e);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function rerender(){
|
||||
renderPage(1);
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.src) {
|
||||
checkPdfLib().then(init).catch(e => {
|
||||
console.warn(e);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.src, () => {
|
||||
checkPdfLib().then(init).catch(e => {
|
||||
console.warn(e);
|
||||
});
|
||||
});
|
||||
function save(fileName) {
|
||||
pdfDocument && pdfDocument._transport && pdfDocument._transport.getData().then(fileData => {
|
||||
downloadFile(fileName || `vue-office-pdf-${new Date().getTime()}.pdf`, fileData.buffer);
|
||||
});
|
||||
}
|
||||
return {
|
||||
wrapperRef,
|
||||
rootRef,
|
||||
numPages,
|
||||
save,
|
||||
onScrollPdf,
|
||||
rerender
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vue-office-pdf" ref="vue-office-pdf" style="text-align: center;overflow-y: auto;" @scroll="onScrollPdf">
|
||||
<div v-if="numPages" ref="wrapperRef" class="vue-office-pdf-wrapper" style="background: gray; padding: 30px 0;position: relative;">
|
||||
<canvas v-for="page in numPages" ref="rootRef" :key="page" style="width:100%" />
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less">
|
||||
</style>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,37 +0,0 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { createVuePlugin } from 'vite-plugin-vue2';
|
||||
import vue3 from '@vitejs/plugin-vue';
|
||||
import * as compiler from '@vue/compiler-sfc';
|
||||
import { isVue2 } from 'vue-demi';
|
||||
const { resolve } = require('path');
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
isVue2
|
||||
? createVuePlugin()
|
||||
: vue3({
|
||||
compiler: compiler
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
target: 'es2015',
|
||||
outDir: 'lib/v' + (isVue2 ? '2' : '3'),
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'index.js'), //指定组件编译入口文件
|
||||
name: 'vue-office-pdf',
|
||||
fileName: 'vue-office-pdf',
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: ['vue-demi']
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['vue-demi','vue'],
|
||||
output: {
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
'vue-demi': 'VueDemi'
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user