This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-booster-ui.git
The following commit(s) were added to refs/heads/main by this push:
new 0334c28d refactor: Implement a common pagination component (#516)
0334c28d is described below
commit 0334c28da54680e12a785b7d7a1d5a062a64f132
Author: Fine0830 <[email protected]>
AuthorDate: Tue Jan 6 18:19:35 2026 +0800
refactor: Implement a common pagination component (#516)
---
src/store/modules/log.ts | 2 +-
src/views/alarm/Content.vue | 13 ++--
src/views/alarm/Header.vue | 27 +++-----
src/views/alarm/data.ts | 2 +
src/views/components/Pagination.vue | 100 +++++++++++++++++++++++++++++
src/views/dashboard/related/log/Header.vue | 6 +-
src/views/dashboard/related/log/List.vue | 30 +++------
7 files changed, 133 insertions(+), 47 deletions(-)
diff --git a/src/store/modules/log.ts b/src/store/modules/log.ts
index 50aa15ed..7febdae7 100644
--- a/src/store/modules/log.ts
+++ b/src/store/modules/log.ts
@@ -63,7 +63,7 @@ export const logStore = defineStore({
this.logs = [];
this.conditions = {
queryDuration: getDurationTime(),
- paging: { pageNum: 1, pageSize: 15 },
+ paging: { pageNum: 1, pageSize: PageSizeDefault },
};
},
setLogHeaderType(type: string) {
diff --git a/src/views/alarm/Content.vue b/src/views/alarm/Content.vue
index a8dafff5..15aafe3a 100644
--- a/src/views/alarm/Content.vue
+++ b/src/views/alarm/Content.vue
@@ -14,7 +14,7 @@ See the License for the specific language governing
permissions and
limitations under the License. -->
<template>
<div class="timeline-table clear" v-loading="alarmStore.loading">
- <div v-for="(i, index) in alarmStore.alarms" :key="index" class="clear
timeline-item">
+ <div v-for="(i, index) in displayAlarms" :key="index" class="clear
timeline-item">
<div class="g-sm-3 grey sm hide-xs time-line tr">
{{ dateFormat(parseInt(i.startTime)) }}
</div>
@@ -42,7 +42,7 @@ limitations under the License. -->
</div>
</div>
</div>
- <div v-if="!alarmStore.alarms.length" class="tips">{{ t("noData") }}</div>
+ <div v-if="!displayAlarms.length" class="tips">{{ t("noData") }}</div>
</div>
<el-dialog
v-model="isShowDetails"
@@ -125,11 +125,11 @@ limitations under the License. -->
</el-dialog>
</template>
<script lang="ts" setup>
- import { ref } from "vue";
+ import { ref, computed } from "vue";
import { useI18n } from "vue-i18n";
import type { Alarm, Event } from "@/types/alarm";
import { useAlarmStore } from "@/store/modules/alarm";
- import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from
"./data";
+ import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys,
PageSizeDefaultAlarm } from "./data";
import { dateFormat } from "@/utils/dateFormat";
import Snapshot from "./components/Snapshot.vue";
@@ -141,6 +141,11 @@ limitations under the License. -->
const alarmTags = ref<string[]>([]);
const currentEvents = ref<any[]>([]);
const currentEvent = ref<Event | any>({});
+ const pageSize = PageSizeDefaultAlarm;
+
+ const displayAlarms = computed(() =>
+ alarmStore.alarms.length >= pageSize ? alarmStore.alarms.slice(0, pageSize
- 1) : alarmStore.alarms,
+ );
function showDetails(item: Alarm) {
isShowDetails.value = true;
diff --git a/src/views/alarm/Header.vue b/src/views/alarm/Header.vue
index f32e4781..8f1cb0e6 100644
--- a/src/views/alarm/Header.vue
+++ b/src/views/alarm/Header.vue
@@ -41,19 +41,11 @@ limitations under the License. -->
/>
</div>
<div class="pagination">
- <el-pagination
- v-model="pageNum"
- :page-size="pageSize"
- layout="prev, pager, next"
- :total="total"
- @current-change="changePage"
- :pager-count="5"
- size="small"
- :style="
- appStore.theme === Themes.Light
- ? `--el-pagination-bg-color: #f0f2f5;
--el-pagination-button-disabled-bg-color: #f0f2f5;`
- : ''
- "
+ <Pagination
+ v-model:currentPage="pageNum"
+ :pageSize="pageSize"
+ :total="alarmStore.alarms.length"
+ @change="changePage"
/>
</div>
</div>
@@ -70,19 +62,19 @@ limitations under the License. -->
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
import ConditionTags from "@/views/components/ConditionTags.vue";
- import { AlarmOptions } from "./data";
+ import Pagination from "@/views/components/Pagination.vue";
+ import { AlarmOptions, PageSizeDefaultAlarm } from "./data";
import { useAppStoreWithOut, InitializationDurationRow } from
"@/store/modules/app";
import { useAlarmStore } from "@/store/modules/alarm";
import { useDuration } from "@/hooks/useDuration";
import timeFormat from "@/utils/timeFormat";
import type { DurationTime, Duration } from "@/types/app";
- import { Themes } from "@/constants/data";
/*global Indexable */
const appStore = useAppStoreWithOut();
const alarmStore = useAlarmStore();
const { t } = useI18n();
const { setDurationRow, getDurationTime, getMaxRange } = useDuration();
- const pageSize = 20;
+ const pageSize = PageSizeDefaultAlarm;
const entity = ref<string>("");
const keyword = ref<string>("");
const pageNum = ref<number>(1);
@@ -90,9 +82,6 @@ limitations under the License. -->
const durationRow = ref<Duration>(InitializationDurationRow);
const tagsMap = ref<{ key: string; value: string }[]>();
- const total = computed(() =>
- alarmStore.alarms.length === pageSize ? pageSize * pageNum.value + 1 :
pageSize * pageNum.value,
- );
const maxRange = computed(() =>
getMaxRange(appStore.coldStageMode ? appStore.recordsTTL?.coldNormal || 0
: appStore.recordsTTL?.normal || 0),
);
diff --git a/src/views/alarm/data.ts b/src/views/alarm/data.ts
index b53186a8..26c8844b 100644
--- a/src/views/alarm/data.ts
+++ b/src/views/alarm/data.ts
@@ -14,6 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+export const PageSizeDefaultAlarm = 21;
+
export const AlarmOptions = [
{ label: "All", value: "" },
{ label: "Service", value: "Service" },
diff --git a/src/views/components/Pagination.vue
b/src/views/components/Pagination.vue
new file mode 100644
index 00000000..8f771daa
--- /dev/null
+++ b/src/views/components/Pagination.vue
@@ -0,0 +1,100 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. -->
+<template>
+ <div class="pagination-container">
+ <el-pagination
+ v-model:current-page="currentPageModel"
+ :page-size="displayPageSize"
+ size="small"
+ layout="prev, pager, next"
+ :total="computedTotal"
+ :pager-count="pagerCount"
+ @current-change="handlePageChange"
+ :style="paginationStyle"
+ />
+ </div>
+</template>
+<script lang="ts" setup>
+ import { computed } from "vue";
+
+ /*global defineProps, defineEmits*/
+ const props = defineProps({
+ currentPage: {
+ type: Number,
+ default: 1,
+ },
+ pageSize: {
+ type: Number,
+ required: true,
+ },
+ total: {
+ type: Number,
+ required: true,
+ },
+ pagerCount: {
+ type: Number,
+ default: 5,
+ },
+ align: {
+ type: String as () => "left" | "center" | "right",
+ default: "right",
+ },
+ });
+
+ const emits = defineEmits<{
+ (e: "update:currentPage", page: number): void;
+ (e: "change", page: number): void;
+ }>();
+
+ // The display page size is pageSize - 1 because we fetch pageSize items
+ // but the last item is only used to check if there are more pages
+ const displayPageSize = computed(() => props.pageSize - 1);
+
+ // Calculate total for pagination display based on fetched items
+ // If we fetched pageSize items, there might be more pages
+ const computedTotal = computed(() => {
+ if (props.total >= props.pageSize) {
+ return displayPageSize.value * props.currentPage + 1;
+ }
+ return displayPageSize.value * props.currentPage;
+ });
+
+ const currentPageModel = computed({
+ get: () => props.currentPage,
+ set: (val: number) => emits("update:currentPage", val),
+ });
+
+ const paginationStyle = computed(() => {
+ const alignMap = {
+ left: "flex-start",
+ center: "center",
+ right: "flex-end",
+ };
+ return {
+ display: "flex",
+ justifyContent: alignMap[props.align],
+ };
+ });
+
+ function handlePageChange(page: number) {
+ emits("update:currentPage", page);
+ emits("change", page);
+ }
+</script>
+<style lang="scss" scoped>
+ .pagination-container {
+ margin: 5px 0;
+ }
+</style>
diff --git a/src/views/dashboard/related/log/Header.vue
b/src/views/dashboard/related/log/Header.vue
index c0a013be..158e7051 100644
--- a/src/views/dashboard/related/log/Header.vue
+++ b/src/views/dashboard/related/log/Header.vue
@@ -133,7 +133,7 @@ limitations under the License. -->
import type { PropType } from "vue";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
- import { useLogStore } from "@/store/modules/log";
+ import { useLogStore, PageSizeDefault } from "@/store/modules/log";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut, InitializationDurationRow } from
"@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors";
@@ -274,7 +274,7 @@ limitations under the License. -->
serviceId: selectorStore.currentService ?
selectorStore.currentService.id : state.service.id,
pagePathId: endpoint || state.endpoint.id || undefined,
serviceVersionId: instance || state.instance.id || undefined,
- paging: { pageNum: 1, pageSize: 15 },
+ paging: { pageNum: 1, pageSize: PageSizeDefault },
queryDuration: duration,
category: state.category.value,
});
@@ -292,7 +292,7 @@ limitations under the License. -->
keywordsOfContent: keywordsOfContent.value,
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
tags: tagsMap.value.length ? tagsMap.value : undefined,
- paging: { pageNum: 1, pageSize: 15 },
+ paging: { pageNum: 1, pageSize: PageSizeDefault },
relatedTrace: traceId.value ? { traceId: traceId.value, segmentId,
spanId } : undefined,
});
}
diff --git a/src/views/dashboard/related/log/List.vue
b/src/views/dashboard/related/log/List.vue
index 11eeb760..435b94a1 100644
--- a/src/views/dashboard/related/log/List.vue
+++ b/src/views/dashboard/related/log/List.vue
@@ -17,18 +17,12 @@ limitations under the License. -->
<LogTable v-loading="logStore.loadLogs" :tableData="displayLogs"
:type="type" :noLink="false" :data="data">
<div class="log-tips" v-if="!logStore.logs.length">{{ t("noData")
}}</div>
</LogTable>
- <div class="mt-5 mb-5">
- <el-pagination
- v-model="logStore.conditions.paging.pageNum"
- :page-size="pageSize - 1"
- size="small"
- layout="prev, pager, next"
- :total="total"
- :pager-count="5"
- @current-change="updatePage"
- :style="`float: right`"
- />
- </div>
+ <Pagination
+ v-model:currentPage="logStore.conditions.paging.pageNum"
+ :pageSize="pageSize"
+ :total="logStore.logs.length"
+ @change="updatePage"
+ />
</div>
</template>
<script lang="ts" setup>
@@ -37,6 +31,7 @@ limitations under the License. -->
import type { PropType } from "vue";
import type { LayoutConfig } from "@/types/dashboard";
import LogTable from "./LogTable/Index.vue";
+ import Pagination from "@/views/components/Pagination.vue";
import { useLogStore, PageSizeDefault } from "@/store/modules/log";
import { useDashboardStore } from "@/store/modules/dashboard";
import { ElMessage } from "element-plus";
@@ -54,18 +49,13 @@ limitations under the License. -->
const logStore = useLogStore();
const dashboardStore = useDashboardStore();
const type = ref<string>(dashboardStore.layerId === "BROWSER" ? "browser" :
"service");
- const pageSize = ref<number>(PageSizeDefault);
- const total = computed(() =>
- logStore.logs.length >= pageSize.value
- ? (pageSize.value - 1) * logStore.conditions.paging.pageNum + 1
- : (pageSize.value - 1) * logStore.conditions.paging.pageNum,
- );
+ const pageSize = PageSizeDefault;
const displayLogs = computed(() =>
- logStore.logs.length === pageSize.value ? logStore.logs.slice(0,
pageSize.value - 1) : logStore.logs,
+ logStore.logs.length === pageSize ? logStore.logs.slice(0, pageSize - 1) :
logStore.logs,
);
function updatePage(p: number) {
logStore.setLogCondition({
- paging: { pageNum: p, pageSize: pageSize.value },
+ paging: { pageNum: p, pageSize: pageSize },
});
queryLogs();
}