Merge pull request #248 from jamebal/search
feat: 新增空格键快速预览docx和excel文件
This commit is contained in:
commit
7ea4691823
@ -15,6 +15,9 @@
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
|
||||
},
|
||||
"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",
|
||||
"clipboard": "^2.0.6",
|
||||
"cropperjs": "^1.5.6",
|
||||
@ -52,6 +55,7 @@
|
||||
"vditor": "3.10.4",
|
||||
"vue-aplayer": "^1.6.1",
|
||||
"vue-color": "^2.8.1",
|
||||
"vue-demi": "^0.14.6",
|
||||
"vue-runtime-helpers": "^1.1.2",
|
||||
"vue-simple-uploader": "0.7.6",
|
||||
"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'
|
||||
const IconFont = Icon.createFromIconfontCN({
|
||||
scriptUrl: document.location.protocol + '/resource/font_2024484_jfax4gppvg.js'
|
||||
scriptUrl: document.location.protocol + '/resource/font_2024484_yd6mpe5qfy.js'
|
||||
})
|
||||
|
||||
// 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表
|
||||
|
||||
@ -91,9 +91,9 @@
|
||||
</div>
|
||||
<svg-icon v-else icon-class="audio"/>
|
||||
</div>
|
||||
<div v-else-if="item.contentType && item.contentType.startsWith('image')">
|
||||
<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'}"
|
||||
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">
|
||||
<svg-icon icon-class="image"/>
|
||||
</div>
|
||||
@ -309,5 +309,8 @@ export default {
|
||||
padding: 0 2px;
|
||||
line-height: 12px;
|
||||
}
|
||||
>>> .el-image.cover {
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -603,7 +603,7 @@
|
||||
:status.sync="iframePreviewVisible"
|
||||
></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
|
||||
class="open-file-dialog"
|
||||
@ -1159,7 +1159,7 @@ export default {
|
||||
if (item.isFolder || !this.grid) {
|
||||
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
|
||||
// 分离文件名和后缀
|
||||
let parts = filename.split('.');
|
||||
@ -1376,15 +1376,19 @@ export default {
|
||||
},
|
||||
// 获取字符的长度。中文字符长度为2,其他字符长度为1
|
||||
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位的长度
|
||||
getEffectiveLength(base, suffix) {
|
||||
let chineseLength = Array.from(base).reduce(
|
||||
(count, char) => count + this.getCharLength(char),
|
||||
0
|
||||
)
|
||||
|
||||
let chineseLength = Array.from(base).reduce((count, char) => count + this.getCharLength(char), 0)
|
||||
return suffix ? chineseLength + suffix.length + 1 : chineseLength
|
||||
},
|
||||
checkCmdKey(event) {
|
||||
@ -1397,9 +1401,13 @@ export default {
|
||||
const isCmd = this.checkCmdKey(event)
|
||||
const checkPreviewVisible = this.checkPreviewVisible()
|
||||
// space
|
||||
if (keyCode === 32 && this.selectRowData.length > 0 && !this.drawer && !checkPreviewVisible) {
|
||||
this.drawer = true
|
||||
this.drawerShowTime = Date.now()
|
||||
if (keyCode === 32 && this.selectRowData.length > 0 && !checkPreviewVisible) {
|
||||
if (!this.drawer) {
|
||||
this.drawer = true
|
||||
this.drawerShowTime = Date.now()
|
||||
} else {
|
||||
this.drawer = false
|
||||
}
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
@ -4206,6 +4214,7 @@ export default {
|
||||
},
|
||||
// 点击文件或文件夹
|
||||
fileClick(row, event) {
|
||||
this.drawer = false
|
||||
if (this.queryFileType === 'trash') {
|
||||
return
|
||||
}
|
||||
@ -4582,5 +4591,4 @@ export default {
|
||||
.mt-5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -1,16 +1,31 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--文件详细信息-->
|
||||
<!-- <el-drawer :title="rowContextData.name" :visible.sync="visible">-->
|
||||
<!-- -->
|
||||
<!-- </el-drawer>-->
|
||||
<el-dialog :visible.sync="visible" width="420px">
|
||||
<div class="drawer-icon">
|
||||
<el-dialog :visible.sync="visible" class="details-content" :custom-class="officePreview ? 'dialog-office':''">
|
||||
<div v-if="officePreview" class="office-preview">
|
||||
<vue-office-docx
|
||||
v-if="file.suffix === 'docx' && visible"
|
||||
:src="fleUrl"
|
||||
@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
|
||||
v-else
|
||||
class="drawer-icon-font"
|
||||
:grid="true"
|
||||
:details="true"
|
||||
:item="rowContextData"
|
||||
:item="file"
|
||||
:image-url="imageUrl"
|
||||
:audio-cover-url="audioCoverUrl"
|
||||
></icon-file>
|
||||
@ -26,7 +41,7 @@
|
||||
</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<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>
|
||||
<el-button slot="reference" id="scanDirectoryBtn-file" type="primary" size="small" :loading="syncLoading"><i class="el-icon-refresh"></i></el-button>
|
||||
</el-popover>
|
||||
@ -36,57 +51,68 @@
|
||||
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper" class="details-form-list">
|
||||
<el-form-item label="名称:">
|
||||
<span>{{ rowContextData.name }}</span>
|
||||
<span>{{ file.name }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型:">
|
||||
<span>{{
|
||||
rowContextData.isFolder ? '文件夹' : rowContextData.contentType
|
||||
file.isFolder ? '文件夹' : file.contentType
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
<div v-if="rowContextData.music">
|
||||
<div v-if="file.music">
|
||||
<el-form-item label="🎵 歌手:">
|
||||
<span>{{ rowContextData.music.singer }}</span>
|
||||
<span>{{ file.music.singer }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="🎵 专辑:">
|
||||
<span>{{ '《' + rowContextData.music.album + '》' }}</span>
|
||||
<span>{{ '《' + file.music.album + '》' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="🎵 歌名:">
|
||||
<span>{{ '《' + rowContextData.music.songName + '》' }}</span>
|
||||
<span>{{ '《' + file.music.songName + '》' }}</span>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item
|
||||
v-show="rowContextData.w && rowContextData.h"
|
||||
v-show="file.w && file.h"
|
||||
label="尺寸:"
|
||||
class="details-resolution"
|
||||
>
|
||||
<span>{{ rowContextData.w + ' x ' + rowContextData.h }}</span>
|
||||
<span>{{ file.w + ' x ' + file.h }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="大小:">
|
||||
<span> {{ formatSize(rowContextData.size) }}</span>
|
||||
<span> {{ formatSize(file.size) }}</span>
|
||||
</el-form-item>
|
||||
<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 label="创建时间:">
|
||||
<span>{{ rowContextData.uploadDate }}</span>
|
||||
<span>{{ file.uploadDate }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="修改时间:">
|
||||
<span>{{ rowContextData.updateDate }}</span>
|
||||
<span>{{ file.updateDate }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="rowContextData.exif" label="">
|
||||
<span style="white-space: break-spaces;">{{ formatExif(rowContextData.exif) }}</span>
|
||||
<el-form-item v-if="file.exif" label="">
|
||||
<span style="white-space: break-spaces;">{{ formatExif(file.exif) }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="rowContextData.video" label="">
|
||||
<span style="white-space: break-spaces;">{{ formatVideo(rowContextData.video) }}</span>
|
||||
<el-form-item v-if="file.video" label="">
|
||||
<span style="white-space: break-spaces;">{{ formatVideo(file.video) }}</span>
|
||||
</el-form-item>
|
||||
</el-scrollbar>
|
||||
|
||||
<el-button v-if="allowOpenFile" type="primary" size="small" @click="openFile" class="open-file">打开文件</el-button>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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 IconFile from '@/components/Icon/IconFile'
|
||||
import {mapState} from "vuex";
|
||||
@ -96,14 +122,16 @@ import settingApi from "@/api/setting-api";
|
||||
export default {
|
||||
name: 'FileDetails',
|
||||
components: {
|
||||
IconFile
|
||||
IconFile,
|
||||
VueOfficeDocx,
|
||||
VueOfficeExcel
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
rowContextData: {
|
||||
file: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
@ -122,12 +150,28 @@ export default {
|
||||
clickSync: false,
|
||||
indexingPercent: 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() {
|
||||
},
|
||||
computed: {
|
||||
...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: {
|
||||
message(msg) {
|
||||
@ -143,6 +187,12 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openFile() {
|
||||
this.$emit('openFile', this.file)
|
||||
},
|
||||
rendered() {
|
||||
console.log('rendered')
|
||||
},
|
||||
formatSize(size) {
|
||||
return formatSize(size)
|
||||
},
|
||||
@ -204,7 +254,8 @@ export default {
|
||||
}
|
||||
|
||||
.details-form {
|
||||
padding: 20px 0;
|
||||
padding-bottom: 20px;
|
||||
width: 280px;
|
||||
|
||||
>>> .el-scrollbar__view {
|
||||
max-height: 50vh;
|
||||
@ -254,8 +305,14 @@ export default {
|
||||
}
|
||||
|
||||
.drawer-icon {
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
>>> .icon-favorite {
|
||||
display: none;
|
||||
}
|
||||
@ -267,7 +324,52 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-icon-font >>> .svg-icon {
|
||||
font-size: 8rem;
|
||||
.drawer-icon-font {
|
||||
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>
|
||||
|
||||
@ -91,6 +91,8 @@ iconClass.set('plist','file-plist')
|
||||
iconClass.set('iso','file-iso')
|
||||
iconClass.set('glb','file-glb')
|
||||
iconClass.set('gltf','file-glb')
|
||||
iconClass.set('epub','epub')
|
||||
iconClass.set('dwg','dwg')
|
||||
|
||||
export function findIconClass(file){
|
||||
if(!file){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user