Преглед на файлове

feat: 解决无限加载分页bug

sunxiao преди 8 месеца
родител
ревизия
af678f7d6c

+ 12 - 4
src/components/Layout/TheSubMenu.vue

@@ -1,6 +1,6 @@
 <script setup lang="jsx">
 import { storeToRefs } from 'pinia';
-import { NScrollbar, NInfiniteScroll } from 'naive-ui';
+import { NInfiniteScroll } from 'naive-ui';
 import { useAppStore } from '@/stores/modules/appStore';
 import SvgIcon from '@/components/SvgIcon';
 
@@ -15,8 +15,6 @@ defineProps({
   }
 })
 
-// const modelLoading = defineModel('loading');
-
 const emits = defineEmits(['scrollToLower']);
 
 const appStore = useAppStore();
@@ -26,6 +24,16 @@ const { subMenuCollapse } = storeToRefs(appStore);
 const changeCollapse = () => appStore.toggleSubMenuCollapse();
 
 const handleLoadMore = () => emits('scrollToLower');
+
+const scrollToTop = () => {
+  document.querySelector('.scroll_container').parentNode.scrollTo({
+    top: 0,
+    left: 0
+  })
+};
+
+defineExpose({ scrollToTop });
+
 </script>
 
 <template>
@@ -41,7 +49,7 @@ const handleLoadMore = () => emits('scrollToLower');
     </div>
 
     <div class="sub-menu-main w-full h-full" >
-      <NInfiniteScroll class="h-full" :distance="10" @load="handleLoadMore">
+      <NInfiniteScroll class="h-full" :distance="10" @load="handleLoadMore" content-class="scroll_container">
         <slot></slot>
         <div class="footer-loading w-full h-[50px]" v-show="loading">
           加载更多

+ 22 - 9
src/composables/useInfinite.js

