فهرست منبع

公告和新闻

yanghao 1 هفته پیش
والد
کامیت
37a8b24515
7فایلهای تغییر یافته به همراه645 افزوده شده و 54 حذف شده
  1. 1 0
      components.d.ts
  2. 5 1
      src/config/axios/service.ts
  3. 23 0
      src/router/index.ts
  4. 128 51
      src/views/index.vue
  5. 2 2
      src/views/login.vue
  6. 240 0
      src/views/news/index.vue
  7. 246 0
      src/views/notices/index.vue

+ 1 - 0
components.d.ts

@@ -21,6 +21,7 @@ declare module 'vue' {
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
     ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
     ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
+    ElEmpty: typeof import('element-plus/es')['ElEmpty']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']

+ 5 - 1
src/config/axios/service.ts

@@ -243,7 +243,11 @@ const handleAuthorized = () => {
         removeToken();
         isRelogin.show = false;
 
-        window.location.href = "/login";
+        if (ua.includes("dingtalk") || ua.includes("dingtalkwork")) {
+          window.location.href = "/";
+        } else {
+          window.location.href = "/login";
+        }
       })
       .catch(() => {
         sessionStorage.setItem(reloginCancelKey, "true");

+ 23 - 0
src/router/index.ts

@@ -87,6 +87,29 @@ const routes: RouteRecordRaw[] = [
       title: "DeepOil 智慧经营平台 | 驾驶舱",
     },
   },
+
+  {
+    path: "/news",
+    name: "News",
+    component: () => import("@/views/news/index.vue"),
+    meta: {
+      title: "DeepOil 智慧经营平台 | 新闻",
+    },
+  },
+
+  {
+    path: "/notice-redhead",
+    name: "NoticeRedhead",
+    component: () => import("@/views/notices/index.vue"),
+    meta: {
+      // 动态设置页面标题
+      dynamicTitle: (route) => {
+        const { paramsObject } = parseURL(route.fullPath);
+        const { title } = paramsObject;
+        return title || "新闻";
+      },
+    },
+  },
 ];
 
 const router = createRouter({

+ 128 - 51
src/views/index.vue

@@ -129,23 +129,39 @@
                 </button>
               </div>
               <button type="button" class="side-card__more">
-                <Icon icon="mdi:dots-horizontal" class="text-[22px]" />
+                <Icon
+                  icon="mdi:dots-horizontal"
+                  class="text-[22px]"
+                  @click="handleNoticeMoreClick"
+                />
               </button>
             </div>
 
             <div class="space-y-2 p-2 pt-3">
               <div
-                v-if="!currentNoticeList.length"
+                v-if="!userStore.getUser.username"
+                class="flex h-full items-center justify-center"
+              >
+                <div class="text-[#8a9ab0] pt-5">登录后查看</div>
+              </div>
+
+              <div
+                v-if="!currentNoticeList.length && userStore.getUser.username"
                 class="flex h-[120px] items-center justify-center text-[#8a9ab0]"
               >
                 暂无数据
               </div>
               <article
+                v-if="userStore.getUser.username"
                 v-for="notice in currentNoticeList"
                 :key="notice.id"
                 class="notice-item cursor-pointer"
+                @click="handleNoticeItemClick(notice)"
               >
                 <div class="notice-item__desc">{{ notice.docsubject }}</div>
+                <div class="date text-[12px] text-[#9cadc0]">
+                  {{ notice.docvaliddate }}
+                </div>
               </article>
             </div>
           </section>
@@ -176,7 +192,7 @@
                 v-if="!oaTasks.length && userStore.getUser.username"
                 class="flex h-full items-center justify-center"
               >
-                <div class="text-[#8a9ab0]">暂无数据</div>
+                <div class="text-[#8a9ab0] pt-10">暂无待办</div>
               </div>
 
               <article
@@ -212,29 +228,38 @@
           >
             <div class="side-card__header w-[90%] ml-[15px]">
               <div class="notice-badge">{{ newsPanelTitle }}</div>
-              <button type="button" class="side-card__more">
+              <button type="button" class="side-card__more" @click="goNews">
                 <Icon icon="mdi:dots-horizontal" class="text-[22px]" />
               </button>
             </div>
             <div class="space-y-2 p-4 pt-2">
+              <div
+                v-if="!userStore.getUser.username"
+                class="flex h-full items-center justify-center"
+              >
+                <div class="text-[#8a9ab0] pt-10">登录后查看</div>
+              </div>
+
+              <div
+                v-if="!newsList.length && userStore.getUser.username"
+                class="flex h-full items-center justify-center"
+              >
+                <div class="text-[#8a9ab0] pt-10">暂无新闻</div>
+              </div>
               <article
                 v-for="news in newsList"
-                :key="news.title"
+                :key="news.id"
                 class="news-mini cursor-pointer rounded-md"
+                @click="handleNoticeItemClick(news)"
               >
-                <img
-                  :src="news.image"
-                  :alt="news.title"
-                  class="h-[34px] w-[52px] rounded-[8px] object-cover"
-                />
                 <div class="min-w-0 flex-1">
                   <div
-                    class="line-clamp-2 text-[13px] font-semibold leading-[1.45] text-[#41597d]"
+                    class="line-clamp-1 text-[13px] font-semibold leading-[1.45] text-[#41597d]"
                   >
-                    {{ news.title }}
+                    {{ news.docsubject }}
                   </div>
                   <div class="mt-2 text-[12px] text-[#9cadc0]">
-                    {{ news.date }}
+                    {{ news.docvaliddate }}
                   </div>
                 </div>
               </article>
@@ -282,6 +307,7 @@ import {
   getOATasks,
   getNotices,
   getRedHeadFiles,
+  getNews,
 } from "@/api/user";
 import { useUserStore } from "@/stores/useUserStore";
 import { getAccessToken } from "@/utils/auth";
@@ -339,28 +365,9 @@ type NoticeItem = {
   docsubject?: string;
 };
 
-type SidePanel = {
-  title: string;
-  height: string;
-};
-
-type TodoTask = {
-  title: string;
-  meta: string;
-  tag: string;
-  tagClass: string;
-};
-
-type NewsItem = {
-  title: string;
-  date: string;
-  image: string;
-};
-
 const router = useRouter();
 const userStore = useUserStore();
 
-const noticeLabel = "公告";
 const todoPanelTitle = "待办中心";
 const newsPanelTitle = "新闻";
 const noticeTabs = [
@@ -482,23 +489,7 @@ const noticeListMap = ref<Record<NoticeTabKey, NoticeItem[]>>({
   redHead: [],
 });
 
-const newsList: NewsItem[] = [
-  {
-    title: "科瑞石油成功交付首套自动化钻机",
-    date: "2026-04-18",
-    image: banner1,
-  },
-  {
-    title: "DeepOil 智慧平台荣获行业创新奖",
-    date: "2026-04-15",
-    image: banner2,
-  },
-  {
-    title: "数字人才培养“扬帆计划”正式启动",
-    date: "2026-04-12",
-    image: img3,
-  },
-];
+const newsList = ref([]);
 
 const currentNoticeList = computed(
   () => noticeListMap.value[activeNoticeTab.value] ?? [],
@@ -514,12 +505,25 @@ const loadNoticeList = async (tabKey: NoticeTabKey) => {
   noticeListMap.value[tabKey] = (res?.list || []).slice(0, 3);
 };
 
+let currentTabKey = ref<NoticeTabKey>("notice");
 const handleNoticeTabChange = async (tabKey: NoticeTabKey) => {
   activeNoticeTab.value = tabKey;
+  currentTabKey.value = tabKey;
 
-  if (noticeListMap.value[tabKey].length) return;
+  // if (noticeListMap.value[tabKey].length) return;
 
-  await loadNoticeList(tabKey);
+  if (userStore.getUser.username) {
+    await loadNoticeList(tabKey);
+  }
+};
+
+const handleNoticeMoreClick = () => {
+  router.push({
+    path: "/notice-redhead",
+    query: {
+      tabKey: currentTabKey.value,
+    },
+  });
 };
 
 const protectedOpen = (url: string) => {
@@ -715,11 +719,64 @@ onMounted(async () => {
         pageSize: 10,
       });
       oaTasks.value = res.todoList.slice(0, 3);
+
+      const newList = await getNews({
+        pageNum: 1,
+        pageSize: 10,
+      });
+
+      newsList.value = newList.list.slice(0, 3);
     } finally {
     }
   }
 });
 
+const handleNoticeItemClick = async (notice) => {
+  const res = await ssoLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const ua = window.navigator.userAgent.toLowerCase();
+    if (ua.includes("dingtalk") || ua.includes("dingtalkwork")) {
+      dd.biz.util.openLink({
+        url:
+          "https://yfoa.keruioil.com/wui/index.html" +
+          "?ssoToken=" +
+          res +
+          "#/main", // 先跳你的 SSO 链接
+        onSuccess: () => {
+          // 延迟跳目标业务地址(和你原来 setTimeout 逻辑一致)
+          setTimeout(() => {
+            dd.biz.util.openLink({
+              url: `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`,
+            });
+          }, 100);
+        },
+      });
+    } else {
+      const loading = ElLoading.service({
+        lock: true,
+        text: "正在跳转,请稍候...",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      const newTab = window.open("", "_blank");
+      newTab.location.href =
+        "https://yfoa.keruioil.com/wui/index.html" +
+        "?ssoToken=" +
+        res +
+        "#/main";
+
+      setTimeout(function () {
+        newTab.location.href = `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`;
+        setTimeout(() => {
+          loading.close();
+        }, 500);
+      }, 100);
+    }
+  }
+};
+
 const handleTask = async (row) => {
   const res = await ssoLogin({
     username: userStore.getUser.username,
@@ -766,6 +823,10 @@ const handleTask = async (row) => {
   }
 };
 
+const goNews = () => {
+  router.push("/news");
+};
+
 onUnmounted(() => {
   if (slideTimer) {
     clearInterval(slideTimer);
@@ -1139,11 +1200,21 @@ onUnmounted(() => {
   border-radius: 10px;
 }
 
+.notice-item:hover {
+  box-shadow: 0 12px 28px rgba(63, 107, 169, 0.1);
+  transition: all 0.2s ease;
+  transform: translateY(-1px);
+}
+
 .notice-item__title,
 .notice-item__desc {
   color: #507698;
   font-size: 13px;
   line-height: 1.5;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  overflow: hidden;
 }
 
 .panel-title {
@@ -1179,6 +1250,12 @@ onUnmounted(() => {
   border: none;
 }
 
+.news-mini:hover {
+  box-shadow: 0 12px 28px rgba(63, 107, 169, 0.1);
+  transition: all 0.2s ease;
+  transform: translateY(-1px);
+}
+
 .placeholder-panel {
   display: flex;
   height: 100%;

+ 2 - 2
src/views/login.vue

@@ -21,7 +21,7 @@
         <h1 class="text-2xl font-bold text-center">登录</h1>
 
         <!-- 用户名密码登陆 -->
-        <div>
+        <!-- <div>
           <el-form
             :model="form"
             :rules="rules"
@@ -62,7 +62,7 @@
               >
             </div>
           </div>
-        </div>
+        </div> -->
 
         <!-- 钉钉登陆 -->
         <div class="text-center">

+ 240 - 0
src/views/news/index.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="news-container">
+    <Header />
+
+    <div class="content-wrapper mt-15 max-w-[1200px] mx-auto">
+      <h2 class="page-title">新闻中心</h2>
+
+      <!-- 新闻列表区域 - 使用 el-table -->
+      <div v-loading="loading" class="table-wrapper">
+        <el-table
+          :data="newsList"
+          style="width: 100%"
+          height="70vh"
+          v-loading="loading"
+          element-loading-text="加载中..."
+          :empty-text="loading ? '' : '暂无数据'"
+          stripe
+          :header-cell-style="{
+            backgroundColor: '#e9f7ff',
+            color: 'black',
+            fontWeight: '400',
+          }"
+          :cell-style="{
+            color: 'black',
+          }"
+        >
+          <!-- 序号列 -->
+          <el-table-column
+            type="index"
+            label="序号"
+            width="60"
+            align="center"
+          />
+
+          <!-- 标题列 -->
+          <el-table-column prop="title" label="标题" min-width="300">
+            <template #default="{ row }">
+              <span class="table-title">{{ row.docsubject }}</span>
+            </template>
+          </el-table-column>
+
+          <!-- 时间列 -->
+          <el-table-column
+            prop="docvaliddate"
+            label="发布时间"
+            width="180"
+            align="center"
+            sortable
+          />
+
+          <!-- 操作列(可选) -->
+          <el-table-column label="操作" width="100" align="center">
+            <template #default="{ row }">
+              <el-button
+                link
+                type="primary"
+                size="small"
+                @click="handleNoticeItemClick(row)"
+                >查看详情</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 分页区域 -->
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="pagination.pageNum"
+          v-model:page-size="pagination.pageSize"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="pagination.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+
+    <Footer />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from "vue";
+import Header from "@components/home/header.vue";
+import Footer from "@components/home/Footer.vue";
+import { ElLoading } from "element-plus";
+import { getNews, ssoLogin } from "@/api/user";
+import { useUserStore } from "@/stores/useUserStore";
+const userStore = useUserStore();
+// 状态定义
+const loading = ref(false);
+const newsList = ref([]);
+
+// 分页参数
+const pagination = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+const handleNoticeItemClick = async (notice) => {
+  const res = await ssoLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const ua = window.navigator.userAgent.toLowerCase();
+    if (ua.includes("dingtalk") || ua.includes("dingtalkwork")) {
+      dd.biz.util.openLink({
+        url:
+          "https://yfoa.keruioil.com/wui/index.html" +
+          "?ssoToken=" +
+          res +
+          "#/main", // 先跳你的 SSO 链接
+        onSuccess: () => {
+          // 延迟跳目标业务地址(和你原来 setTimeout 逻辑一致)
+          setTimeout(() => {
+            dd.biz.util.openLink({
+              url: `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`,
+            });
+          }, 100);
+        },
+      });
+    } else {
+      const loading = ElLoading.service({
+        lock: true,
+        text: "正在跳转,请稍候...",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      const newTab = window.open("", "_blank");
+      newTab.location.href =
+        "https://yfoa.keruioil.com/wui/index.html" +
+        "?ssoToken=" +
+        res +
+        "#/main";
+
+      setTimeout(function () {
+        newTab.location.href = `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`;
+        setTimeout(() => {
+          loading.close();
+        }, 500);
+      }, 100);
+    }
+  }
+};
+
+// 获取新闻列表方法
+const fetchNewsList = async () => {
+  loading.value = true;
+  try {
+    const res = await getNews({
+      pageNum: pagination.pageNum,
+      pageSize: pagination.pageSize,
+    });
+
+    // 请根据实际接口返回结构调整以下赋值逻辑
+    if (res && res.list) {
+      newsList.value = res.list || [];
+      pagination.total = res.total || 0;
+    } else if (res && res.data) {
+      // 兼容另一种常见返回结构
+      newsList.value = res.data.list || [];
+      pagination.total = res.data.total || 0;
+    }
+  } catch (error) {
+    console.error("获取新闻列表失败:", error);
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 分页大小改变事件
+const handleSizeChange = (val) => {
+  pagination.pageSize = val;
+  pagination.pageNum = 1;
+  fetchNewsList();
+};
+
+// 当前页改变事件
+const handleCurrentChange = (val) => {
+  pagination.pageNum = val;
+  fetchNewsList();
+};
+
+// 组件挂载时获取数据
+onMounted(() => {
+  fetchNewsList();
+});
+</script>
+
+<style scoped>
+.news-container {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f7fa;
+}
+
+.content-wrapper {
+  flex: 1;
+  max-width: 1200px;
+  /* margin: 0 auto; */
+  padding: 20px;
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.page-title {
+  margin-bottom: 20px;
+  color: #303133;
+  border-left: 5px solid #409eff;
+  padding-left: 10px;
+}
+
+.table-wrapper {
+  min-height: 400px;
+  background: #fff;
+  padding: 20px;
+  border-radius: 4px;
+}
+
+.table-title {
+  font-weight: 500;
+  color: #303133;
+}
+
+.table-summary {
+  color: #606266;
+  font-size: 13px;
+}
+
+.pagination-container {
+  display: flex;
+  justify-content: center;
+  margin-top: 10px;
+  padding: 20px 0;
+}
+</style>

+ 246 - 0
src/views/notices/index.vue

@@ -0,0 +1,246 @@
+<template>
+  <div class="news-container">
+    <Header />
+
+    <div class="content-wrapper mt-15 max-w-[1200px] mx-auto">
+      <h2 class="page-title">
+        {{ route.query.tabKey === "notice" ? "公告" : "红头文件" }}
+      </h2>
+
+      <!-- 新闻列表区域 - 使用 el-table -->
+      <div v-loading="loading" class="table-wrapper">
+        <el-table
+          :data="newsList"
+          style="width: 100%"
+          height="70vh"
+          v-loading="loading"
+          element-loading-text="加载中..."
+          :empty-text="loading ? '' : '暂无数据'"
+          stripe
+          :header-cell-style="{
+            backgroundColor: '#e9f7ff',
+            color: 'black',
+            fontWeight: '400',
+          }"
+          :cell-style="{
+            color: 'black',
+          }"
+        >
+          <!-- 序号列 -->
+          <el-table-column
+            type="index"
+            label="序号"
+            width="60"
+            align="center"
+          />
+
+          <!-- 标题列 -->
+          <el-table-column prop="title" label="标题" min-width="300">
+            <template #default="{ row }">
+              <span class="table-title">{{ row.docsubject }}</span>
+            </template>
+          </el-table-column>
+
+          <!-- 时间列 -->
+          <el-table-column
+            prop="docvaliddate"
+            label="发布时间"
+            width="180"
+            align="center"
+            sortable
+          />
+
+          <!-- 操作列(可选) -->
+          <el-table-column label="操作" width="100" align="center">
+            <template #default="{ row }">
+              <el-button
+                link
+                type="primary"
+                size="small"
+                @click="handleNoticeItemClick(row)"
+                >查看详情</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 分页区域 -->
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="pagination.pageNum"
+          v-model:page-size="pagination.pageSize"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="pagination.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+
+    <Footer />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from "vue";
+import Header from "@components/home/header.vue";
+import Footer from "@components/home/Footer.vue";
+import { ElLoading } from "element-plus";
+import { getNews, ssoLogin, getNotices, getRedHeadFiles } from "@/api/user";
+import { useUserStore } from "@/stores/useUserStore";
+import { useRoute } from "vue-router";
+const userStore = useUserStore();
+const route = useRoute();
+// 状态定义
+const loading = ref(false);
+const newsList = ref([]);
+
+// 分页参数
+const pagination = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+const handleNoticeItemClick = async (notice) => {
+  const res = await ssoLogin({
+    username: userStore.getUser.username,
+  });
+
+  if (res) {
+    const ua = window.navigator.userAgent.toLowerCase();
+    if (ua.includes("dingtalk") || ua.includes("dingtalkwork")) {
+      dd.biz.util.openLink({
+        url:
+          "https://yfoa.keruioil.com/wui/index.html" +
+          "?ssoToken=" +
+          res +
+          "#/main", // 先跳你的 SSO 链接
+        onSuccess: () => {
+          // 延迟跳目标业务地址(和你原来 setTimeout 逻辑一致)
+          setTimeout(() => {
+            dd.biz.util.openLink({
+              url: `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`,
+            });
+          }, 100);
+        },
+      });
+    } else {
+      const loading = ElLoading.service({
+        lock: true,
+        text: "正在跳转,请稍候...",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      const newTab = window.open("", "_blank");
+      newTab.location.href =
+        "https://yfoa.keruioil.com/wui/index.html" +
+        "?ssoToken=" +
+        res +
+        "#/main";
+
+      setTimeout(function () {
+        newTab.location.href = `https://yfoa.keruioil.com/spa/document/index.jsp?openAttachment=0&id=${notice.id}`;
+        setTimeout(() => {
+          loading.close();
+        }, 500);
+      }, 100);
+    }
+  }
+};
+
+// 获取新闻列表方法
+const fetchNewsList = async () => {
+  loading.value = true;
+  try {
+    const requestApi =
+      route.query.tabKey === "notice" ? getNotices : getRedHeadFiles;
+    const res = await requestApi({
+      pageNum: pagination.pageNum,
+      pageSize: pagination.pageSize,
+    });
+
+    // 请根据实际接口返回结构调整以下赋值逻辑
+    if (res && res.list) {
+      newsList.value = res.list || [];
+      pagination.total = res.total || 0;
+    } else if (res && res.data) {
+      // 兼容另一种常见返回结构
+      newsList.value = res.data.list || [];
+      pagination.total = res.data.total || 0;
+    }
+  } catch (error) {
+    console.error("获取新闻列表失败:", error);
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 分页大小改变事件
+const handleSizeChange = (val) => {
+  pagination.pageSize = val;
+  pagination.pageNum = 1;
+  fetchNewsList();
+};
+
+// 当前页改变事件
+const handleCurrentChange = (val) => {
+  pagination.pageNum = val;
+  fetchNewsList();
+};
+
+// 组件挂载时获取数据
+onMounted(() => {
+  fetchNewsList();
+});
+</script>
+
+<style scoped>
+.news-container {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f7fa;
+}
+
+.content-wrapper {
+  flex: 1;
+  max-width: 1200px;
+  /* margin: 0 auto; */
+  padding: 20px;
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.page-title {
+  margin-bottom: 20px;
+  color: #303133;
+  border-left: 5px solid #409eff;
+  padding-left: 10px;
+}
+
+.table-wrapper {
+  min-height: 400px;
+  background: #fff;
+  padding: 20px;
+  border-radius: 4px;
+}
+
+.table-title {
+  font-weight: 500;
+  color: #303133;
+}
+
+.table-summary {
+  color: #606266;
+  font-size: 13px;
+}
+
+.pagination-container {
+  display: flex;
+  justify-content: center;
+  margin-top: 10px;
+  padding: 20px 0;
+}
+</style>