feat: 新增空格键快速预览docx和excel文件
This commit is contained in:
parent
48881a860f
commit
06cad76ce0
@ -15,6 +15,9 @@
|
|||||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
|
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vue-office/docx": "^1.6.2",
|
||||||
|
"@vue-office/excel": "^1.7.11",
|
||||||
|
"@vue/composition-api": "^1.7.2",
|
||||||
"ant-design-vue": "^1.6.5",
|
"ant-design-vue": "^1.6.5",
|
||||||
"clipboard": "^2.0.6",
|
"clipboard": "^2.0.6",
|
||||||
"cropperjs": "^1.5.6",
|
"cropperjs": "^1.5.6",
|
||||||
@ -52,6 +55,7 @@
|
|||||||
"vditor": "3.10.4",
|
"vditor": "3.10.4",
|
||||||
"vue-aplayer": "^1.6.1",
|
"vue-aplayer": "^1.6.1",
|
||||||
"vue-color": "^2.8.1",
|
"vue-color": "^2.8.1",
|
||||||
|
"vue-demi": "^0.14.6",
|
||||||
"vue-runtime-helpers": "^1.1.2",
|
"vue-runtime-helpers": "^1.1.2",
|
||||||
"vue-simple-uploader": "0.7.6",
|
"vue-simple-uploader": "0.7.6",
|
||||||
"vuedraggable": "^2.23.2",
|
"vuedraggable": "^2.23.2",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
1
public/resource/font_2024484_yd6mpe5qfy.js
Normal file
1
public/resource/font_2024484_yd6mpe5qfy.js
Normal file
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { Icon } from 'ant-design-vue'
|
import { Icon } from 'ant-design-vue'
|
||||||
const IconFont = Icon.createFromIconfontCN({
|
const IconFont = Icon.createFromIconfontCN({
|
||||||
scriptUrl: document.location.protocol + '/resource/font_2024484_jfax4gppvg.js'
|
scriptUrl: document.location.protocol + '/resource/font_2024484_yd6mpe5qfy.js'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表
|
// 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表
|
||||||
|
|||||||
@ -93,7 +93,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else-if="(item.contentType && item.contentType.startsWith('image')) || item.showCover">
|
<div v-else-if="(item.contentType && item.contentType.startsWith('image')) || item.showCover">
|
||||||
<el-image v-if="grid || grid === 'details'" :style="{'height':details?'110px':(gridWidth-35) + 'px'}"
|
<el-image v-if="grid || grid === 'details'" :style="{'height':details?'110px':(gridWidth-35) + 'px'}"
|
||||||
fit="contain" :src="item.fileId ? (imageUrl+item.fileId) : (imageUrl+item.id)">
|
fit="contain" :src="item.fileId ? (imageUrl+item.fileId) : (imageUrl+item.id)" :class="item.showCover ? 'cover' : ''">
|
||||||
<div slot="error" class="image-slot-error">
|
<div slot="error" class="image-slot-error">
|
||||||
<svg-icon icon-class="image"/>
|
<svg-icon icon-class="image"/>
|
||||||
</div>
|
</div>
|
||||||
@ -309,5 +309,8 @@ export default {
|
|||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
}
|
}
|
||||||
|
>>> .el-image.cover {
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -603,7 +603,7 @@
|
|||||||
:status.sync="iframePreviewVisible"
|
:status.sync="iframePreviewVisible"
|
||||||
></iframe-preview>
|
></iframe-preview>
|
||||||
|
|
||||||
<file-details :audio-cover-url="audioCoverUrl" :image-url="imageUrl" :row-context-data="rowContextData" :visible.sync="drawer"></file-details>
|
<file-details :audio-cover-url="audioCoverUrl" :image-url="imageUrl" :file="rowContextData" :visible.sync="drawer" @openFile="fileClick"></file-details>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
class="open-file-dialog"
|
class="open-file-dialog"
|
||||||
@ -1159,7 +1159,7 @@ export default {
|
|||||||
if (item.isFolder || !this.grid) {
|
if (item.isFolder || !this.grid) {
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
const singleLine = item.contentType && item.contentType.startsWith('image')
|
const singleLine = (item.contentType && item.contentType.startsWith('image')) || item.showCover
|
||||||
const gridFilenameLength = singleLine ? 14 : 32
|
const gridFilenameLength = singleLine ? 14 : 32
|
||||||
// 分离文件名和后缀
|
// 分离文件名和后缀
|
||||||
let parts = filename.split('.');
|
let parts = filename.split('.');
|
||||||
@ -1376,15 +1376,19 @@ export default {
|
|||||||
},
|
},
|
||||||
// 获取字符的长度。中文字符长度为2,其他字符长度为1
|
// 获取字符的长度。中文字符长度为2,其他字符长度为1
|
||||||
getCharLength(char) {
|
getCharLength(char) {
|
||||||
return this.isChineseChar(char) ? 2 : 1
|
//return this.isChineseChar(char) ? 2 : 1
|
||||||
|
// 简单判断字符长度:中文字符和全角字符长度为2,其他为1
|
||||||
|
if (this.isChineseChar(char)) {
|
||||||
|
return 2;
|
||||||
|
} else if (char === ' ') {
|
||||||
|
return 2; // 空格作为一个字符处理
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 获取有效长度。如果有后缀,则包括后缀和点的长度;否则是基础名称和后7位的长度
|
// 获取有效长度。如果有后缀,则包括后缀和点的长度;否则是基础名称和后7位的长度
|
||||||
getEffectiveLength(base, suffix) {
|
getEffectiveLength(base, suffix) {
|
||||||
let chineseLength = Array.from(base).reduce(
|
let chineseLength = Array.from(base).reduce((count, char) => count + this.getCharLength(char), 0)
|
||||||
(count, char) => count + this.getCharLength(char),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
return suffix ? chineseLength + suffix.length + 1 : chineseLength
|
return suffix ? chineseLength + suffix.length + 1 : chineseLength
|
||||||
},
|
},
|
||||||
checkCmdKey(event) {
|
checkCmdKey(event) {
|
||||||
@ -1397,9 +1401,13 @@ export default {
|
|||||||
const isCmd = this.checkCmdKey(event)
|
const isCmd = this.checkCmdKey(event)
|
||||||
const checkPreviewVisible = this.checkPreviewVisible()
|
const checkPreviewVisible = this.checkPreviewVisible()
|
||||||
// space
|
// space
|
||||||
if (keyCode === 32 && this.selectRowData.length > 0 && !this.drawer && !checkPreviewVisible) {
|
if (keyCode === 32 && this.selectRowData.length > 0 && !checkPreviewVisible) {
|
||||||
this.drawer = true
|
if (!this.drawer) {
|
||||||
this.drawerShowTime = Date.now()
|
this.drawer = true
|
||||||
|
this.drawerShowTime = Date.now()
|
||||||
|
} else {
|
||||||
|
this.drawer = false
|
||||||
|
}
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
@ -4206,6 +4214,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 点击文件或文件夹
|
// 点击文件或文件夹
|
||||||
fileClick(row, event) {
|
fileClick(row, event) {
|
||||||
|
this.drawer = false
|
||||||
if (this.queryFileType === 'trash') {
|
if (this.queryFileType === 'trash') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -4582,5 +4591,4 @@ export default {
|
|||||||
.mt-5 {
|
.mt-5 {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,16 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!--文件详细信息-->
|
<el-dialog :visible.sync="visible" class="details-content" :custom-class="officePreview ? 'dialog-office':''">
|
||||||
<!-- <el-drawer :title="rowContextData.name" :visible.sync="visible">-->
|
<div v-if="officePreview" class="office-preview">
|
||||||
<!-- -->
|
<vue-office-docx
|
||||||
<!-- </el-drawer>-->
|
v-if="file.suffix === 'docx' && visible"
|
||||||
<el-dialog :visible.sync="visible" width="420px">
|
:src="fleUrl"
|
||||||
<div class="drawer-icon">
|
@rendered="rendered"
|
||||||
|
/>
|
||||||
|
<vue-office-excel
|
||||||
|
v-if="file.suffix === 'xlsx' && visible"
|
||||||
|
:options="excelOptions"
|
||||||
|
:src="fleUrl"
|
||||||
|
@rendered="rendered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else class="drawer-icon">
|
||||||
|
<el-image v-if="file && file.showCover" fit="contain" :src="imageUrl + file.id + '&showCover=true'" class="cover">
|
||||||
|
<div slot="error" class="image-slot-error">
|
||||||
|
<svg-icon icon-class="image"/>
|
||||||
|
</div>
|
||||||
|
</el-image>
|
||||||
<icon-file
|
<icon-file
|
||||||
|
v-else
|
||||||
class="drawer-icon-font"
|
class="drawer-icon-font"
|
||||||
:grid="true"
|
:grid="true"
|
||||||
:details="true"
|
:details="true"
|
||||||
:item="rowContextData"
|
:item="file"
|
||||||
:image-url="imageUrl"
|
:image-url="imageUrl"
|
||||||
:audio-cover-url="audioCoverUrl"
|
:audio-cover-url="audioCoverUrl"
|
||||||
></icon-file>
|
></icon-file>
|
||||||
@ -26,7 +41,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<div style="text-align: right; margin: 0">
|
<div style="text-align: right; margin: 0">
|
||||||
<el-button size="mini" type="text" @click="cancelScan()">取消</el-button>
|
<el-button size="mini" type="text" @click="cancelScan()">取消</el-button>
|
||||||
<el-button type="primary" size="mini" @click="scanDirectory(rowContextData)">确定</el-button>
|
<el-button type="primary" size="mini" @click="scanDirectory(file)">确定</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-button slot="reference" id="scanDirectoryBtn-file" type="primary" size="small" :loading="syncLoading"><i class="el-icon-refresh"></i></el-button>
|
<el-button slot="reference" id="scanDirectoryBtn-file" type="primary" size="small" :loading="syncLoading"><i class="el-icon-refresh"></i></el-button>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
@ -36,57 +51,68 @@
|
|||||||
|
|
||||||
<el-scrollbar wrap-class="scrollbar-wrapper" class="details-form-list">
|
<el-scrollbar wrap-class="scrollbar-wrapper" class="details-form-list">
|
||||||
<el-form-item label="名称:">
|
<el-form-item label="名称:">
|
||||||
<span>{{ rowContextData.name }}</span>
|
<span>{{ file.name }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="类型:">
|
<el-form-item label="类型:">
|
||||||
<span>{{
|
<span>{{
|
||||||
rowContextData.isFolder ? '文件夹' : rowContextData.contentType
|
file.isFolder ? '文件夹' : file.contentType
|
||||||
}}</span>
|
}}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="rowContextData.music">
|
<div v-if="file.music">
|
||||||
<el-form-item label="🎵 歌手:">
|
<el-form-item label="🎵 歌手:">
|
||||||
<span>{{ rowContextData.music.singer }}</span>
|
<span>{{ file.music.singer }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="🎵 专辑:">
|
<el-form-item label="🎵 专辑:">
|
||||||
<span>{{ '《' + rowContextData.music.album + '》' }}</span>
|
<span>{{ '《' + file.music.album + '》' }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="🎵 歌名:">
|
<el-form-item label="🎵 歌名:">
|
||||||
<span>{{ '《' + rowContextData.music.songName + '》' }}</span>
|
<span>{{ '《' + file.music.songName + '》' }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-show="rowContextData.w && rowContextData.h"
|
v-show="file.w && file.h"
|
||||||
label="尺寸:"
|
label="尺寸:"
|
||||||
class="details-resolution"
|
class="details-resolution"
|
||||||
>
|
>
|
||||||
<span>{{ rowContextData.w + ' x ' + rowContextData.h }}</span>
|
<span>{{ file.w + ' x ' + file.h }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="大小:">
|
<el-form-item label="大小:">
|
||||||
<span> {{ formatSize(rowContextData.size) }}</span>
|
<span> {{ formatSize(file.size) }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="位置:" class="details-position">
|
<el-form-item label="位置:" class="details-position">
|
||||||
<a :href="'/?path=' + rowContextData.path + '&highlight=' + rowContextData.name">{{ rowContextData.path }}</a>
|
<a :href="'/?path=' + file.path + '&highlight=' + file.name">{{ file.path }}</a>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="创建时间:">
|
<el-form-item label="创建时间:">
|
||||||
<span>{{ rowContextData.uploadDate }}</span>
|
<span>{{ file.uploadDate }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="修改时间:">
|
<el-form-item label="修改时间:">
|
||||||
<span>{{ rowContextData.updateDate }}</span>
|
<span>{{ file.updateDate }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="rowContextData.exif" label="">
|
<el-form-item v-if="file.exif" label="">
|
||||||
<span style="white-space: break-spaces;">{{ formatExif(rowContextData.exif) }}</span>
|
<span style="white-space: break-spaces;">{{ formatExif(file.exif) }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="rowContextData.video" label="">
|
<el-form-item v-if="file.video" label="">
|
||||||
<span style="white-space: break-spaces;">{{ formatVideo(rowContextData.video) }}</span>
|
<span style="white-space: break-spaces;">{{ formatVideo(file.video) }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
<el-button v-if="allowOpenFile" type="primary" size="small" @click="openFile" class="open-file">打开文件</el-button>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// 引入VueOfficeDocx 组件
|
||||||
|
import VueOfficeDocx from '@vue-office/docx'
|
||||||
|
// 引入VueOfficeDocx 相关样式
|
||||||
|
import '@vue-office/docx/lib/index.css'
|
||||||
|
|
||||||
|
// 引入VueOfficeExcel 组件
|
||||||
|
import VueOfficeExcel from '@vue-office/excel'
|
||||||
|
// 引入VueOfficeExcel 相关样式
|
||||||
|
import '@vue-office/excel/lib/index.css'
|
||||||
|
|
||||||
|
import fileConfig from '@/utils/file-config'
|
||||||
import { formatSize } from '@/utils/number'
|
import { formatSize } from '@/utils/number'
|
||||||
import IconFile from '@/components/Icon/IconFile'
|
import IconFile from '@/components/Icon/IconFile'
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
@ -96,14 +122,16 @@ import settingApi from "@/api/setting-api";
|
|||||||
export default {
|
export default {
|
||||||
name: 'FileDetails',
|
name: 'FileDetails',
|
||||||
components: {
|
components: {
|
||||||
IconFile
|
IconFile,
|
||||||
|
VueOfficeDocx,
|
||||||
|
VueOfficeExcel
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
rowContextData: {
|
file: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
@ -122,12 +150,28 @@ export default {
|
|||||||
clickSync: false,
|
clickSync: false,
|
||||||
indexingPercent: 100,
|
indexingPercent: 100,
|
||||||
syncPercent: 100,
|
syncPercent: 100,
|
||||||
|
excelOptions: {
|
||||||
|
minColLength: 10,
|
||||||
|
minRowLength: 10,
|
||||||
|
widthOffset: 10,
|
||||||
|
heightOffset: 10,
|
||||||
|
excel: window.location.origin + fileConfig.previewUrl(this.$store.state.user.name, this.file, this.$store.getters.token)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['message']),
|
...mapState(['message']),
|
||||||
|
fleUrl() {
|
||||||
|
return window.location.origin + fileConfig.previewUrl(this.$store.state.user.name, this.file, this.$store.getters.token)
|
||||||
|
},
|
||||||
|
officePreview() {
|
||||||
|
return ['docx', 'xlsx'].includes(this.file.suffix) && this.file.size > 0 && this.file.size < 1024 * 1024 * 5
|
||||||
|
},
|
||||||
|
allowOpenFile() {
|
||||||
|
return (this.file.contentType.indexOf('office') > -1 || ['pdf', 'epub'].includes(this.file.suffix))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
message(msg) {
|
message(msg) {
|
||||||
@ -143,6 +187,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openFile() {
|
||||||
|
this.$emit('openFile', this.file)
|
||||||
|
},
|
||||||
|
rendered() {
|
||||||
|
console.log('rendered')
|
||||||
|
},
|
||||||
formatSize(size) {
|
formatSize(size) {
|
||||||
return formatSize(size)
|
return formatSize(size)
|
||||||
},
|
},
|
||||||
@ -204,7 +254,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.details-form {
|
.details-form {
|
||||||
padding: 20px 0;
|
padding-bottom: 20px;
|
||||||
|
width: 280px;
|
||||||
|
|
||||||
>>> .el-scrollbar__view {
|
>>> .el-scrollbar__view {
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
@ -254,8 +305,14 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.drawer-icon {
|
.drawer-icon {
|
||||||
|
margin-right: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
>>> .icon-favorite {
|
>>> .icon-favorite {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -267,7 +324,52 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-icon-font >>> .svg-icon {
|
.drawer-icon-font {
|
||||||
font-size: 8rem;
|
margin-bottom: 40px;
|
||||||
|
>>> .svg-icon {
|
||||||
|
font-size: 8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.details-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
>>> .el-dialog__body {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>> .el-image {
|
||||||
|
height: 200px !important;
|
||||||
|
}
|
||||||
|
>>> .el-image.cover {
|
||||||
|
height: unset !important;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .el-dialog {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
width: fit-content;
|
||||||
|
min-width: 500px;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .dialog-office {
|
||||||
|
max-width: 1400px;
|
||||||
|
min-width: 1225px;
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.office-preview {
|
||||||
|
flex: 20;
|
||||||
|
height: 80vh;
|
||||||
|
margin-right: 20px;
|
||||||
|
>>> .docx-wrapper {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-file {
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -91,6 +91,8 @@ iconClass.set('plist','file-plist')
|
|||||||
iconClass.set('iso','file-iso')
|
iconClass.set('iso','file-iso')
|
||||||
iconClass.set('glb','file-glb')
|
iconClass.set('glb','file-glb')
|
||||||
iconClass.set('gltf','file-glb')
|
iconClass.set('gltf','file-glb')
|
||||||
|
iconClass.set('epub','epub')
|
||||||
|
iconClass.set('dwg','dwg')
|
||||||
|
|
||||||
export function findIconClass(file){
|
export function findIconClass(file){
|
||||||
if(!file){
|
if(!file){
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user