@@ -1,14 +1,18 @@
-import { ref, unref, onMounted, computed } from "vue";
+import { ref, unref, onMounted, computed, watch } from "vue";
 import { chatApi } from '@/api/chat';
 
 export const useInfinite = (path, props) => {
+
   const pageParams = ref({ pageNum: 1, pageSize: 20 });
+  const queryParams = ref(props);
 
   const recordList = ref([]);
   const isFetching = ref(false);
   const counter = ref(0);
   const noMore = ref(false);
 
+  // let isSwitchStatus = false;
+
   const isMore = computed(() => pageParams.value.pageNum * pageParams.value.pageSize < counter.value);
 
   const addHistoryRecord = record => {
@@ -16,8 +20,7 @@ export const useInfinite = (path, props) => {
   }
 
   const onScrolltolower = async () => {
-
-    if(unref(isFetching) || unref(noMore)) return;
+    if(unref(isFetching) || unref(noMore) ) return;
 
     isFetching.value = true;
 
@@ -26,7 +29,7 @@ export const useInfinite = (path, props) => {
     recordList.value.push(...rows);
 
     counter.value = total;
-
+  
     if (unref(isMore)) {
       pageParams.value.pageNum ++;
     } else {
@@ -38,23 +41,33 @@ export const useInfinite = (path, props) => {
 
   const onReset = async () => {
     const { rows, total } = await initRecordData({pageNum:1, pageSize: (pageParams.value.pageNum * pageParams.value.pageSize) + 1});
-
     recordList.value = rows;
     counter.value = total;
-    noMore.value = !unref(isMore);
+
+    noMore.value = !unref(isMore)
   }
 
+  // 重置请求
   const onRestore = async (params) => {
     pageParams.value = { pageNum: 1, pageSize: 20 };
-    const { rows, total } = await initRecordData(params);
+    queryParams.value = { ...unref(queryParams), ...params };
+      
+    const { rows, total } = await initRecordData();
+
+    // isSwitchStatus = true;  
+    
     recordList.value = rows;
     counter.value = total;
+
+    // setTimeout(() =>  isSwitchStatus = false, 100);
+
+    noMore.value = !isMore.value;
   }
 
   const initRecordData = async (params = {}) => {
     const reqParams = {
-      ...pageParams.value,
-      ...props,
+      ...unref(pageParams),
+      ...unref(queryParams),
       ...params
     }
     return await chatApi.getRecordFetch(path, reqParams);

+ 20 - 4
src/router/index.js

@@ -10,11 +10,27 @@ const constantRouterMap = [
     }
   },
   {
-    path: '/count',
-    name: 'count',
-    component: () => import('@/views/count/index.vue'),
+    path: '/count1',
+    name: 'count1',
+    component: () => import('@/views/count/index1.vue'),
     meta: {
-      title: "临时统计"
+      title: "临时统计1"
+    }
+  },
+  {
+    path: '/count2',
+    name: 'count2',
+    component: () => import('@/views/count/index2.vue'),
+    meta: {
+      title: "临时统计2"
+    }
+  },
+  {
+    path: '/count3',
+    name: 'count3',
+    component: () => import('@/views/count/index3.vue'),
+    meta: {
+      title: "临时统计3"
     }
   },
   {

+ 4 - 2
src/views/analyse/ForecastView.vue

@@ -26,6 +26,7 @@ const chartTitle = ref("");
 
 let chart = null;
 const echartRef = ref({});
+const subMenuRef = ref(null);
 
 // 进出水数据
 const jsTableData = ref([]);
@@ -35,7 +36,8 @@ const csTableData = ref([]);
 const onChangeTabs = warningStatus => {
   answerResult.value = '';
   textDataSources.value = '';
-  onRestore({ warningStatus })
+  onRestore({ warningStatus });
+  subMenuRef.value.scrollToTop();
 }
 
 // 打开详情
@@ -86,7 +88,7 @@ onMounted(() => {
 
 <template>
   <section class="flex items-start h-full" id="warning">
-    <TheSubMenu title="预测预警" @scrollToLower="onScrolltolower" :loading="isFetching">
+    <TheSubMenu title="预测预警" @scrollToLower="onScrolltolower" :loading="isFetching" ref="subMenuRef">
       <template #top>
         <div class="border-[#DAE5ED]">
           <n-tabs type="line" justify-content="space-evenly">

+ 3 - 1
src/views/analyse/PymolView.vue

@@ -19,6 +19,7 @@ const chatStore = useChatStore();
 
 const answerResult = ref("");
 const textDataSources = ref(null);
+const subMenuRef = ref(null);
 
 // 进出水数据
 const jsTableData = ref([]);
@@ -29,6 +30,7 @@ const onChangeTabs = warningStatus => {
   answerResult.value = '';
   textDataSources.value = '';
   onRestore({ warningStatus })
+  subMenuRef.value.scrollToTop();
 }
 
 // 打开详情
@@ -57,7 +59,7 @@ const handleWelcomeRecommend = question => {
 
 <template>
   <section class="flex items-start h-full" id="warning">
-    <TheSubMenu title="生化报警" @scrollToLower="onScrolltolower" :loading="isFetching">
+    <TheSubMenu title="生化报警" @scrollToLower="onScrolltolower" :loading="isFetching" ref="subMenuRef">
       <template #top>
         <div class="border-[#DAE5ED]">
           <n-tabs type="line" justify-content="space-evenly">

+ 5 - 1
src/views/analyse/WaterView.vue

@@ -16,6 +16,7 @@ import { waterApi } from '@/api/water';
 const { recommendList } = useRecommend({type: 1});
 const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll();
 const { refetch, cancelFetch } = useFetchStream("/grpc/decisionStream", { methdos: 'POST' }, false);
+
 const { recordList, isFetching, onScrolltolower, onRestore } = useInfinite('/front/bigModel/warning/pageList', { type: 0, warningStatus: 0 });
 
 const router = useRouter();
@@ -34,6 +35,7 @@ const flowParams = {
 const answerLoading = ref(false);
 const textDataSources = ref(null);
 const warningActive = ref(0);
+const subMenuRef = ref(null);
 
 // 进出水数据
 const jsTableData = ref([]);
@@ -115,6 +117,7 @@ const handleOpenContent = async ({ id, category, reason:title }) => {
     })
 
     if ( reportList.length ) {
+      console.log( reportList.join("") );
       answerResult.value.push({
         biz: 'DECISION_REPORT',
         answer: reportList.join(""),
@@ -222,6 +225,7 @@ const onChangeTabs = warningStatus => {
   resetConfiguration();
   warningActive.value = warningStatus;
   onRestore({ warningStatus });
+  subMenuRef.value.scrollToTop();
 }
 
 // 生成流数据
@@ -375,7 +379,7 @@ const handleWelcomeRecommend = question => {
 
 <template>
   <section class="flex items-start h-full" id="warning">
-    <TheSubMenu title="水质报警" @scrollToLower="onScrolltolower" :loading="isFetching">
+    <TheSubMenu title="水质报警" @scrollToLower="onScrolltolower" :loading="isFetching" ref="subMenuRef">
       <template #top>
         <div class="border-[#DAE5ED]">
           <n-tabs type="line" justify-content="space-evenly">

Файловите разлики са ограничени, защото са твърде много
+ 0 - 1158
src/views/count/all_book.json


Файловите разлики са ограничени, защото са твърде много
+ 1158 - 0
src/views/count/all_book1.json


Файловите разлики са ограничени, защото са твърде много
+ 496 - 0
src/views/count/all_book2.json


Файловите разлики са ограничени, защото са твърде много
+ 340 - 0
src/views/count/all_book3.json


+ 1 - 1
src/views/count/index.vue → src/views/count/index1.vue

@@ -2,7 +2,7 @@
 import { ref, onMounted, watch } from 'vue';
 import { NButton, NSpace, NDrawer, NDrawerContent, NCard } from 'naive-ui';
 import { ChatAsk, ChatAnswer } from '@/components/Chat';
-import allBookData from "./all_book.json";
+import allBookData from "./all_book1.json";
 
 const dataSource = ref([]);
 const errIds = ref([]);

+ 125 - 0
src/views/count/index2.vue

@@ -0,0 +1,125 @@
+<script setup>
+import { ref, onMounted, watch } from 'vue';
+import { NButton, NSpace, NDrawer, NDrawerContent, NCard } from 'naive-ui';
+import { ChatAsk, ChatAnswer } from '@/components/Chat';
+import allBookData from "./all_book2.json";
+
+const dataSource = ref([]);
+const errIds = ref([]);
+const visible = ref(false);
+const pageNum = ref(0);
+const pageSize = 10;
+
+const totalPages = Math.ceil(allBookData.length / pageSize);
+
+watch(pageNum, (num) => {
+  dataSource.value = allBookData.slice((num - 1) * pageSize, num * pageSize).map(item => ({
+    ...item,
+    isDisable: errIds.value.includes(item.id),
+    history: [
+      ...item.history,
+      [item.instruction, item.output]
+    ]
+  }))
+})
+
+const changeVisible = () => {
+  visible.value = !visible.value;
+}
+
+const handleNextPage = () => {
+  if ( pageNum.value === totalPages ) return alert("已经是最后一页了");
+  pageNum.value += 1;
+  localStorage.setItem('pageNum', pageNum.value)
+}
+
+const handleError = item => {
+  item.isDisable = true;
+
+  errIds.value.push(item.id);
+  localStorage.setItem('errIds', JSON.stringify( errIds.value ));
+}
+
+onMounted(() => {
+  const localIds = localStorage.getItem('errIds');
+  const localNum = localStorage.getItem('pageNum');
+  const ids = localIds ? JSON.parse(localIds) : [];
+  const num = localNum ? Number(localNum) : 1;
+
+  errIds.value = ids;
+  pageNum.value = num;
+})
+</script>
+
+<template>
+  <section class="page-container">
+    <header class="header flex items-center">
+      <NSpace>
+        <n-button @click="handleNextPage">下一页</n-button>
+        <n-button @click="changeVisible">显示错误id</n-button>
+      </NSpace>
+      <p class="ml-[30px] space-x-[10px]">
+        <span>{{ pageNum }}</span>
+        <span> / </span>
+        <span>{{ totalPages }}</span>
+      </p>
+    </header>
+    <div class="main">
+      <NCard :title="item.id" v-for="item in dataSource" :key="item.id" class="mb-[20px]">
+        <div v-for="arr, i in item.history" :key="i + item.id" class="pt-[40px]">
+          <ChatAsk :content="arr[0]"></ChatAsk>
+          <ChatAnswer :content="arr[1]" :toggleVisibleIcons="false"></ChatAnswer>
+          <hr>
+        </div>
+        <div class="answer-btns pt-[20px]">
+          <NSpace>
+            <NButton :type="item.isDisable? '' : 'error'" @click="handleError(item)" :disabled="item.isDisable">
+              {{ item.isDisable ? '已审核' : '错' }}
+            </NButton>
+          </NSpace>
+        </div>
+      </NCard>
+    </div>
+  </section>
+  <NDrawer placement="right" v-model:show="visible" width="800" title="错误ID">
+    <n-drawer-content :title="'错误ID列表 -- ' + errIds.length + ' 个'">
+      <!-- <div class="py-[30px]">{{ errIds.join(',') }}</div> -->
+    <!-- <hr> -->
+    <ul class="grid grid-cols-5">
+      <li v-for="item in errIds" :key="item">{{ item }}</li>
+    </ul>
+    </n-drawer-content>
+  </NDrawer>
+</template>
+
+<style lang="scss" scoped>
+.page-container {
+  width: 100vw;
+  height: 100vh;
+  background: #edf7fc;
+
+  .header {
+    display: flex;
+    justify-content: center;
+    padding: 20px 0;
+    background: #fff;
+  }
+
+  .main {
+    width: 1000px;
+    height: calc(100% - 74px);
+    margin: 0 auto;
+    overflow-y: scroll;
+
+    .answer-block {
+      border-bottom: 1px solid #000000;
+      padding-bottom: 20px;
+    }
+
+    .answer-btns {
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+}
+</style>

+ 125 - 0
src/views/count/index3.vue

@@ -0,0 +1,125 @@
+<script setup>
+import { ref, onMounted, watch } from 'vue';
+import { NButton, NSpace, NDrawer, NDrawerContent, NCard } from 'naive-ui';
+import { ChatAsk, ChatAnswer } from '@/components/Chat';
+import allBookData from "./all_book3.json";
+
+const dataSource = ref([]);
+const errIds = ref([]);
+const visible = ref(false);
+const pageNum = ref(0);
+const pageSize = 10;
+
+const totalPages = Math.ceil(allBookData.length / pageSize);
+
+watch(pageNum, (num) => {
+  dataSource.value = allBookData.slice((num - 1) * pageSize, num * pageSize).map(item => ({
+    ...item,
+    isDisable: errIds.value.includes(item.id),
+    history: [
+      ...item.history,
+      [item.instruction, item.output]
+    ]
+  }))
+})
+
+const changeVisible = () => {
+  visible.value = !visible.value;
+}
+
+const handleNextPage = () => {
+  if ( pageNum.value === totalPages ) return alert("已经是最后一页了");
+  pageNum.value += 1;
+  localStorage.setItem('pageNum', pageNum.value)
+}
+
+const handleError = item => {
+  item.isDisable = true;
+
+  errIds.value.push(item.id);
+  localStorage.setItem('errIds', JSON.stringify( errIds.value ));
+}
+
+onMounted(() => {
+  const localIds = localStorage.getItem('errIds');
+  const localNum = localStorage.getItem('pageNum');
+  const ids = localIds ? JSON.parse(localIds) : [];
+  const num = localNum ? Number(localNum) : 1;
+
+  errIds.value = ids;
+  pageNum.value = num;
+})
+</script>
+
+<template>
+  <section class="page-container">
+    <header class="header flex items-center">
+      <NSpace>
+        <n-button @click="handleNextPage">下一页</n-button>
+        <n-button @click="changeVisible">显示错误id</n-button>
+      </NSpace>
+      <p class="ml-[30px] space-x-[10px]">
+        <span>{{ pageNum }}</span>
+        <span> / </span>
+        <span>{{ totalPages }}</span>
+      </p>
+    </header>
+    <div class="main">
+      <NCard :title="item.id" v-for="item in dataSource" :key="item.id" class="mb-[20px]">
+        <div v-for="arr, i in item.history" :key="i + item.id" class="pt-[40px]">
+          <ChatAsk :content="arr[0]"></ChatAsk>
+          <ChatAnswer :content="arr[1]" :toggleVisibleIcons="false"></ChatAnswer>
+          <hr>
+        </div>
+        <div class="answer-btns pt-[20px]">
+          <NSpace>
+            <NButton :type="item.isDisable? '' : 'error'" @click="handleError(item)" :disabled="item.isDisable">
+              {{ item.isDisable ? '已审核' : '错' }}
+            </NButton>
+          </NSpace>
+        </div>
+      </NCard>
+    </div>
+  </section>
+  <NDrawer placement="right" v-model:show="visible" width="800" title="错误ID">
+    <n-drawer-content :title="'错误ID列表 -- ' + errIds.length + ' 个'">
+      <!-- <div class="py-[30px]">{{ errIds.join(',') }}</div> -->
+    <!-- <hr> -->
+    <ul class="grid grid-cols-5">
+      <li v-for="item in errIds" :key="item">{{ item }}</li>
+    </ul>
+    </n-drawer-content>
+  </NDrawer>
+</template>
+
+<style lang="scss" scoped>
+.page-container {
+  width: 100vw;
+  height: 100vh;
+  background: #edf7fc;
+
+  .header {
+    display: flex;
+    justify-content: center;
+    padding: 20px 0;
+    background: #fff;
+  }
+
+  .main {
+    width: 1000px;
+    height: calc(100% - 74px);
+    margin: 0 auto;
+    overflow-y: scroll;
+
+    .answer-block {
+      border-bottom: 1px solid #000000;
+      padding-bottom: 20px;
+    }
+
+    .answer-btns {
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+}
+</style>

+ 19 - 0
xxx.md

@@ -0,0 +1,19 @@
+### 解决方案
+1. **紧急响应与预案启动**
+   - 当出水总磷指标超过管控值时,应立即进行水质复测确认。   - 若确认超标且超过标准值,则立即启动应急预案,并向行业主管部门报备。2. **加强水质监测与数据分析**
+   - 建议增加水质监测频次,特别是针对总磷指标的实时监测。   - 对历史数据进行深入分析,找出总磷超标的原因和规律。3. **优化除磷工艺**
+   - 调整除磷药剂的投加量,由原先的0.56提升至0.74,以提高除磷效率。   - 对除磷药剂投加点位进行优化,确保药剂与污水的充分混合。4. **工艺调整与优化**
+   - 针对AAO+MBBR工艺,优化生化系统的运行,特别是厌氧段、缺氧段和好氧段的运行参数。   - 调整多点进水和回流分配,提高厌氧释磷的底物浓度和反应速率。5. **污泥管理与处置**
+   - 增加干污泥的排放量,由当前的13.15调整至22.8,以降低污泥龄,提高磷的去除率。   - 定期检查污泥的性质,确保污泥的活性。6. **溶解氧与污泥浓度的控制**
+   - 调整好氧池1的溶解氧,由2.83降至2.80,以保持适宜的微生物活性。   - 好氧池2的溶解氧建议大幅调整至20.00,以促进有机物的降解和磷的吸收。(注:此值较高,需根据实际情况和工艺要求进行验证)
+   - 调整生化池的污泥浓度,池1由5342.00mg/L降至4746.00mg/L,池2由5827.00mg/L降至5375.00mg/L,以优化污泥的活性。### 解决策略表格
+| 指标项 | 当前值 | 建议调整值 | 是否要调整 | 调整说明 | 如何调整 |
+| --- | --- | --- | --- | --- | --- |
+| 进水水量 | 3619.0 | 3619.0 | 否 | 保持稳定 | 无需调整 || 除磷药剂投加量 | 0.56 | 0.74 | 是 | 提高除磷效率 | 增加药剂投加泵的频率或时间 |
+| 干污泥量 | 13.15 | 22.8 | 是 | 降低污泥龄,提高磷去除率 | 增加污泥排放频次或量 |
+| 好氧池1溶解氧 | 2.83 | 2.80 | 是 | 保持微生物活性 | 调整曝气装置的运行参数 |
+| 好氧池2溶解氧 | 2.46 | 20.00 | 是 | 促进有机物降解和磷吸收 | 大幅增加曝气量,需验证和调整 |
+| 池1生化池污泥浓度(MLSS) | 5342.00mg/L | 4746.00mg/L | 是 | 优化污泥活性 | 调整污泥回流和排放比例 |
+| 池2生化池污泥浓度(MLSS) | 5827.00mg/L | 5375.00mg/L | 是 | 优化污泥活性 | 调整污泥回流和排放比例 |
+### 总结概述
+针对污水处理厂出水总磷超标的问题,我们提出了一系列综合解决方案。

Някои файлове не бяха показани, защото твърде много файлове са промени