Jelajahi Sumber

feat: 报警预测

sunxiao 10 bulan lalu
induk
melakukan
e22fd812fd

+ 1 - 1
src/assets/styles/github-markdown.scss

@@ -293,7 +293,7 @@ html {
   width: 100%;
   overflow: hidden;
   text-overflow: ellipsis;
-  white-space: nowrap;
+  white-space: normal;
   text-align: center;
   font-size: 12px;
   // border-spacing: 0;

+ 3 - 33
src/components/Chat/ChatAnswer.vue

@@ -62,10 +62,13 @@ const handleCopy = () => {
 <template>
   <ChatBaseCard class="answer-inner" :loading="loading" :delayLoading="delayLoading">
 
+    <slot></slot>
+    
     <template #text>
       <ChatText :content="content"></ChatText>
     </template>
 
+
     <template #button>
       <ul class="answer-btn-group" v-if="!loading && toggleVisibleIcons">
         <li class="btn" @click="handleCopy">
@@ -84,39 +87,6 @@ const handleCopy = () => {
 
   </ChatBaseCard>
 
-  <!-- <div class="answer-inner">
-    <div :class="[ 'answer-card', 'px-[20px]', 'py-[20px]']">
-      <div class="chat-answer_icon relative flex-shrink-0">
-        <SvgIcon name="common-logo" class="chat-logo " size="30" :style="{ scale: loading ? 0 : 1 }" />
-        <div style="color: #2454FF" class="la-ball-circus la-dark la-sm flex-shrink-0" v-show="loading">
-          <div v-for="item in 5" :key="item"></div>
-        </div>
-      </div>
-      <div class="flex-1 pt-[4px] ml-[16px] text-[15px]">
-        <template v-if="loading && delayLoading">
-          <p class="font-bold text-[#1A2029] leading-[24px]">内容生成中...</p>
-        </template>
-        <div class="markdown-body text-[15px]" v-if="content">
-          <div v-html="text"></div>
-        </div>
-          <slot></slot>
-      </div>
-    </div>
-    <ul class="answer-btn-group" v-if="!loading">
-      <li class="btn" @click="handleCopy">
-        <SvgIcon name="chat-icon-copy" size="16" />
-      </li>
-      <li class="line"></li>
-      <li :class="['btn', { btn_active: isSatisfied == 1 }]">
-        <SvgIcon name="chat-icon-yes" size="16" @click="handlLeToggleLike(1)" />
-      </li>
-      <li class="line"></li>
-      <li :class="['btn', { btn_active: isSatisfied == 0 }]">
-        <SvgIcon name="chat-icon-no" size="16" @click="handlLeToggleLike(0)" />
-      </li>
-    </ul>
-  </div> -->
-
 </template>
 
 <style lang="scss">

+ 2 - 2
src/components/Chat/ChatBaseCard.vue

@@ -57,10 +57,10 @@ const props = defineProps({
           <p class="font-bold text-[#1A2029] leading-[24px]">内容生成中...</p>
         </template>
 
-        <slot name="text"></slot>
-
         <slot></slot>
 
+        <slot name="text"></slot>
+
       </div>
     </div>
 

+ 1 - 1
src/composables/useFetchStream.js

@@ -68,7 +68,7 @@ export function useFetchStream(url, options = {}, immediate = true) {
       return completeData;
     } catch (err) {
       errorHandler && errorHandler();
-      console.log("cancel success");
+      console.log("fetch err:", err);
       error.value = err;
     } finally {
       loading.value = false;

+ 9 - 4
src/utils/format.js

@@ -5,15 +5,20 @@ const formatTextData = (dataSource, whileList) => {
 export const format = {
   textSorting(dataSource, rule) {
     const title = dataSource.title || dataSource['进水SS超标报警'];
+
     const list = rule.map(item => {
       Object.keys(dataSource).forEach(key => {
-        if (item.realKey === key) {
-          item.value = (isNaN(dataSource[key]) ? dataSource[key]  : truncateDecimals(dataSource[key])) + item.value
+        if (item.realKey === key ) {
+          if ( dataSource[key] !== null ) {
+            item.value = (isNaN(dataSource[key]) ? dataSource[key]  : truncateDecimals(dataSource[key])) + item.value
+          } else{
+            item.value = ''
+          }
+          
         }
       })
       return item;
-    })
-
+    }).filter(({ value }) => value)
     return { title, list };
   }
 }

+ 112 - 29
src/views/analyse/WaterView.vue

@@ -30,7 +30,8 @@ const answerResult = ref([]);
 const flowParams = {
   feedback: '',
   category: '',
-  warningId: ''
+  warningId: '',
+  simulate: null
 };
 
 const answerLoading = ref(false);
@@ -43,6 +44,8 @@ const csTableData = ref([]);
 
 const visible = ref(false);
 
+const modalData = ref({});
+
 const renderRowDom = ({ row, key }) => {
   const { exceed, value } = row[key] || {};
   const cls = exceed ? 'text-[#F44C49] font-bold' : 'text-[1A2029]'
@@ -117,7 +120,7 @@ const handleLoad = () => {
 }
 
 const handleModelVisible = () => {
-  visible.value = true
+  visible.value = true;
 } 
 
 /**
@@ -141,8 +144,6 @@ const handleOpenContent = async ({ id, category }) => {
 
   answerResult.value = [];
 
-  console.log( answerObjItem.biz );
-
   const textWhiteList = [
     { label: '报警时间', realKey: '报警时间', value: '', isWarning: false },
     { label: '报警值',   realKey: '报警值', value: 'mg/L', isWarning: true },
@@ -158,7 +159,7 @@ const handleOpenContent = async ({ id, category }) => {
     const answerContent = answer.map(item => {
       const itemParse = JSON.parse(item); 
       return itemParse.message;
-    }).join();
+    }).join("");
 
     answerResult.value.push({
       biz: 'DECISION_REPORT',
@@ -173,7 +174,6 @@ const handleOpenContent = async ({ id, category }) => {
       result.message = Object.keys(result.message).map(key => ({ ...result.message[key], isActive: null }));
       return result;
     })
-    console.log( parseAnswer?.message );
     answerResult.value.push({
       biz: 'DECISION_ALERT',
       loading: false,
@@ -182,8 +182,9 @@ const handleOpenContent = async ({ id, category }) => {
       list: parseAnswer?.message
     })
   }
+
+  console.log( basic );
   textDataSources.value = format.textSorting(basic, textWhiteList);
-  console.log( "textDataSources", textDataSources );
 
   jsTableData.value = [jsData];
   csTableData.value = [csData];
@@ -203,16 +204,19 @@ const onRegenerate = async () => {
   
   answerLoading.value = true;
 
-  const list = [ {biz: 'DECISION_REPORT', list: []} ]
-
   const len = answerResult.value.length ? answerResult.value.length : 0;
- 
+
   const tempReport = { 
     biz: 'DECISION_REPORT',
     answer: '',
     loading: true,
     delayLoading: true,
   };
+
+  let tempSimulate = null;
+
+  answerLoading.value = true;
+
   const params = {
     body: JSON.stringify(flowParams),
     errorHandler: () => {
@@ -239,12 +243,28 @@ const onRegenerate = async () => {
           isAllSelect: false,
           list
         })
-
       }
 
       if (item.biz === 'DECISION_SIMULATE') {
-        console.log( item );
-        alert("DECISION_SIMULATE")
+        const lastAnswerItem = answerResult.value[len - 1];
+
+        if ( lastAnswerItem.biz === 'DECISION_TABLE' ) {
+          answerResult.value[len - 1] = {
+            ...lastAnswerItem,
+            content: JSON.parse(item.message).pred.join(",")
+          }
+        } else {
+          const { off, on, pred } = JSON.parse(item.message);
+          tempSimulate = {
+            biz: 'DECISION_SIMULATE',
+            off,
+            on,
+            pred,
+            isDisable: false
+          }
+          modalData.value = tempSimulate;
+        }
+        console.log("DECISION_SIMULATE")
       }
 
       scrollToBottomIfAtBottom();
@@ -259,6 +279,9 @@ const onRegenerate = async () => {
       answerItem.loading = false;
       answerItem.delayLoading = false;
     }
+    if (tempSimulate) {
+      answerResult.value.push(tempSimulate);
+    }
   }
   catch(error) {
     console.log("exist error .....", error);
@@ -290,11 +313,30 @@ const handlerAlertOptions = (item, val, index) => {
   }
 }
 
+// 开始预测
+const handleSendSimulate = ({ simulate, table }) => {
+  const len = answerResult.value.length;
+
+  flowParams.simulate = simulate;
+  answerResult.value[len - 1].isDisable = false;
+
+  answerResult.value.push({
+    biz: 'DECISION_TABLE',
+    loading: true,
+    delayLoading: true,
+    table,
+    isDisable: false
+  })
+
+  onRegenerate();
+}
+
 // 欢迎页提交
 const handleWelcomeRecommend = question => {
   chatStore.setChatQuestion(question);
   router.push('/answer');
 }
+
 </script>
 
 <template>
@@ -325,14 +367,14 @@ const handleWelcomeRecommend = question => {
 
       <ChatWelcome title="您好,我是LibraAI工艺管控助手" card-title="常见处理方案:"
         :sub-title="[
-          '报警分析功能具备实时监测与预警机制,检测到异常情况立即触发多种报警方式,推送相关',
-          '工作人员确保问题及时处理。报警时间为每小时警报,请大家及时处理。'
+          '报警分析功能具备实时监测与预警机制,检测到异常情况推送相关工作人员确保问题及时处理。',
+          '报警时间为每小时警报,请大家及时处理。'
         ]" 
         :card-content="recommendList"
         @on-click="handleWelcomeRecommend"
         v-if="!textDataSources"
       />
-  
+
       <ChatBaseCard v-if="textDataSources">
         <div class="waring-answer-wrapper">
           <dl class="message-inner warning-info_medium ">
@@ -360,8 +402,6 @@ const handleWelcomeRecommend = question => {
         </div>
       </ChatBaseCard>
 
-      <!-- {{  answerResult.length  }} -->
-
       <section v-for="item,index in answerResult" :key="index">
         <template v-if="item.biz === 'DECISION_REPORT'">
           <ChatAnswer
@@ -393,6 +433,55 @@ const handleWelcomeRecommend = question => {
             </ul>
           </ChatBaseCard>
         </template>
+
+        <template v-if="item.biz === 'DECISION_SIMULATE'">
+          <button class="
+            px-[30px] py-[10px] mb-[20px]
+            rounded-[8px] 
+            bg-white text-[13px] 
+            text-[#5E5E5E] hover:text-[#2454FF]"
+            :disabled="item.isDisable"
+            @click="handleModelVisible"
+          >
+            水质预测推演
+          </button>
+        </template>
+        
+        <template v-if="item.biz === 'DECISION_TABLE'">
+          <ChatAnswer
+            :loading="item.loading"
+            :delay-loading="item.delayLoading"
+            :toggleVisibleIcons="false"
+          >
+            <div class="markdown-body text-[15px] break-all">
+              <strong class="block mb-[16px]">推荐指标调整:</strong>
+              <table>
+                <thead>
+                  <tr>
+                    <th v-for="text in item.table.header" :key="text">{{ text }}</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <td v-for="text in item.table.body" :key="text">{{ text }}</td>
+                  </tr>
+                </tbody>
+              </table>
+              <strong class="block mb-[16px]">预测推演结果:</strong>
+              <span>出水硝酸盐:{{ item.content }}</span>
+            </div>
+          </ChatAnswer>
+          <button class="
+            px-[30px] py-[10px] mb-[20px]
+            rounded-[8px] 
+            bg-white text-[13px] 
+            text-[#5E5E5E] hover:text-[#2454FF]"
+            :disabled="item.isDisable"
+            @click="handleModelVisible"
+          >
+            水质预测推演
+          </button>
+        </template>
       </section>
 
       <ChatAnswer
@@ -402,19 +491,13 @@ const handleWelcomeRecommend = question => {
         v-show="answerLoading"
       ></ChatAnswer>
 
-      <!-- <button class="
-        px-[30px] py-[10px] mb-[20px]
-        rounded-[8px] 
-        bg-white text-[13px] 
-        text-[#5E5E5E] hover:text-[#2454FF]"
-        @click="handleModelVisible"
-      >
-        水质预测推演
-      </button> -->
-
     </TheChatView>
   </section>
 
-  <CustomModal v-model:visible="visible"></CustomModal>
+  <CustomModal
+    v-model:visible="visible"
+    :current-data="modalData"
+    @on-submit="handleSendSimulate"
+    ></CustomModal>
 
 </template>

+ 0 - 172
src/views/analyse/WorkOrder-old.vue

@@ -1,172 +0,0 @@
-<script setup>
-import { ref, unref, computed, onMounted } from 'vue';
-import { useRoute } from 'vue-router';
-import { useMessage, NDatePicker, NInput, NButton } from 'naive-ui'
-import { useChatStore } from '@/stores/modules/chatStore';
-import { BaseButton, RecodeCardItem, TheSubMenu, TheChatView, ChatWelcome, SvgIcon } from '@/components';
-import { ChatAsk, ChatAnswer, ChatInput } from '@/components/Chat';
-import { chatApi } from '@/api/chat';
-
-import { useInfinite } from '@/composables/useInfinite';
-import { useScroll } from '@/composables/useScroll';
-import { useChat } from '@/composables/useChat';
-import { useRecommend } from '@/composables/useRecommend';
-
-// TODO: 如果这里的key不一样,将会在拆一层组件出来 - list
-const { recordList, isFetching, onScrolltolower, onReset, addHistoryRecord } = useInfinite('/front/bigModel/qa/pageList', { module: 1 });
-const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll();
-const { chatDataSource, addChat, updateChat, clearChat, updateById } = useChat();
-const { recommendList } = useRecommend({ type: 0 });
-
-
-const oneText = ref('');
-const twoText = ref('');
-
-</script>
-
-<template>
-  <section class="flex items-start h-full">
-
-    <TheSubMenu title="历史记录" @scrollToLower="onScrolltolower" :loading="isFetching">
-      <template #top>
-        <div class="create-btn px-[11px] pb-[22px]">
-          <BaseButton @click="handleCreateDialog">新建工单</BaseButton>
-        </div>
-      </template>
-
-      <div class="pr-[4px] text-[#5e5e5e]">
-        <RecodeCardItem v-for="item, index in recordList" :key="item.sessionId + index" :title="item.showVal"
-          :time="item.createTime" :data-item="item" @on-click="handleChatDetail" @on-delete="handeChatDelete" />
-      </div>
-    </TheSubMenu>
-
-    <TheChatView ref="scrollRef" :is-footer="false">
-      <ChatWelcome 
-        title="您好,我是LibraAI智慧工单助手" 
-        card-title="您可以试着问我:"
-        :sub-title="[
-          '基于大语言模型的智能数据分析助手,可以为您实现数据分析及数据解读',
-          '选择日期并填写关键信息为您生成日报工单'
-        ]"
-        @on-click="handleWelcomeRecommend"
-        v-if="1"
-      />
-
-      <div class="order-container px-[60px] py-[30px] mt-[36px] rounded-[10px] bg-[#fff]">
-        <div class="flex items-end justify-start space-x-[16px] pb-[20px] border-b-[1px] border-solid border-[#F1F1F1]">
-          <span class="text-[20px] leading-[28px] font-bold">智慧工单报告</span>
-          <span class="text-[12px] text-[#8F959C]">填写下面关键信息为您生成工单分析</span>
-        </div>
-
-        <main class="order pt-[20px] text-[#1A2029]">
-          <div class="flex items-center justify-start text-[16px] space-x-[16px]">
-            <span class="font-bold">选择时间</span>
-            <div class="w-[164px] border-[1px] border-[#EFEFF0] rounded-[8px] overflow-hidden">
-              <NDatePicker placeholder="选择日期" :readonly="true">
-                <template #date-icon>
-                  <SvgIcon name="tool-arrow-bottom"></SvgIcon>
-                </template>
-              </NDatePicker>
-            </div>
-          </div>
-
-          <div class="flex items-end justify-start my-[20px] text-[16px] space-x-[16px]">
-            <span class="font-bold leading-[22px]">报告内容</span>
-            <span class="text-[12px] text-[#8F959C] leading-[16px]">可直接点击“立即生成”输出报告,也可以在输入框内调整您要分析的内容</span>
-          </div>
-
-          <ul class="flex flex-col text-[14px]">
-            <li class="list-item"><span class="title">1、水质数据、生化数据情况</span></li>
-            <li class="list-item">
-              <p class="item-top">
-                <span class="title">2、指标数据的分析</span>
-                <span class="num">{{ oneText.length }}/100</span>
-              </p>
-               <n-input
-                class="text-[14px] border-[1px] border-[#EFEFF0] bg-[#f8f8fa] rounded-[8px]"
-                clearable
-                maxlength="100"
-                placeholder="请输入您的建议,100字内"
-                type="textarea" 
-                size="large" 
-                :autosize="{ minRows: 1, maxRows: 2 }"
-                v-model:value="oneText" 
-              />
-            </li>
-            <li class="list-item">
-              <p class="item-top">
-                <span class="title">3、根据分析法,输出分析报告</span>
-                <span class="num">{{ twoText.length }}/100</span>
-              </p>
-              <n-input
-                class="text-[14px] border-[1px] border-[#EFEFF0] bg-[#f8f8fa] rounded-[8px]"
-                clearable
-                maxlength="100"
-                placeholder="请输入您的建议,100字内"
-                type="textarea" 
-                size="large"
-                :autosize="{ minRows: 1, maxRows: 2 }"
-                v-model:value="oneText"
-              />
-            </li>
-          </ul>
-        </main>
-
-        <footer class="pt-[8px]">
-          <button class="btn-primary" @click="">立即生成</button>
-        </footer>
-      </div>
-    </TheChatView>
-  </section>
-</template>
-
-<style scoped lang="scss">
-.n-input__input-el {
-  font-size: 12px !important;
-}
-
-.list-item {
-  margin-bottom: 16px;
-
-  .title {
-    font-size: 14px;
-    font-weight: bold;
-    line-height: 20px;
-  }
-
-  .item-top {
-    display: flex;
-    justify-content: space-between;
-    margin-bottom: 10px;
-
-    .num {
-      font-size: 12px;
-      font-weight: 400;
-      color: #B0B7C0;
-    }
-  }
-}
-
-
-.btn-primary {
-  width: 88px;
-  height: 32px;
-  border-radius: 6px;
-  background-color: #2454FF;
-  font-size: 14px;
-  line-height: 32px;
-  color: #fff;
-
-  &:hover {
-    background: #1D43CC;
-  }
-}
-</style>
-
-<style lang="scss">
-.order {
-  .n-input__input-el, .n-input__placeholder {
-    font-size: 14px;
-  }
-}
-</style>

+ 76 - 41
src/views/analyse/components/CustomModal.vue

@@ -1,13 +1,71 @@
 <script setup>
-import { ref, defineModel } from 'vue';
+import { ref, defineModel, computed, unref } from 'vue';
 import { NModal, NInput } from 'naive-ui';
+import { SIMULATE_ENUM } from './config';
+import { truncateDecimals } from "@/utils/format";
+
+const props = defineProps({
+  currentData: {
+    type: Object,
+    default: () => ({})
+  }
+})
+
+const emit = defineEmits(['on-submit']);
 
 const modelVisible = defineModel('visible');
-const showModal = ref(true);
 
+const simulateData = computed(() => {
+  const data = props.currentData;
+  const usefulkeys = ['on', 'off'];
+  const resultObj = {};
+
+  usefulkeys.forEach(key => {
+    const tempArr = data[key];
+
+    resultObj[key] = tempArr.map(item => {
+      return {
+        ...item,
+        label: SIMULATE_ENUM[item.name],
+        inpVal: Array.isArray( item.value ) ? item.value.join() : item.value,
+        errMsg: ''
+      }
+    })
+  })
+  console.log("resultObj", resultObj);
+  return resultObj;
+})
+
+// 关闭弹窗
 const handleCancel = () => {
   modelVisible.value = false;
 }
+
+// 发起预测
+const handleStartReport = () => {
+  const usefulkeys = ['on', 'off'];
+  const simulate = {};
+  const table = {
+    header: [],
+    body: []
+  };
+  usefulkeys.forEach(key => {
+    simulateData.value[key].forEach(item => {
+      
+      simulate[item.name] = Array.isArray(item.value) ? item.inpVal.split(",") : item.inpVal;
+
+      table.header.push(item.label);
+      table.body.push(item.inpVal);
+    })
+  })
+  
+  console.log( simulateData.value );
+  console.log( simulate );
+  handleCancel();
+  emit('on-submit', { simulate: JSON.stringify(simulate), table })
+  console.log( "result", JSON.stringify(simulate), table );
+}
+
 </script>
 
 <template>
@@ -19,25 +77,16 @@ const handleCancel = () => {
   >
     <div class="modal-wrapper">
       <p class="header mb-[16px] font-bold text-[16px] leading-[22px]">水质预测推演 - 出水硝酸盐</p>
-
       <div class="content-card mb-[8px]">
         <p class="mb-[10px] font-bold text-[14px] leading-[20px]">可调参数</p>
         <ul class="inp-group grid grid-cols-2 gap-x-[24px]  gap-y-[8px]">
-          <li>
-            <span>碳源投加量(L/h)</span>
-            <input type="text">
-          </li>
-          <li>
-            <span>碳源投加量(L/h)</span>
-            <input type="text">
-          </li>
-          <li>
-            <span>碳源投加量(L/h)</span>
-            <input type="text">
-          </li>
-          <li>
-            <span>碳源投加量(L/h)</span>
-            <input type="text">
+          <li
+            class="flex items-center justify-start mt-[8px]" 
+            v-for="item,index in simulateData.on"
+            :key="index"
+          >
+            <span class="w-[120px] flex-shrink-0">{{ item.label }}</span>
+            <input type="text" v-model="item.inpVal">
           </li>
         </ul>
       </div>
@@ -45,25 +94,11 @@ const handleCancel = () => {
       <div class="content-card mb-[20px]">
         <p class="mb-[10px] font-bold text-[14px] leading-[20px]">相关参数</p>
         <ul class="grid grid-cols-2 gap-x-[24px]  gap-y-[10px]">
-          <li class="space-x-[8px]">
-            <span>好氧池水温</span>
-            <span>11.9</span>
-          </li>
-          <li class="space-x-[8px]">
-            <span>好氧池PH</span>
-            <span>11.9</span>
-          </li>
-          <li class="space-x-[8px]">
-            <span>好氧池硝酸盐</span>
-            <span>11.9</span>
-          </li>
-          <li class="space-x-[8px]">
-            <span>缺氧池氨氮</span>
-            <span>11.9</span>
-          </li>
-          <li class="space-x-[8px]">
-            <span>缺氧池硝酸盐</span>
-            <span>11.9</span>
+          <li class="space-x-[8px]" v-for="item,index in simulateData.off" :key="index">
+            <span class="text-[#5E5E5E]">{{ item.label }}</span>
+            <span class="text-[#1A2029] font-bold">
+              {{ item.inpVal }}
+            </span>
           </li>
         </ul>
       </div>
@@ -72,7 +107,7 @@ const handleCancel = () => {
         <p>*红色数字为建议调整数值</p>
         <div class="btn-group space-x-[16px]">
           <button class="btn btn_default" @click="handleCancel">取消</button>
-          <button class="btn btn_primary">发起预测</button>
+          <button class="btn btn_primary" @click="handleStartReport">发起预测</button>
         </div>
       </div>
     </div>
@@ -81,7 +116,7 @@ const handleCancel = () => {
 
 <style scoped lang="scss">
 .modal-wrapper {
-  width: 432px;
+  // width: 432px;
   padding: 30px 32px 20px 32px;
   border: 1px solid #fff;
   border-radius: 8px;
@@ -94,12 +129,12 @@ const handleCancel = () => {
 
     span {
       font-size: 12px;
-      color: #5E5E5E;
+      // color: #5E5E5E;
     }
 
     input {
       padding: 7px 13px;
-      margin-top: 8px;
+      // margin-top: 8px;
       border: 1px solid #D7D7D7;
       border-radius: 4px;
       background: #F8F8FA;

+ 15 - 0
src/views/analyse/components/config.js

@@ -0,0 +1,15 @@
+export const SIMULATE_ENUM = {
+  COD_in: '进水COD',
+  DO_O:         '好氧池DO (多池)',
+  MLSS:         '好氧池MLSS (多池)',
+  Q_in:         '进水流量',
+  tyjyl:        '碳源药剂投加量',
+  r:            '内回流比(多池)',
+  cltjl:        '除磷药剂投加量',
+  gwnl:         '出泥量(千泥)',
+  hycxsy_all:   '好氧硝酸盐(多池)',
+  qyan_all:     '缺氧氨氮(多池)',
+  qyckxsy_all:  '缺氧硝酸盐',
+  T:            '好氧池水温',
+  pH:           '好氧池'
+}