feat: 新增搜索选项

This commit is contained in:
jmal 2025-04-10 14:32:26 +08:00
parent 69ca54add7
commit b129287d4f
2 changed files with 121 additions and 76 deletions

View File

@ -1,15 +1,10 @@
<template>
<el-dialog
:visible.sync="dialogVisible"
<div
v-show="dialogVisible"
:show-close="false"
custom-class="no-header-dialog"
class="file-search-dialog">
<!-- 关闭按钮 -->
<div class="dialog-close-btn">
<el-button type="text" icon="el-icon-close" @click="dialogVisible = false"></el-button>
</div>
<div class="search-bar">
<div class="search-input-wrapper">
<div class="search-filters">
@ -105,27 +100,37 @@
<!-- 搜索条件标签 -->
<div class="search-tags" v-if="hasSearchConditions">
<el-tag
v-if="fileTypeText !== '全部文件'"
closable
@close="resetFileType">
文件类型: {{ fileTypeText }}
</el-tag>
<el-tag
v-if="sizeRange[0] > 0 || sizeRange[1] < sliderConfig.max"
closable
@close="resetSizeRange">
文件大小: {{ formatSizeRange }}
</el-tag>
<el-tag
v-if="timeRange"
closable
@close="resetTimeRange">
时间范围: {{ formatTimeRange }}
</el-tag>
<div v-if="keyword !== ''">
<el-tag
closable
@close="resetKeyword">
关键字: {{ keyword }}
</el-tag>
</div>
<div v-if="fileTypeText !== '全部文件'">
<el-tag
closable
@close="resetFileType">
文件类型: {{ fileTypeText }}
</el-tag>
</div>
<div v-if="hasSizeRange">
<el-tag
closable
@close="resetSizeRange">
文件大小: {{ formatSizeRange }}
</el-tag>
</div>
<div v-if="timeRange">
<el-tag
closable
@close="resetTimeRange">
时间范围: {{ formatTimeRange }}
</el-tag>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
@ -136,13 +141,17 @@ export default {
type: Boolean,
default: false
},
keyword: {
type: String,
default: ''
}
},
data() {
return {
dialogVisible: false,
fileType: 'all',
timeRange: null,
sizeRange: [0, 1073741824], // 默认范围:0 到 1GB
sizeRange: [0, -1], // 默认范围:0 到 1GB
fileTypeText: '全部文件',
filterOption: {
type: null,
@ -155,8 +164,10 @@ export default {
},
computed: {
hasSearchConditions() {
return this.fileType !== 'all' || this.timeRange ||
(this.sizeRange[0] > 0 || this.sizeRange[1] < 1073741824)
return this.keyword || this.fileType !== 'all' || this.timeRange || this.hasSizeRange
},
hasSizeRange () {
return this.sizeRange[0] >= 0 && this.sizeRange[1] > 0
},
formatTimeRange() {
if (!this.timeRange) return ''
@ -172,7 +183,7 @@ export default {
return {
min: 1073741824,
max: 10737418240,
step: 1073741824 / 100 // 约10MB的步长
step: 20971520 // 20MB
}
} else {
// 普通模式 (0 - 1GB)
@ -197,10 +208,10 @@ export default {
updateFilterOption() {
this.filterOption = {
type: this.fileType === 'all' ? null : this.fileType,
modifyStart: this.timeRange ? this.timeRange[0] : null,
modifyEnd: this.timeRange ? this.timeRange[1] : null,
sizeMin: this.sizeRange[0],
sizeMax: this.sizeRange[1]
modifyStart: this.timeRange ? new Date(this.timeRange[0]).getTime() : null,
modifyEnd: this.timeRange ? new Date(this.timeRange[1]).getTime() : null,
sizeMin: this.hasSizeRange ? this.sizeRange[0] : null,
sizeMax: this.hasSizeRange ? this.sizeRange[1] : null
}
this.$emit('filter-change', this.filterOption)
@ -246,6 +257,12 @@ export default {
this.updateFilterOption()
},
resetKeyword() {
this.$emit('update:keyword', '')
this.$emit('update:visible', false)
this.updateFilterOption()
},
resetFileType() {
this.handleFileType('all')
},
@ -256,7 +273,7 @@ export default {
},
resetSizeRange() {
this.sizeRange = [0, 1073741824]
this.sizeRange = [-1, -1]
this.updateFilterOption()
},
@ -265,13 +282,10 @@ export default {
},
formatFileSize(size) {
const units = ['B', 'KB', 'MB', 'GB', 'TB']
let index = 0
while (size >= 1024 && index < units.length - 1) {
size /= 1024
index++
}
return `${size.toFixed(2)} ${units[index]}`
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
if (size === 0) return '0 B';
const i = Math.floor(Math.log(size) / Math.log(1024));
return `${(size / Math.pow(1024, i)).toFixed(2)} ${units[i]}`;
},
setTimePreset(preset) {
@ -324,6 +338,17 @@ export default {
<style lang="scss" scoped>
.file-search-dialog {
display: flex;
justify-content: center;
gap: 16px;
.search-bar {
display: flex;
align-content: center;
align-items: center;
}
>>> .el-dialog {
margin-top: 6vh !important;
border-radius: 12px;
@ -341,35 +366,10 @@ export default {
padding: 20px 24px;
}
.dialog-close-btn {
position: absolute;
right: -44px;
top: 0;
z-index: 100;
.el-button {
color: #fff;
font-size: 20px;
padding: 10px;
border-radius: 50%;
transition: all 0.3s ease;
&:hover {
color: #fff;
background-color: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
}
}
.search-input-wrapper {
display: flex;
justify-content: center;
}
.search-filters {
display: flex;
align-items: center;
flex-direction: column;
gap: 8px;
.el-divider--vertical {
@ -440,10 +440,11 @@ export default {
}
.search-tags {
margin: 16px 0;
display: flex;
justify-content: center;
flex-direction: column;
gap: 8px;
min-width: 250px;
>>> .el-tag {
border-radius: 6px;

View File

@ -161,7 +161,6 @@
ref="searchInput"
placeholder="搜索"
v-model="searchFileName"
@keyup.enter.native="searchFileEnter(searchFileName)"
@focus="setInputFocus"
@input="searchFileEnter(searchFileName)"
@ -169,9 +168,16 @@
@clear="searchFileEnter(searchFileName)"
>
<template v-slot:suffix>
<el-button type="text" class="search-option" @click="searchDialogVisible = true">
<i class="el-icon-s-operation"></i>
</el-button>
<el-popover
v-if="searchFileName"
placement="bottom-end"
popper-class="search-filter-popover"
trigger="click">
<search-dialog :visible.sync="searchDialogVisible" :keyword.sync="searchFileName" @filter-change="searchFilterChange"></search-dialog>
<el-button slot="reference" type="text" :class="searchOptionBtnClass" @click="searchDialogVisible = true">
<i class="el-icon-s-operation"></i>
</el-button>
</el-popover>
</template>
</el-input>
<el-dropdown
@ -821,8 +827,6 @@
</el-dialog>
<file-clipboard ref="fileClipboard" v-if="showClipboard && fileClipboard.length > 0" :file-list="fileClipboard" :image-url="imageUrl" :audio-cover-url="audioCoverUrl" :target-path="path" :target-folder="currentFolder" @onCopy="onCopy" @onMove="onMove"></file-clipboard>
<search-dialog :visible.sync="searchDialogVisible"></search-dialog>
</div>
</template>
@ -1157,6 +1161,8 @@ export default {
debounceSearch: null,// 搜索防抖
debounceGetFileList: null,// 获取文件列表防抖
searchDialogVisible: false,
filterOption: {}, // 搜索选项
hasSearchFilterOption: false, // 是否有搜索选项
fileUsername: '', // 一般用于挂载文件
}
},
@ -1177,6 +1183,13 @@ export default {
return '名称'
}
},
searchOptionBtnClass() {
if (this.hasSearchFilterOption) {
return 'search-option-btn search-option-btn-active'
} else {
return 'search-option-btn'
}
},
cmdKey() {
return navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'
},
@ -2920,10 +2933,15 @@ export default {
tagId: this.$route.query.tagId,
isFolder: this.queryCondition.isFolder,
isFavorite: this.queryCondition.isFavorite,
queryFileType: this.queryFileType,
queryFileType: this.filterOption.type || this.queryFileType,
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize,
showFolderSize: localStorage.getItem('showFolderSize'),
type: this.filterOption.type,
queryModifyStart: this.filterOption.modifyStart,
queryModifyEnd: this.filterOption.modifyEnd,
querySizeMin: this.filterOption.sizeMin,
querySizeMax: this.filterOption.sizeMax,
}).then(res => {
this.loadData(res, onLoad)
this.listModeSearch = true
@ -4457,6 +4475,22 @@ export default {
this.fileHandler = {}
this.specifyPreviewer = 'office'
},
searchFilterChange(filterOption) {
this.filterOption = filterOption
let hasSearchFilterOption = false
if (filterOption.type !== 'all' && filterOption.type !== null) {
hasSearchFilterOption = true
}
if (filterOption.modifyStart !== null && filterOption.modifyEnd !== null) {
hasSearchFilterOption = true
}
if (filterOption.sizeMin !== null && filterOption.sizeMax !== null) {
hasSearchFilterOption = true
}
this.hasSearchFilterOption = hasSearchFilterOption
this.debounceSearch(this.searchFileName, false)
},
checkPreviewVisible() {
if (this.searchDialogVisible) {
return true
@ -4723,4 +4757,14 @@ export default {
margin-top: 5px;
}
.search-option-btn {
padding: 8px;
}
.search-option-btn-active {
padding: 8px;
background: #409EFF;
color: #fff;
}
</style>