Commit 6db57b86 authored by 田翔's avatar 田翔

fix: excel表格预览优化

parent b88c4a58
{ {
"name": "panda-xform", "name": "panda-xform",
"version": "5.1.8", "version": "5.1.9",
"description": "5.1.8 自动计算参数属性修改", "description": "5.1.9 excel表格预览优化",
"keywords": [ "keywords": [
"panda-xform" "panda-xform"
], ],
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
"react-svg": "15.1.9", "react-svg": "15.1.9",
"viewerjs": "^1.11.3", "viewerjs": "^1.11.3",
"viewerjs-react": "^1.0.2", "viewerjs-react": "^1.0.2",
"xlsx": "^0.18.5",
"yarn": "^1.22.17" "yarn": "^1.22.17"
}, },
"devDependencies": { "devDependencies": {
...@@ -53,9 +54,9 @@ ...@@ -53,9 +54,9 @@
"@babel/plugin-syntax-jsx": "^7.12.13", "@babel/plugin-syntax-jsx": "^7.12.13",
"@babel/plugin-transform-modules-amd": "^7.14.5", "@babel/plugin-transform-modules-amd": "^7.14.5",
"@umijs/fabric": "^2.0.7", "@umijs/fabric": "^2.0.7",
"@wisdom-map/amap": "1.1.0-beta.56", "@wisdom-map/amap": "1.1.0-beta.42",
"@wisdom-map/arcgismap": "1.4.0-178", "@wisdom-map/arcgismap": "1.4.0-92",
"@wisdom-map/basemap": "1.1.0-27", "@wisdom-map/basemap": "1.1.0-18",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"babel-plugin-import": "^1.13.3", "babel-plugin-import": "^1.13.3",
"check-prettier": "^1.0.3", "check-prettier": "^1.0.3",
...@@ -131,4 +132,4 @@ ...@@ -131,4 +132,4 @@
"publishConfig": { "publishConfig": {
"registry": "https://g.civnet.cn:4873" "registry": "https://g.civnet.cn:4873"
} }
} }
\ No newline at end of file
...@@ -201,6 +201,10 @@ export function downloadFile(str) { ...@@ -201,6 +201,10 @@ export function downloadFile(str) {
return request({ return request({
url: `${url}/DownloadFiles?filePath=${str}`, url: `${url}/DownloadFiles?filePath=${str}`,
method: 'get', method: 'get',
headers: {
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
},
responseType: 'blob'
}); });
} }
......
import React, { useMemo, useState } from 'react' import React, { useEffect, useMemo, useState } from 'react'
import styles from './index.less' import styles from './index.less'
import { Button, Upload, message } from 'antd' import { Button, Upload, message } from 'antd'
import { getFileType } from '../../../../../../constant' import { getFileType } from '../../../../../../constant'
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
import FileViewer from 'react-file-viewer' import FileViewer from 'react-file-viewer'
import Viewer from 'viewerjs-react' import Viewer from 'viewerjs-react'
import Drag from '../../../../../components/Drag' import Drag from '../../../../../components/Drag'
import { convertUrlToBase64 } from '../../../../../../utils/index'
const FileView = (props) => { const FileView = (props) => {
...@@ -22,6 +23,7 @@ const FileView = (props) => { ...@@ -22,6 +23,7 @@ const FileView = (props) => {
const [visible, setVisible] = useState(false) const [visible, setVisible] = useState(false)
const [viewVisible, setViewVisible] = useState(false) const [viewVisible, setViewVisible] = useState(false)
const [showFile, setShowFile] = useState({ fileType: '', filePath: '' }) const [showFile, setShowFile] = useState({ fileType: '', filePath: '' })
const [fileListSrc, setFileListSrc] = useState(fileList)
const icon = useMemo(() => { const icon = useMemo(() => {
if (fileType === '音频') { if (fileType === '音频') {
...@@ -33,6 +35,20 @@ const FileView = (props) => { ...@@ -33,6 +35,20 @@ const FileView = (props) => {
return <FileZipOutlined /> return <FileZipOutlined />
}, [fileType]) }, [fileType])
useEffect(() => {
getfileListSrc()
}, [])
const getfileListSrc = async () => {
let array = []
for (let i = 0; i < fileList.length; i++) {
let src = `${window.origin}/PandaWorkFlow/WorkFlow/AccountManage/DownloadFiles?filePath=${fileList[i]}`
let value = fileList[i].includes('svg') ? await convertUrlToBase64(src) : src
array.push(value)
}
setFileListSrc(array)
}
const showList = useMemo(() => { const showList = useMemo(() => {
let list = [] let list = []
fileList.forEach((item, index) => { fileList.forEach((item, index) => {
...@@ -50,7 +66,6 @@ const FileView = (props) => { ...@@ -50,7 +66,6 @@ const FileView = (props) => {
"response": { "code": 0, "msg": "Ok", "data": item, "stackTrace": null }, "response": { "code": 0, "msg": "Ok", "data": item, "stackTrace": null },
"xhr": {}, "xhr": {},
}; };
// if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}${site ? `&_site=${site}` : ''}`;
list.push(_obj) list.push(_obj)
} }
}) })
...@@ -61,18 +76,14 @@ const FileView = (props) => { ...@@ -61,18 +76,14 @@ const FileView = (props) => {
if (fileType === '图片') { if (fileType === '图片') {
return ( return (
<div className={styles.fileView}> <div className={styles.fileView} id='panda-xform-fileView'>
<Viewer> <Viewer container='#app'>
{ {
fileList.map((v, i) => { fileListSrc.map((v, i) => {
return ( return (
<span className={styles.imgSpan} key={v} style={{ display: i == 0 ? 'inline-block' : 'none' }}> <span className={styles.imgSpan} key={i} style={{ display: i == 0 ? 'inline-block' : 'none' }}>
{fileList.length !== 1 ? <span className={styles.imgSub}>{fileList.length}</span> : null} {fileList.length !== 1 ? <span className={styles.imgSub}>{fileList.length}</span> : null}
<img <img className={styles.img} src={v}></img>
className={styles.img}
src={`${window.origin}/PandaWorkFlow/WorkFlow/AccountManage/DownloadFiles?filePath=${v}`}
>
</img>
</span> </span>
) )
}) })
...@@ -96,7 +107,6 @@ const FileView = (props) => { ...@@ -96,7 +107,6 @@ const FileView = (props) => {
const option = { const option = {
name: 'file', name: 'file',
// action: `${window.location.origin}${uploadFileUrl}`,
listType: 'picture', listType: 'picture',
withCredentials: true, withCredentials: true,
showUploadList: download ? showUploadList: download ?
...@@ -116,7 +126,7 @@ const FileView = (props) => { ...@@ -116,7 +126,7 @@ const FileView = (props) => {
} }
return ( return (
<div className={styles.fileView}> <div className={styles.fileView} >
<Button <Button
size='small' size='small'
icon={icon} icon={icon}
......
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import styles from './index.less' import styles from './index.less'
import { Upload, Button, message } from 'antd' import { Upload, Button, message, Tabs } from 'antd'
import { UploadOutlined, FileOutlined } from '@ant-design/icons' import { UploadOutlined, FileOutlined } from '@ant-design/icons'
import FileViewer from 'react-file-viewer' import FileViewer from 'react-file-viewer'
import { uploadFileUrl, downloadFileUrl } from '../../../../apis/process' import { uploadFileUrl, downloadFileUrl, downloadFile } from '../../../../apis/process'
import { filenameVerification } from '../../../../utils' import { filenameVerification } from '../../../../utils'
import Drag from '../../../components/Drag' import Drag from '../../../components/Drag'
import * as XLSX from 'xlsx'
import { convertUrlToBase64 } from '../../../../utils/index'
const accepts = { const accepts = {
'全部': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg', '.docx', '.xlsx', '.pdf', '.mp4', '.mp3'], '全部': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg', '.docx', '.xlsx', '.pdf', '.mp4', '.mp3'],
...@@ -64,10 +66,10 @@ const FileUpload = (props) => { ...@@ -64,10 +66,10 @@ const FileUpload = (props) => {
const [showList, setShowList] = useState([]) const [showList, setShowList] = useState([])
const [visible, setVisible] = useState(false) const [visible, setVisible] = useState(false)
const [showFile, setShowFile] = useState({ fileType: '', filePath: '' }) const [showFile, setShowFile] = useState({ fileType: '', filePath: '' })
const [imgVisible, setImgVisible] = useState(false) const [workbook, setWorkbook] = useState({ SheetNames: [] })
const showType = fileType === '图片' ? 'picture-card' : 'picture' const showType = fileType === '图片' ? 'picture-card' : 'picture'
const option = { const option = {
name: 'file', name: 'file',
action: `${window.location.origin}${uploadFileUrl}`, action: `${window.location.origin}${uploadFileUrl}`,
...@@ -112,16 +114,31 @@ const FileUpload = (props) => { ...@@ -112,16 +114,31 @@ const FileUpload = (props) => {
if (Array.isArray(fileList)) { if (Array.isArray(fileList)) {
setShowList(fileList) setShowList(fileList)
} else { } else {
setShowList() setShowList([])
} }
if (file.status === 'done') { if (file.status === 'done') {
onChange(fileList.map(v => v.sourcePath).join(',')) onChange(fileList.map(v => v.sourcePath).join(','))
} }
}, },
onPreview: (file) => { onPreview: async (file) => {
if (!preview) return message.info('该附件禁止预览') if (!preview) return message.info('该附件禁止预览')
let fileType = getFileType(file.name) let fileType = getFileType(file.name)
if (fileType) { if (fileType) {
if (fileType === 'xlsx') {
downloadFile(file.sourcePath)
.then(response => response.arrayBuffer())
.then(buffer => {
const data = new Uint8Array(buffer);
const workbook = XLSX.read(data, { type: 'array' });
setWorkbook(workbook)
workbook?.SheetNames?.forEach(sheetName => {
const worksheet = workbook.Sheets[sheetName];
// 将工作表转换为 JSON 对象
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' });
console.log(sheetName, jsonData)
})
})
}
setShowFile({ name: file.name, fileType: fileType, filePath: file.url }) setShowFile({ name: file.name, fileType: fileType, filePath: file.url })
setVisible(true) setVisible(true)
} else { } else {
...@@ -130,6 +147,77 @@ const FileUpload = (props) => { ...@@ -130,6 +147,77 @@ const FileUpload = (props) => {
} }
} }
const elemet = () => {
if (['jpg', 'png', 'svg', 'jpeg'].includes(showFile.fileType)) {
return (
<div style={{ width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<img style={{ maxWidth: '100%', maxHeight: '100%' }} src={window.location.origin + showFile.filePath}></img>
</div>
)
} else if (['xlsx'.includes(showFile.fileType)]) {
return (
<div>
<Tabs>
{
workbook?.SheetNames?.map(sheetName => {
const worksheet = workbook.Sheets[sheetName]
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' })
return (
<Tabs.TabPane tab={sheetName} key={sheetName}>
<div style={{ width: '100%', height: '550px', overflow: 'auto' }}>
<table
cellPadding={10}
style={{ width: '100%', height: '100%', display: 'block', tableLayout: 'fixed' }}
>
{
jsonData.map((row, rowIndex) => {
let maxLength = 0
jsonData.forEach((v, i) => {
if (v.length > maxLength) {
maxLength = v.length
}
})
let width = (100 / maxLength) + '%'
return (
<tbody>
<tr>
{
row.map((col, colIndex) => {
return (
<td
colSpan={row.length === 1 ? maxLength : 1}
style={{ border: '1px solid #aaa', width: width }}
>
{row[colIndex]}
</td>
)
})
}
</tr>
</tbody>
)
})
}
</table>
</div>
</Tabs.TabPane>
)
})
}
</Tabs>
</div>
)
}
return (
<FileViewer
className='fileViewer'
title='123'
fileType={showFile.fileType}
filePath={window.location.origin + showFile.filePath}
/>
)
}
const iconRender = (file, listType) => { const iconRender = (file, listType) => {
if (listType !== 'text') { if (listType !== 'text') {
let fileType = getFileType(file.name) let fileType = getFileType(file.name)
...@@ -142,37 +230,37 @@ const FileUpload = (props) => { ...@@ -142,37 +230,37 @@ const FileUpload = (props) => {
return <FileOutlined /> return <FileOutlined />
} }
const valueToList = (presetValue) => { const valueToList = async (presetValue) => {
let fileList = [] let fileList = []
if (presetValue) { if (presetValue) {
let list = presetValue ? presetValue.split(',') : [] let list = presetValue ? presetValue.split(',') : []
list.forEach((item, index) => { for (let i = 0; i < list.length; i++) {
if (item) { // @Tips: 直接过滤掉名字中有异常字符的文件 if (list[i]) { // @Tips: 直接过滤掉名字中有异常字符的文件
let uid = index + '_' + Math.random() let uid = i + '_' + Math.random()
let _obj = { let _obj = {
uid: uid, uid: uid,
value: item, value: list[i],
name: item.split('\\').reverse()[0], name: list[i].split('\\').reverse()[0],
type: fileType === '图片' ? 'image/jpeg' : 'file', type: fileType === '图片' ? 'image/jpeg' : 'file',
status: 'done', status: 'done',
url: `${downloadFileUrl}?filePath=${item}${site ? `&_site=${site}` : ''}`, url: `${downloadFileUrl}?filePath=${list[i]}${site ? `&_site=${site}` : ''}`,
sourcePath: item.url, sourcePath: list[i],
thumbUrl: list[i].includes('svg') ? await convertUrlToBase64(`${window.origin}${downloadFileUrl}?filePath=${list[i]}${site ? `&_site=${site}` : ''}`) : list[i],
originFileObj: { "uid": uid }, originFileObj: { "uid": uid },
"response": { "code": 0, "msg": "Ok", "data": item, "stackTrace": null }, "response": { "code": 0, "msg": "Ok", "data": list[i], "stackTrace": null },
"xhr": {}, "xhr": {},
}; };
if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}${site ? `&_site=${site}` : ''}`;
fileList.push(_obj); fileList.push(_obj);
} }
}) }
} }
return fileList return fileList
} }
useEffect(() => { useEffect(async () => {
if (presetValue && !presetValue.includes('拍照相册')) { if (presetValue && !presetValue.includes('拍照相册')) {
addons?.setValue(addons?.dataPath, presetValue || '') addons?.setValue(addons?.dataPath, presetValue || '')
setShowList(valueToList(presetValue)) setShowList(await valueToList(presetValue))
} else { } else {
addons?.setValue(addons?.dataPath, '') addons?.setValue(addons?.dataPath, '')
} }
...@@ -201,20 +289,7 @@ const FileUpload = (props) => { ...@@ -201,20 +289,7 @@ const FileUpload = (props) => {
onCancel={() => setVisible(false)} onCancel={() => setVisible(false)}
bodyStyle={{ height: 650, overflowY: showFile.fileType.includes('xlsx') ? 'none' : "auto" }} bodyStyle={{ height: 650, overflowY: showFile.fileType.includes('xlsx') ? 'none' : "auto" }}
> >
{ {elemet()}
['jpg', 'png', 'svg', 'jpeg'].includes(showFile.fileType) ? (
<div style={{ width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<img style={{ maxWidth: '100%', maxHeight: '100%' }} src={window.location.origin + showFile.filePath}></img>
</div>
) : (
<FileViewer
className='fileViewer'
title='123'
fileType={showFile.fileType}
filePath={window.location.origin + showFile.filePath}
/>
)
}
</Drag> </Drag>
</div> </div>
) )
......
...@@ -34,6 +34,20 @@ export function filenameVerification(file, special) { ...@@ -34,6 +34,20 @@ export function filenameVerification(file, special) {
}; };
} }
export const convertUrlToBase64 = async (url) => {
const response = await fetch(url)
const blob = await response.blob()
return await new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => {
const base64 = reader.result.split(',')[1]
resolve(`data:image/svg+xml;base64,${base64}`)
}
reader.onerror = reject
reader.readAsDataURL(blob)
})
}
/** /**
* @Description: 判断数据类型 * @Description: 判断数据类型
* @Params: 参数描述 * @Params: 参数描述
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment