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();
   }

Reply via email to