perf: 优化排序操作

This commit is contained in:
jmal 2025-07-18 17:31:44 +08:00
parent f05ce8d18b
commit e694604d35
3 changed files with 214 additions and 76 deletions

View File

@ -259,44 +259,45 @@
</template>
</el-autocomplete>
<el-dropdown size="medium" style="height: 40px;" @command="contextmenuClick" >
<div>
<el-button round type="text" class="sort">
<svg-icon
v-if="sortable.order === 'descending'"
icon-class="sort-amount-down-solid"
/>
<svg-icon v-else icon-class="sort-amount-up-alt-solid" />
<span class="sort-name">{{ sortName }}</span>
</el-button>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="orderName">
<span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'name' }" >
<i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>
<span>名称</span>
</span>
</el-dropdown-item>
<el-dropdown-item command="orderSize">
<span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'size' }" >
<i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>
<span>大小</span>
</span>
</el-dropdown-item>
<el-dropdown-item command="orderUploadDate">
<span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'uploadDate' }" >
<i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>
<span>上传时间</span>
</span>
</el-dropdown-item>
<el-dropdown-item command="orderUpdateDate">
<span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'updateDate', }">
<i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending'}"></i>
<span>修改时间</span>
</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<sort-dropdown :sortable="sortable" @sort-change="handleSortChange" />
<!-- <el-dropdown size="medium" style="height: 40px;" @command="handleSortChange" >-->
<!-- <div>-->
<!-- <el-button round type="text" class="sort">-->
<!-- <svg-icon-->
<!-- v-if="sortable.order === 'descending'"-->
<!-- icon-class="sort-amount-down-solid"-->
<!-- />-->
<!-- <svg-icon v-else icon-class="sort-amount-up-alt-solid" />-->
<!-- <span class="sort-name">{{ sortName }}</span>-->
<!-- </el-button>-->
<!-- </div>-->
<!-- <el-dropdown-menu slot="dropdown">-->
<!-- <el-dropdown-item command="orderName">-->
<!-- <span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'name' }" >-->
<!-- <i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>-->
<!-- <span>名称</span>-->
<!-- </span>-->
<!-- </el-dropdown-item>-->
<!-- <el-dropdown-item command="orderSize">-->
<!-- <span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'size' }" >-->
<!-- <i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>-->
<!-- <span>大小</span>-->
<!-- </span>-->
<!-- </el-dropdown-item>-->
<!-- <el-dropdown-item command="orderUploadDate">-->
<!-- <span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'uploadDate' }" >-->
<!-- <i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>-->
<!-- <span>上传时间</span>-->
<!-- </span>-->
<!-- </el-dropdown-item>-->
<!-- <el-dropdown-item command="orderUpdateDate">-->
<!-- <span :class="{ 'al-file-sort-item': true, active: sortable.prop === 'updateDate', }">-->
<!-- <i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending'}"></i>-->
<!-- <span>修改时间</span>-->
<!-- </span>-->
<!-- </el-dropdown-item>-->
<!-- </el-dropdown-menu>-->
<!-- </el-dropdown>-->
<el-button round type="text" class="vmode" @click="changeVmode">
<svg-icon :icon-class="grid ? 'list' : 'grid'" />
</el-button>
@ -824,6 +825,7 @@ import SearchOption from '@/components/SearchOption/index.vue'
import ShareDialog from '@/components/ShareDialog/index.vue'
import DialogFileList from '@/components/ShowFile/DialogFileList.vue'
import FileClipboard from '@/components/ShowFile/FileClipboard.vue'
import SortDropdown from '@/components/SortDropdown/index.vue'
import TagDialog from '@/components/TagDialog/index.vue'
import FileContextmenu from '@/components/VContextmenu/file-contextmenu.vue'
import store from '@/store'
@ -844,6 +846,7 @@ import { mapGetters, mapState } from 'vuex'
export default {
name: 'ShowFile',
components: {
SortDropdown,
DirectLinkDialog,
FileContextmenu,
FileClipboard,
@ -2793,13 +2796,6 @@ export default {
child[0].iconClass = 'menu-point'
child[1].iconClass = 'menu-empty'
}
if (child[2]) {
if (localStorage.getItem('showFolderSize') === '1') {
child[2].iconClass = 'duigou'
} else {
child[2].iconClass = 'menu-empty'
}
}
}
if (arrangementModeIndex > -1) {
const child = this.contextMenus[arrangementModeIndex].child
@ -2808,8 +2804,9 @@ export default {
const orderProp = item.orderProp
if (orderProp === prop) {
child.map(item => {
if (orderProp === item.orderProp) {
if (orderProp === item.orderProp && this.sortable.order === item.order) {
item.iconClass = 'menu-' + this.sortable.order
console.log('当前排序:', item.order)
} else {
item.iconClass = 'menu-null'
}
@ -2974,7 +2971,6 @@ export default {
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,
@ -3025,7 +3021,6 @@ export default {
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize,
folder: this.$route.query.folder,
showFolderSize: localStorage.getItem('showFolderSize'),
})
.then(res => {
this.loadData(res, onLoad)
@ -3046,7 +3041,6 @@ export default {
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize,
folder: this.$route.query.folder,
showFolderSize: localStorage.getItem('showFolderSize'),
})
.then(res => {
this.loadData(res, onLoad)
@ -3088,7 +3082,6 @@ export default {
queryCondition: this.queryCondition,
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize,
showFolderSize: localStorage.getItem('showFolderSize'),
})
.then(res => {
this.loadData(res, onLoad)
@ -3167,7 +3160,7 @@ export default {
}
})
// 重新加上排序高亮
let order = this.sortable.order === 'ascending' ? 'descending' : 'ascending'
let order = this.sortable.order
if (headerIndex > -1) {
this.addClass(tableHeader.children[headerIndex], order)
}
@ -3678,27 +3671,9 @@ export default {
}, 100)
this.cellMouseIndex = -1
},
// 全局右键菜单操作
contextmenuClick(operation) {
this.$refs.fileListTable.clearSelection()
switch (operation) {
case 'vmode-list':
this.grid = true
this.changeVmode()
break
case 'vmode-grid':
this.grid = false
this.changeVmode()
break
case 'show-folder-size':
const showFolderSize = localStorage.getItem('showFolderSize')
if (showFolderSize === '1') {
localStorage.setItem('showFolderSize', '0')
} else {
localStorage.setItem('showFolderSize', '1')
}
this.getFileListEnter()
break
handleSortChange(command, order) {
this.sortable.order = order
switch (command) {
case 'orderName':
this.sortChangeOfMenu('name', 1)
break
@ -3711,6 +3686,25 @@ export default {
case 'orderUploadDate':
this.sortChangeOfMenu('uploadDate', -1)
break
}
},
// 全局右键菜单操作
contextmenuClick(operation) {
this.$refs.fileListTable.clearSelection()
if (operation.startsWith('order')) {
const [prop, order] = operation.split('-')
this.handleSortChange(prop, order)
return
}
switch (operation) {
case 'vmode-list':
this.grid = true
this.changeVmode()
break
case 'vmode-grid':
this.grid = false
this.changeVmode()
break
case 'refresh':
this.getFileListEnter()
break

View File

@ -0,0 +1,137 @@
<template>
<el-dropdown
size="medium"
style="height: 40px;"
@command="handleCommand"
>
<div>
<el-button round type="text" class="sort">
<svg-icon
v-if="currentSortOrder === 'descending'"
icon-class="sort-amount-down-solid"
/>
<svg-icon v-else icon-class="sort-amount-up-alt-solid" />
<span class="sort-name">{{ currentSortName }}</span>
</el-button>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item in allSortOptions"
:key="item.key"
:command="item.command"
:divided="item.order === 'ascending' && item.key !== 'name-asc'"
>
<span :class="{ 'al-file-sort-item': true, active: sortable.prop === item.prop && sortable.order === item.order }">
<i :class="{ 'al-file-sort-item-icon': true, 'el-icon-top': sortable.order === 'ascending', 'el-icon-bottom': sortable.order === 'descending' }" ></i>
<span>{{ item.label }}</span>
</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
name: 'SortDropdown',
props: {
// 当前排序状态
sortable: {
type: Object,
required: true,
validator(value) {
return value && typeof value.prop === 'string' && typeof value.order === 'string'
}
},
// 排序选项配置
sortOptions: {
type: Array,
default: () => [
{ command: 'orderName', prop: 'name', title: '名称' },
{ command: 'orderSize', prop: 'size', title: '大小' },
{ command: 'orderUploadDate', prop: 'uploadDate', title: '上传时间' },
{ command: 'orderUpdateDate', prop: 'updateDate', title: '修改时间' }
]
}
},
computed: {
// 生成完整的排序选项(包含顺序和倒序)
allSortOptions() {
const options = []
this.sortOptions.forEach(option => {
// 顺序选项
options.push({
key: `${option.prop}-asc`,
command: `${option.command}-ascending`,
prop: option.prop,
order: 'ascending',
title: option.title,
label: `${option.title} - 顺序`
})
// 倒序选项
options.push({
key: `${option.prop}-desc`,
command: `${option.command}-descending`,
prop: option.prop,
order: 'descending',
title: option.title,
label: `${option.title} - 倒序`
})
})
return options
},
// 当前排序字段的显示名称
currentSortName() {
const currentOption = this.sortOptions.find(option => option.prop === this.sortable.prop)
return currentOption.title
},
// 当前排序方向
currentSortOrder() {
return this.sortable.order
}
},
methods: {
handleCommand(command) {
const [prop, order] = command.split('-')
// 向父组件发送排序数据
this.$emit('sort-change', prop, order)
}
}
}
</script>
<style scoped>
.sort {
display: flex;
align-items: center;
gap: 4px;
}
.sort-name {
margin-left: 4px;
}
.al-file-sort-item {
display: flex;
align-items: center;
width: 100%;
}
.al-file-sort-item.active {
color: #409eff;
font-weight: bold;
}
.al-file-sort-item-icon {
margin-right: 8px;
width: 14px;
height: 14px;
flex-shrink: 0;
}
/* 确保图标和文字垂直对齐 */
.al-file-sort-item-icon /deep/ svg {
width: 14px;
height: 14px;
vertical-align: middle;
}
</style>

View File

@ -20,10 +20,17 @@ export const directLinkSubMenus = [
]
export const fileArrangements = [
{ label: '名称', operation: 'orderName', orderProp: 'name'},
{ label: '大小', operation: 'orderSize', orderProp: 'size'},
{ label: '上传时间', operation: 'orderUploadDate', orderProp: 'uploadDate'},
{ label: '修改时间', operation: 'orderUpdateDate', orderProp: 'updateDate'},
{ label: '名称 - 顺序', operation: 'orderName-ascending', orderProp: 'name', order: 'ascending'},
{ label: '名称 - 倒序', operation: 'orderName-descending', orderProp: 'name', order: 'descending'},
{ divider: true, operation: 'divider' },
{ label: '大小 - 顺序', operation: 'orderSize-ascending', orderProp: 'size', order: 'ascending'},
{ label: '大小 - 倒序', operation: 'orderSize-descending', orderProp: 'size', order: 'descending'},
{ divider: true, operation: 'divider' },
{ label: '上传时间 - 顺序', operation: 'orderUploadDate-ascending', orderProp: 'uploadDate', order: 'ascending'},
{ label: '上传时间 - 倒序', operation: 'orderUploadDate-descending', orderProp: 'uploadDate', order: 'ascending'},
{ divider: true, operation: 'divider' },
{ label: '修改时间 - 顺序', operation: 'orderUpdateDate-ascending', orderProp: 'updateDate', order: 'ascending'},
{ label: '修改时间 - 倒序', operation: 'orderUpdateDate-descending', orderProp: 'updateDate', order: 'ascending'},
]
export const createFiles = [