Remember table sort order when switching pages

This commit is contained in:
Natsumi
2025-10-22 17:45:25 +11:00
parent 9547297a09
commit 8a58c25084
4 changed files with 51 additions and 48 deletions
+10 -1
View File
@@ -74,11 +74,13 @@
emits: [
'update:currentPage',
'update:pageSize',
'update:tableProps',
'size-change',
'current-change',
'selection-change',
'row-click',
'filtered-data'
'filtered-data',
'sort-change'
],
setup(props, { emit }) {
const appearanceSettingsStore = useAppearanceSettingsStore();
@@ -180,7 +182,14 @@
});
const handleSortChange = ({ prop, order }) => {
if (props.tableProps.defaultSort) {
const { tableProps } = props;
tableProps.defaultSort.prop = prop;
tableProps.defaultSort.order = order;
emit('update:tableProps', tableProps);
}
sortData.value = { prop, order };
emit('sort-change', sortData.value);
};
const handleSelectionChange = (selection) => {
+1
View File
@@ -45,6 +45,7 @@ export async function initSentry(app) {
const error = hint.originalException;
if (error && typeof error.message === 'string') {
if (
error.message.includes('401') ||
error.message.includes('403') ||
error.message.includes('404') ||
error.message.includes('500') ||
+30 -7
View File
@@ -12,11 +12,35 @@ export const useModerationStore = defineStore('Moderation', () => {
const cachedPlayerModerations = ref(new Map());
const cachedPlayerModerationsUserIds = ref(new Set());
const isPlayerModerationsLoading = ref(false);
const playerModerationTable = ref({
data: [],
search: '',
loading: false,
filters: [
{
prop: 'type',
value: []
},
{
prop: ['sourceDisplayName', 'targetDisplayName'],
value: ''
}
],
tableProps: {
stripe: true,
size: 'small',
defaultSort: {
prop: 'created',
order: 'descending'
}
},
pageSize: 15,
pageSizeLinked: true
pageSizeLinked: true,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
watch(
@@ -24,7 +48,7 @@ export const useModerationStore = defineStore('Moderation', () => {
(isLoggedIn) => {
cachedPlayerModerations.value.clear();
cachedPlayerModerationsUserIds.value.clear();
isPlayerModerationsLoading.value = false;
playerModerationTable.value.loading = false;
playerModerationTable.value.data = [];
if (isLoggedIn) {
refreshPlayerModerations();
@@ -168,17 +192,17 @@ export const useModerationStore = defineStore('Moderation', () => {
}
async function refreshPlayerModerations() {
if (isPlayerModerationsLoading.value) {
if (playerModerationTable.value.loading) {
return;
}
isPlayerModerationsLoading.value = true;
playerModerationTable.value.loading = true;
expirePlayerModerations();
Promise.all([
playerModerationRequest.getPlayerModerations(),
avatarModerationRequest.getAvatarModerations()
])
.finally(() => {
isPlayerModerationsLoading.value = false;
playerModerationTable.value.loading = false;
})
.then((res) => {
// TODO: compare with cachedAvatarModerations
@@ -244,7 +268,6 @@ export const useModerationStore = defineStore('Moderation', () => {
return {
cachedPlayerModerations,
cachedPlayerModerationsUserIds,
isPlayerModerationsLoading,
playerModerationTable,
refreshPlayerModerations,
+10 -40
View File
@@ -3,7 +3,7 @@
<!-- 工具栏 -->
<div class="tool-slot">
<el-select
v-model="filters[0].value"
v-model="playerModerationTable.filters[0].value"
@change="saveTableFilters()"
multiple
clearable
@@ -16,26 +16,20 @@
:value="item" />
</el-select>
<el-input
v-model="filters[1].value"
v-model="playerModerationTable.filters[1].value"
:placeholder="t('view.moderation.search_placeholder')"
class="filter-input" />
<el-tooltip placement="bottom" :content="t('view.moderation.refresh_tooltip')">
<el-button
type="default"
:loading="isPlayerModerationsLoading"
:loading="playerModerationTable.loading"
@click="refreshPlayerModerations()"
:icon="Refresh"
circle />
</el-tooltip>
</div>
<DataTable
:data="playerModerationTable.data"
:pageSize="playerModerationTable.pageSize"
:filters="filters"
:tableProps="tableProps"
:paginationProps="paginationProps"
v-loading="isPlayerModerationsLoading">
<DataTable v-bind="playerModerationTable">
<el-table-column :label="t('table.moderation.date')" prop="created" :sortable="true" width="130">
<template #default="scope">
<el-tooltip placement="right">
@@ -93,7 +87,6 @@
<script setup>
import { Close, Refresh } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus';
import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
@@ -106,39 +99,13 @@
const { t } = useI18n();
const { showUserDialog } = useUserStore();
const { isPlayerModerationsLoading, playerModerationTable } = storeToRefs(useModerationStore());
const { playerModerationTable } = storeToRefs(useModerationStore());
const { refreshPlayerModerations, handlePlayerModerationDelete } = useModerationStore();
const { shiftHeld } = storeToRefs(useUiStore());
const { currentUser } = storeToRefs(useUserStore());
const filters = ref([
{
prop: 'type',
value: []
},
{
prop: ['sourceDisplayName', 'targetDisplayName'],
value: ''
}
]);
const tableProps = ref({
stripe: true,
size: 'small',
defaultSort: {
prop: 'created',
order: 'descending'
}
});
const paginationProps = ref({
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
});
async function init() {
filters.value[0].value = JSON.parse(
playerModerationTable.value.filters[0].value = JSON.parse(
await configRepository.getString('VRCX_playerModerationTableFilters', '[]')
);
}
@@ -146,7 +113,10 @@
init();
function saveTableFilters() {
configRepository.setString('VRCX_playerModerationTableFilters', JSON.stringify(filters.value[0].value));
configRepository.setString(
'VRCX_playerModerationTableFilters',
JSON.stringify(playerModerationTable.value.filters[0].value)
);
}
async function deletePlayerModeration(row) {