prc 1 年之前
父節點
當前提交
d64bd29775

+ 2 - 1
build_all.py

@@ -30,13 +30,14 @@ class BuildAll:
              self.current_dir),
             (f"conda activate {python_env_name} && Pyinstaller {pyinstaller_confirm_flag} -D server.py",
              os.path.join(self.current_dir, "server")),
-            ("npm run build:win", os.path.join(self.current_dir, "client"))
+            ("npm run build:win && echo BUILD_EXIT_WITH_NPM_RUN_END", os.path.join(self.current_dir, "client"))
         ]
 
         for cmd, cwd in commands:
             if not self.__pre_execute_check(cmd, cwd):
                 return
             self.__execute_cmd_with_pty(cmd, cwd)
+        print("Build complete!")
 
     @staticmethod
     def __pre_execute_check(cmd, cwd):

+ 1 - 1
build_and_release.py

@@ -12,7 +12,7 @@ class BuildAndRelease:
             "python clean_build_all.py",
             "python build_all.py",
             "python make_release.py",
-            "python clean_build_all.py"
+            # "python clean_build_all.py"
         ]
         self.user_input = input("请输入conda python环境的名称(例如:base): ")
         self.__readline_in_treading: bool = False

+ 0 - 8
client/electron-builder.json5

@@ -56,14 +56,6 @@
       {
         target: 'zip',
         arch: 'x64'
-      },
-      {
-        target: 'portable',
-        arch: 'x64'
-      },
-      {
-        target: 'nsis',
-        arch: 'x64'
       }
     ]
   },

+ 273 - 288
client/src/renderer/App.vue

@@ -2,64 +2,64 @@
 import { ref, onMounted, onBeforeUnmount } from 'vue'
 
 import {
-  ListNumNone,
-  ListNum1,
-  ListNum2,
-  ListNum3,
-  ListNum4,
-  ListNum5
+    ListNumNone,
+    ListNum1,
+    ListNum2,
+    ListNum3,
+    ListNum4,
+    ListNum5
 } from '@/renderer/pages/ListNum/list_num'
 
 const httpServerPort = ref<number | null>(null)
 
 onMounted(() => {
-  window.mainApi.send('msgRequestGetServerPort')
+    window.mainApi.send('msgRequestGetServerPort')
 
-  window.mainApi.receive('msgReceivedServerPort', (event, port) => {
-    httpServerPort.value = port
-  })
+    window.mainApi.receive('msgReceivedServerPort', (event, port) => {
+        httpServerPort.value = port
+    })
 })
 
 const languages = ref(['en'])
 const appVersion = ref('Unknown')
 
 const leftButtonList = () => {
-  const leftButtons = ref(['功能测试', '干扰控制', '衰减控制', '负载控制', '帮助文档'])
-  const selectedItem = ref('')
+    const leftButtons = ref(['功能测试', '干扰控制', '衰减控制', '负载控制', '帮助文档'])
+    const selectedItem = ref('')
 
-  return {
-    leftButtons,
-    selectedItem
-  }
+    return {
+        leftButtons,
+        selectedItem
+    }
 }
 
 const { leftButtons, selectedItem } = leftButtonList()
 
 const getSelectedComponent = (getSelectedItem) => {
-  switch (getSelectedItem.value) {
-    case '':
-      return ListNumNone
-    case '干扰控制':
-      //   return ListNum1
-      return ListNumNone
-    case '衰减控制':
-      return ListNum2
-    case '负载控制':
-      return ListNum3
-    case '功能测试':
-      return ListNum4
-    case '帮助文档':
-      return ListNum5
-    default:
-      return ListNumNone
-  }
+    switch (getSelectedItem.value) {
+        case '':
+            return ListNumNone
+        case '干扰控制':
+            // return ListNum1
+            return ListNumNone
+        case '衰减控制':
+            return ListNum2
+        case '负载控制':
+            return ListNum3
+        case '功能测试':
+            return ListNum4
+        case '帮助文档':
+            return ListNum5
+        default:
+            return ListNumNone
+    }
 }
 
 const selectedComponent = ref(getSelectedComponent(selectedItem))
 
 const updateSelectedLeftButton = (buttonName: string) => {
-  selectedItem.value = buttonName
-  selectedComponent.value = getSelectedComponent(selectedItem)
+    selectedItem.value = buttonName
+    selectedComponent.value = getSelectedComponent(selectedItem)
 }
 
 // const minimizeWindow = () => {
@@ -75,12 +75,12 @@ const updateSelectedLeftButton = (buttonName: string) => {
 // }
 
 const getIconURL = () => {
-  return {
-    iconMinURL: './icons/icon-min-white.png',
-    iconMaxURL: './icons/icon-max-white.png',
-    iconCloseURL: './icons/icon-close-white.png',
-    iconRestoreURL: './icons/icon-max-white.png'
-  }
+    return {
+        iconMinURL: './icons/icon-min-white.png',
+        iconMaxURL: './icons/icon-max-white.png',
+        iconCloseURL: './icons/icon-close-white.png',
+        iconRestoreURL: './icons/icon-max-white.png'
+    }
 }
 
 const iconURL = getIconURL()
@@ -90,11 +90,11 @@ const iconSaveWhite = './iconlib/google/save_white.png'
 const iconSave = ref(iconSaveWhite)
 
 const iconSaveUseBlack = () => {
-  iconSave.value = iconSaveBlack
+    iconSave.value = iconSaveBlack
 }
 
 const iconSaveUseWhite = () => {
-  iconSave.value = iconSaveWhite
+    iconSave.value = iconSaveWhite
 }
 
 const iconOpenBlack = './iconlib/google/folder_open_black.png'
@@ -102,11 +102,11 @@ const iconOpenWhite = './iconlib/google/folder_open_white.png'
 const iconOpen = ref(iconOpenWhite)
 
 const iconOpenUseBlack = () => {
-  iconOpen.value = iconOpenBlack
+    iconOpen.value = iconOpenBlack
 }
 
 const iconOpenUseWhite = () => {
-  iconOpen.value = iconOpenWhite
+    iconOpen.value = iconOpenWhite
 }
 
 const iconSettingBlack = './iconlib/google/settings_black.png'
@@ -114,72 +114,60 @@ const iconSettingWhite = './iconlib/google/settings_white.png'
 const iconSetting = ref(iconSettingWhite)
 
 const iconSettingUseBlack = () => {
-  iconSetting.value = iconSettingBlack
+    iconSetting.value = iconSettingBlack
 }
 
 const iconSettingUseWhite = () => {
-  iconSetting.value = iconSettingWhite
+    iconSetting.value = iconSettingWhite
 }
 
 // 初始化为当前时间的24小时制
 const currentDateTime = ref(getCurrentTime())
 
 function getCurrentTime() {
-  const now = new Date()
-  return now.toLocaleTimeString('en-US', { hour12: false })
+    const now = new Date()
+    return now.toLocaleTimeString('en-US', { hour12: false })
 }
 
 let interval
 onMounted(() => {
-  interval = setInterval(() => {
-    currentDateTime.value = getCurrentTime()
-  }, 1000)
+    interval = setInterval(() => {
+        currentDateTime.value = getCurrentTime()
+    }, 1000)
 })
 
 onBeforeUnmount(() => {
-  clearInterval(interval)
+    clearInterval(interval)
 })
 </script>
 
 <template>
-  <div id="main-screen-app" class="main-screen">
-    <div class="top-bar">
-      <div class="title">
-        <div class="title-text"> </div>
-        <div class="button-bar">
-          <button
-            class="button-unlock"
-            @mousedown="iconOpenUseBlack"
-            @mouseup="iconOpenUseWhite"
-            @mouseleave="iconOpenUseWhite"
-          >
-            <img :src="iconOpen" class="icon" id="icon-open" />
-            <div class="text">打开项目</div>
-          </button>
-          <button
-            class="button-unlock"
-            @mousedown="iconSaveUseBlack"
-            @mouseup="iconSaveUseWhite"
-            @mouseleave="iconSaveUseWhite"
-          >
-            <img :src="iconSave" id="icon-save" class="icon" />
-            <div class="text">保存项目</div>
-          </button>
-          <div class="middle"></div>
-          <button
-            class="button-unlock"
-            @mousedown="iconSettingUseBlack"
-            @mouseup="iconSettingUseWhite"
-            @mouseleave="iconSettingUseWhite"
-          >
-            <img :src="iconSetting" id="icon-setting" class="icon" />
-            <div class="text">偏好设置</div>
-          </button>
-        </div>
-      </div>
-      <div class="middle"></div>
-      <div class="window-buttons-zone">
-        <!-- <button id="min" class="window-buttons" @click="minimizeWindow()">
+    <div id="main-screen-app" class="main-screen">
+        <div class="top-bar">
+            <div class="title">
+                <div class="title-text"> </div>
+                <div class="button-bar">
+                    <button class="button-unlock" @mousedown="iconOpenUseBlack" @mouseup="iconOpenUseWhite"
+                        @mouseleave="iconOpenUseWhite">
+                        <img :src="iconOpen" class="icon" id="icon-open" />
+                        <div class="text">打开项目</div>
+                    </button>
+                    <button class="button-unlock" @mousedown="iconSaveUseBlack" @mouseup="iconSaveUseWhite"
+                        @mouseleave="iconSaveUseWhite">
+                        <img :src="iconSave" id="icon-save" class="icon" />
+                        <div class="text">保存项目</div>
+                    </button>
+                    <div class="middle"></div>
+                    <button class="button-unlock" @mousedown="iconSettingUseBlack" @mouseup="iconSettingUseWhite"
+                        @mouseleave="iconSettingUseWhite">
+                        <img :src="iconSetting" id="icon-setting" class="icon" />
+                        <div class="text">偏好设置</div>
+                    </button>
+                </div>
+            </div>
+            <div class="middle"></div>
+            <div class="window-buttons-zone">
+                <!-- <button id="min" class="window-buttons" @click="minimizeWindow()">
                     <img :src="iconURL.iconMinURL" alt="error" class="icons">
                 </button>
                 <button id="max" class="window-buttons" @click="maximizeWindow()">
@@ -188,287 +176,284 @@ onBeforeUnmount(() => {
                 <button id="close" class="window-buttons" @click="closeWindow()">
                     <img :src="iconURL.iconCloseURL" alt="error" class="icons">
                 </button> -->
-      </div>
-    </div>
-    <div class="content">
-      <div class="left-side">
-        <div class="container">
-          <div class="title"> 测试项目 </div>
-          <div v-for="currentButton in leftButtons" :key="currentButton" class="row">
-            <div class="col">
-              <button
-                class="button"
-                :class="{ active: selectedItem === currentButton }"
-                @click="updateSelectedLeftButton(currentButton)"
-              >
-                {{ currentButton }}
-              </button>
             </div>
-          </div>
         </div>
-      </div>
-      <div class="right-side">
-        <div class="container">
-          <keep-alive>
-            <component :is="selectedComponent"></component>
-          </keep-alive>
+        <div class="content">
+            <div class="left-side">
+                <div class="container">
+                    <div class="title"> 测试项目 </div>
+                    <div v-for="currentButton in leftButtons" :key="currentButton" class="row">
+                        <div class="col">
+                            <button class="button" :class="{ active: selectedItem === currentButton }"
+                                @click="updateSelectedLeftButton(currentButton)">
+                                {{ currentButton }}
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="right-side">
+                <div class="container">
+                    <keep-alive>
+                        <component :is="selectedComponent"></component>
+                    </keep-alive>
+                </div>
+            </div>
+        </div>
+        <div class="status-bar">
+            <div class="running-status"> Ready </div>
+            <div class="server-status"> Server Port: {{ httpServerPort }} </div>
+            <div class="middle"></div>
+            <div class="current-datetime"> 当前时间: {{ currentDateTime }} </div>
+            <div class="version"> v1.0.0 </div>
         </div>
-      </div>
-    </div>
-    <div class="status-bar">
-      <div class="running-status"> Ready </div>
-      <div class="server-status"> Server Port: {{ httpServerPort }} </div>
-      <div class="middle"></div>
-      <div class="current-datetime"> 当前时间: {{ currentDateTime }} </div>
-      <div class="version"> v1.0.0 </div>
     </div>
-  </div>
 </template>
 
 <style>
 html {
-  overflow-y: hidden !important;
-  user-select: none;
+    overflow-y: hidden !important;
+    user-select: none;
 }
 
 html,
 body {
-  overflow-y: hidden !important;
-  width: 100%;
-  height: 100%;
+    overflow-y: hidden !important;
+    width: 100%;
+    height: 100%;
 }
 
 .main-screen {
-  margin: 0;
-  padding: 0;
-  height: 100vh;
-  display: flex;
-  flex-direction: column;
+    margin: 0;
+    padding: 0;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
 }
 
 .top-bar {
-  width: 100%;
-  height: 45px;
-  background-color: #2673e3;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
+    width: 100%;
+    height: 45px;
+    background-color: #2673e3;
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    align-items: center;
 }
 
 .top-bar,
 .top-bar * {
-  -webkit-app-region: drag;
+    -webkit-app-region: drag;
 }
 
 .top-bar .title {
-  width: 100%;
-  margin-left: 15px;
-  color: white;
-  font-size: 20px;
-  font-weight: 500;
+    width: 100%;
+    margin-left: 15px;
+    color: white;
+    font-size: 20px;
+    font-weight: 500;
 }
 
 .top-bar .middle {
-  flex: 1;
+    flex: 1;
 }
 
 .top-bar .window-buttons-zone {
-  margin-right: 8px;
+    margin-right: 8px;
 }
 
 .top-bar .window-buttons {
-  -webkit-app-region: no-drag;
-  width: 40px;
-  height: 30px;
+    -webkit-app-region: no-drag;
+    width: 40px;
+    height: 30px;
 }
 
 .top-bar .window-buttons .icons {
-  width: 12px;
-  height: 12px;
-  margin: 0 auto;
+    width: 12px;
+    height: 12px;
+    margin: 0 auto;
 }
 
 .top-bar .window-buttons:hover {
-  background-color: rgba(255, 255, 255, 0.2);
+    background-color: rgba(255, 255, 255, 0.2);
 }
 
 .top-bar {
-  .button-bar {
+    .button-bar {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+        font-size: 16px;
+        font-weight: 500;
+    }
+
+    .button-bar .button-lock,
+    .button-bar .button-unlock {
+        width: auto;
+        height: 35px;
+        padding-left: 12px;
+        padding-right: 12px;
+        border-radius: 5px;
+        margin-right: 3px;
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+        color: white;
+    }
+
+    .button-bar .button-lock:hover,
+    .button-bar .button-unlock:hover {
+        font-weight: 500;
+        text-decoration: underline;
+    }
+
+    .button-bar .button-lock.active,
+    .button-bar .button-unlock:active {
+        color: black;
+        background-color: rgba(255, 255, 255, 0.2);
+        font-weight: 500;
+    }
+
+    .icon {
+        width: 20px;
+        height: 20px;
+        margin: 0px;
+        margin-right: 5px;
+        margin-left: -5px;
+        padding: 0px;
+    }
+
+    .button-bar .middle {
+        flex: 1;
+        width: 100%;
+    }
+}
+
+.content {
     width: 100%;
-    height: 100%;
+    background-color: #e9edf5;
+    flex: 1;
     display: flex;
     flex-direction: row;
-    justify-content: flex-start;
-    align-items: center;
-    font-size: 16px;
-    font-weight: 500;
-  }
+    overflow-y: auto;
+}
 
-  .button-bar .button-lock,
-  .button-bar .button-unlock {
-    width: auto;
-    height: 35px;
-    padding-left: 12px;
-    padding-right: 12px;
-    border-radius: 5px;
-    margin-right: 3px;
+.status-bar {
+    width: 100%;
+    height: 23px;
+    background-color: #2673e3;
     display: flex;
     flex-direction: row;
-    justify-content: flex-start;
+    justify-content: center;
     align-items: center;
     color: white;
-  }
-
-  .button-bar .button-lock:hover,
-  .button-bar .button-unlock:hover {
-    font-weight: 500;
-    text-decoration: underline;
-  }
-
-  .button-bar .button-lock.active,
-  .button-bar .button-unlock:active {
-    color: black;
-    background-color: rgba(255, 255, 255, 0.2);
-    font-weight: 500;
-  }
-
-  .icon {
-    width: 20px;
-    height: 20px;
-    margin: 0px;
-    margin-right: 5px;
-    margin-left: -5px;
-    padding: 0px;
-  }
-
-  .button-bar .middle {
-    flex: 1;
-    width: 100%;
-  }
-}
-
-.content {
-  width: 100%;
-  background-color: #e9edf5;
-  flex: 1;
-  display: flex;
-  flex-direction: row;
-  overflow-y: auto;
+    font-size: 13px;
 }
 
 .status-bar {
-  width: 100%;
-  height: 23px;
-  background-color: #2673e3;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  color: white;
-  font-size: 13px;
-}
+    .running-status {
+        margin-left: 12px;
+    }
 
-.status-bar {
-  .running-status {
-    margin-left: 12px;
-  }
+    .server-status {
+        margin-left: 15px;
+    }
 
-  .server-status {
-    margin-left: 15px;
-  }
+    .middle {
+        flex: 1;
+    }
 
-  .middle {
-    flex: 1;
-  }
-
-  .current-datetime {
-    margin-right: 15px;
-  }
+    .current-datetime {
+        margin-right: 15px;
+    }
 
-  .version {
-    margin-right: 12px;
-  }
+    .version {
+        margin-right: 12px;
+    }
 }
 
 .right-side {
-  flex: 1;
-  background-color: rgba(0, 0, 0, 0);
-  height: 100%;
-  overflow-y: hidden;
+    flex: 1;
+    background-color: rgba(0, 0, 0, 0);
+    height: 100%;
+    overflow-y: hidden;
 }
 
 .right-side .container {
-  width: 100%;
-  height: 100%;
-  overflow-y: auto;
+    width: 100%;
+    height: 100%;
+    overflow-y: auto;
 }
 
 .left-side {
-  background-color: rgba(0, 0, 0, 0);
-  height: 100%;
-  width: auto;
-  overflow-y: hidden;
-  overflow-x: hidden;
-  border-right: 1px solid #dfdfdf;
+    background-color: rgba(0, 0, 0, 0);
+    height: 100%;
+    width: auto;
+    overflow-y: hidden;
+    overflow-x: hidden;
+    border-right: 1px solid #dfdfdf;
 }
 
 .left-side .container {
-  /* margin-top: 20px; */
-  margin-bottom: 20px;
-  /* margin-left: 20px; */
-  /* padding-top: 8px; */
-  width: 100%;
-  height: 100%;
-  background-color: white;
-  overflow-x: hidden;
-  overflow-y: auto;
-  display: flex;
-  align-items: start;
-  flex-direction: column;
-  /* border-radius: 10px; */
+    /* margin-top: 20px; */
+    margin-bottom: 20px;
+    /* margin-left: 20px; */
+    /* padding-top: 8px; */
+    width: 100%;
+    height: 100%;
+    background-color: white;
+    overflow-x: hidden;
+    overflow-y: auto;
+    display: flex;
+    align-items: start;
+    flex-direction: column;
+    /* border-radius: 10px; */
 }
 
 .left-side .container .title {
-  width: 100%;
-  height: 25px;
-  font-size: 15px;
-  font-weight: 500;
-  color: black;
-  background-color: #dee2ec;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  padding-left: 20px;
+    width: 100%;
+    height: 25px;
+    font-size: 15px;
+    font-weight: 500;
+    color: black;
+    background-color: #dee2ec;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    padding-left: 20px;
 }
 
 .left-side .title-text {
-  margin-left: 30px;
-  color: black;
+    margin-left: 30px;
+    color: black;
 }
 
 .left-side .container .button {
-  /* width: 180px; */
-  width: 150px;
-  height: 35px;
-  font-size: 15px;
-  /* border-radius: 10px; */
-  background-color: rgba(0, 0, 0, 0);
-  box-shadow: none;
-  text-align: left;
-  padding-left: 20px;
-  color: gray;
+    /* width: 180px; */
+    width: 150px;
+    height: 35px;
+    font-size: 15px;
+    /* border-radius: 10px; */
+    background-color: rgba(0, 0, 0, 0);
+    box-shadow: none;
+    text-align: left;
+    padding-left: 20px;
+    color: gray;
 }
 
 .left-side .container .button:hover {
-  background-color: #ffffff;
-  color: black;
-  font-weight: 500;
+    background-color: #ffffff;
+    color: black;
+    font-weight: 500;
 }
 
 .left-side .container .button.active {
-  background-color: #2673e3;
-  color: white;
-  font-weight: 500;
+    background-color: #2673e3;
+    color: white;
+    font-weight: 500;
 }
 </style>

+ 779 - 495
client/src/renderer/pages/ListNum/ListNum1.vue

@@ -3,118 +3,119 @@ import { onMounted, ref, watch, onBeforeUnmount } from 'vue'
 import axios from 'axios'
 
 import Progress from '@/renderer/pages/ListNum/ColorfulProgress.vue'
+import { el } from 'vuetify/lib/locale/index.mjs';
 
 const httpServerPort = ref<number | null>(null)
 
 onMounted(() => {
-  window.mainApi.send('msgRequestGetServerPort')
+    window.mainApi.send('msgRequestGetServerPort')
 
-  window.mainApi.receive('msgReceivedServerPort', (event, port) => {
-    httpServerPort.value = port
-  })
+    window.mainApi.receive('msgReceivedServerPort', (event, port) => {
+        httpServerPort.value = port
+    })
 })
 
 class ProgressBarHandler {
-  fixedNumber = 3
-  percent = ref(0)
-  maxNumber = ref(100)
-  progressWidth = ref(10)
-  targetValue = ref(0.0)
-  targetValueString = ref(this.percent.value.toFixed(this.fixedNumber))
-
-  constructor(setMaxNumber: number, setDefaultPercent: number) {
-    this.maxNumber.value = setMaxNumber
-    this.percent.value = setDefaultPercent
-    this.updatePercentToTargetValue()
-
-    watch(this.targetValue, (newPercent) => {
-      this.updateTargetValueString(newPercent)
-    })
+    fixedNumber = 3
+    percent = ref(0)
+    maxNumber = ref(100)
+    progressWidth = ref(10)
+    targetValue = ref(0.0)
+    targetValueString = ref(this.percent.value.toFixed(this.fixedNumber))
+
+    constructor(setMaxNumber: number, setDefaultPercent: number) {
+        this.maxNumber.value = setMaxNumber
+        this.percent.value = setDefaultPercent
+        this.updatePercentToTargetValue()
+
+        watch(this.targetValue, (newPercent) => {
+            this.updateTargetValueString(newPercent)
+        })
+
+        watch(this.percent, (newPercent) => {
+            this.updateTargetValue(newPercent)
+        })
+    }
 
-    watch(this.percent, (newPercent) => {
-      this.updateTargetValue(newPercent)
-    })
-  }
-
-  updatePercentToTargetValue() {
-    this.updateTargetValueString(this.percent.value)
-    this.updateTargetValue(this.targetValue.value)
-  }
-
-  updateTargetValue(newValue: number) {
-    this.targetValue.value = this.processValue(0.01 * this.maxNumber.value * newValue)
-  }
-
-  updateTargetValueString(newValue: number) {
-    this.targetValueString.value = this.processValueStringFormat(newValue)
-  }
-
-  processValue(rawValue: number): number {
-    const processedValue = Math.round(rawValue / 0.5) * 0.5
-    return +processedValue.toFixed(this.fixedNumber)
-  }
-
-  processValueStringFormat(num: number): string {
-    const integerPart = Math.floor(num)
-    const decimalPart = num - integerPart
-    const integerString = integerPart < 10 ? '0' + integerPart : '' + integerPart
-    const decimalString = decimalPart.toFixed(this.fixedNumber).slice(2)
-    return integerString + '.' + decimalString
-  }
-
-  progressMouseUp() {
-    this.progressWidth.value = 10
-  }
-
-  progressMouseOver() {
-    this.progressWidth.value = 20
-  }
-
-  progressMouseLeave() {
-    this.progressWidth.value = 10
-  }
-
-  progressOnIncrease(scale: number) {
-    const res = this.percent.value + scale
-    this.percent.value = res > 100 ? 100 : res
-  }
-
-  progressOnDecline(scale: number) {
-    const res = this.percent.value - scale
-    this.percent.value = res < 0 ? 0 : res
-  }
-
-  progressMouseDown(event: MouseEvent) {
-    const adjustLine = event.currentTarget as HTMLElement
-    const rect = adjustLine.getBoundingClientRect()
-    const initialX = event.clientX
-
-    const updatePercent = (e: MouseEvent) => {
-      let x = e.clientX - rect.left
-      const dragRange = 0.8 * rect.width
-      const dragStart = 0.1 * rect.width
-      x = Math.max(Math.min(x, dragStart + dragRange), dragStart)
-      this.percent.value = ((x - dragStart) / dragRange) * 100
-    }
-
-    const moveHandler = (e: MouseEvent) => {
-      if (e.clientX > initialX) {
-        this.progressOnIncrease(((e.clientX - initialX) / rect.width) * 100)
-      } else {
-        this.progressOnDecline(((initialX - e.clientX) / rect.width) * 100)
-      }
-      updatePercent(e)
-    }
-
-    const upHandler = () => {
-      document.removeEventListener('mousemove', moveHandler)
-      document.removeEventListener('mouseup', upHandler)
-    }
-
-    document.addEventListener('mousemove', moveHandler)
-    document.addEventListener('mouseup', upHandler)
-    updatePercent(event)
-  }
+    updatePercentToTargetValue() {
+        this.updateTargetValueString(this.percent.value)
+        this.updateTargetValue(this.targetValue.value)
+    }
+
+    updateTargetValue(newValue: number) {
+        this.targetValue.value = this.processValue(0.01 * this.maxNumber.value * newValue)
+    }
+
+    updateTargetValueString(newValue: number) {
+        this.targetValueString.value = this.processValueStringFormat(newValue)
+    }
+
+    processValue(rawValue: number): number {
+        const processedValue = Math.round(rawValue / 0.5) * 0.5
+        return +processedValue.toFixed(this.fixedNumber)
+    }
+
+    processValueStringFormat(num: number): string {
+        const integerPart = Math.floor(num)
+        const decimalPart = num - integerPart
+        const integerString = integerPart < 10 ? '0' + integerPart : '' + integerPart
+        const decimalString = decimalPart.toFixed(this.fixedNumber).slice(2)
+        return integerString + '.' + decimalString
+    }
+
+    progressMouseUp() {
+        this.progressWidth.value = 10
+    }
+
+    progressMouseOver() {
+        this.progressWidth.value = 20
+    }
+
+    progressMouseLeave() {
+        this.progressWidth.value = 10
+    }
+
+    progressOnIncrease(scale: number) {
+        const res = this.percent.value + scale
+        this.percent.value = res > 100 ? 100 : res
+    }
+
+    progressOnDecline(scale: number) {
+        const res = this.percent.value - scale
+        this.percent.value = res < 0 ? 0 : res
+    }
+
+    progressMouseDown(event: MouseEvent) {
+        const adjustLine = event.currentTarget as HTMLElement
+        const rect = adjustLine.getBoundingClientRect()
+        const initialX = event.clientX
+
+        const updatePercent = (e: MouseEvent) => {
+            let x = e.clientX - rect.left
+            const dragRange = 0.8 * rect.width
+            const dragStart = 0.1 * rect.width
+            x = Math.max(Math.min(x, dragStart + dragRange), dragStart)
+            this.percent.value = ((x - dragStart) / dragRange) * 100
+        }
+
+        const moveHandler = (e: MouseEvent) => {
+            if (e.clientX > initialX) {
+                this.progressOnIncrease(((e.clientX - initialX) / rect.width) * 100)
+            } else {
+                this.progressOnDecline(((initialX - e.clientX) / rect.width) * 100)
+            }
+            updatePercent(e)
+        }
+
+        const upHandler = () => {
+            document.removeEventListener('mousemove', moveHandler)
+            document.removeEventListener('mouseup', upHandler)
+        }
+
+        document.addEventListener('mousemove', moveHandler)
+        document.addEventListener('mouseup', upHandler)
+        updatePercent(event)
+    }
 }
 
 const valueBarHandler = new ProgressBarHandler(100, 10)
@@ -126,468 +127,751 @@ let initialHeight = 0 // 开始调整时的元素高度
 const isDragging = ref(false)
 
 const startResize = (event: MouseEvent) => {
-  initialY = event.clientY
-  initialHeight = height.value
-  isDragging.value = true // 设置为正在拖动
+    initialY = event.clientY
+    initialHeight = height.value
+    isDragging.value = true // 设置为正在拖动
 
-  document.addEventListener('mousemove', onResize)
-  document.addEventListener('mouseup', stopResize)
+    document.addEventListener('mousemove', onResize)
+    document.addEventListener('mouseup', stopResize)
 }
 
 const onResize = (event: MouseEvent) => {
-  const deltaY = initialY - event.clientY // 计算鼠标的垂直移动距离
-  height.value = initialHeight + deltaY // 调整元素的高度
+    const deltaY = initialY - event.clientY // 计算鼠标的垂直移动距离
+    height.value = initialHeight + deltaY // 调整元素的高度
 }
 
 const stopResize = () => {
-  document.removeEventListener('mousemove', onResize)
-  document.removeEventListener('mouseup', stopResize)
-  isDragging.value = false // 设置为停止拖动
+    document.removeEventListener('mousemove', onResize)
+    document.removeEventListener('mouseup', stopResize)
+    isDragging.value = false // 设置为停止拖动
 }
 
 const terminalOutput = ref<string[]>([])
 
 // 定义一个方法,允许在组件内部推送内容到terminalOutput数组
 const terminalPush = (content: string) => {
-  terminalOutput.value.push(content)
+    terminalOutput.value.push(content)
 }
-
+//  {{ resultFreqValue }} {{ selectedFreqUnit }}, {{ resultVoltageValue }} {{selectedVoltageUnit }}
 const setDeviceValue = async (targetDeviceValue: string) => {
-  try {
-    terminalPush(`[干扰注入器] 尝试将干扰设置为 ${targetDeviceValue} Ω`)
-    const params = {
-      value: targetDeviceValue
-    }
-    const url = `http://127.0.0.1:${httpServerPort.value}/serial_device/cnc/set`
-    const response = await axios.get(url, { params })
-    const ifSetSuccess = response.data
-    if (ifSetSuccess === 'True' || ifSetSuccess === 'true') {
-      terminalPush(`[干扰注入器] 干扰成功调整为 ${targetDeviceValue} Ω`)
-    } else {
-      terminalPush(`[干扰注入器] 干扰器调整失败`)
-    }
-  } catch (error) {
-    terminalPush(`[干扰注入器] 干扰器调整失败:${error}`)
-  }
+    try {
+        terminalPush(`[干扰注入器] 尝试将干扰设置为 ${selectedWaveformType.value}, ${resultFreqValue} ${selectedFreqUnit.value}, ${resultVoltageValue} ${selectedVoltageUnit.value}, CH1: ${enableCH1.value}, CH2: ${enableCH2.value}`)
+        const params = {
+            value: targetDeviceValue
+        }
+        const url = `http://127.0.0.1:${httpServerPort.value}/serial_device/cnc/set`
+        const response = await axios.get(url, { params })
+        const ifSetSuccess = response.data
+        if (ifSetSuccess === 'True' || ifSetSuccess === 'true') {
+            terminalPush(`[干扰注入器] 干扰调整成功`)
+        } else {
+            terminalPush(`[干扰注入器] 干扰器调整失败`)
+        }
+    } catch (error) {
+        terminalPush(`[干扰注入器] 干扰器调整失败:${error}`)
+    }
 }
 
 const updateDeviceValue = () => {
-  setDeviceValue(valueBarHandler.targetValueString.value)
+    if (tipWord.value === tipWordAllCorrect) {
+        setDeviceValue(valueBarHandler.targetValueString.value)
+    }
+    else {
+        terminalPush(`[干扰注入器] 配置错误,取消应用配置`)
+    }
+}
+
+const selectedWaveformType = ref('SIN')
+
+const updateWaveformType = (selectedType: string) => {
+    selectedWaveformType.value = selectedType
+}
+
+const selectedFreqUnit = ref('MHz')
+
+const updateFreqUnit = (selectedUnit: string) => {
+    selectedFreqUnit.value = selectedUnit
+}
+
+const selectedVoltageUnit = ref('Vpp')
+
+const updateVoltageUnit = (selectedValue: string) => {
+    selectedVoltageUnit.value = selectedValue
+}
+
+const inputVoltageValue = ref('')
+
+const handleInputVoltageValue = () => {
+    checkVoltageInputUpdate()
+}
+
+const inputFreqValue = ref('')
+
+const handleInputFreqValue = () => {
+    checkFreqInputUpdate()
+}
+
+watch(inputVoltageValue, (newVal, oldVal) => {
+    checkVoltageInputUpdate()
+})
+
+watch(inputFreqValue, (newVal, oldVal) => {
+    checkFreqInputUpdate()
+})
+
+const enableCH1 = ref(false)
+
+const updateEnableCH1 = () => {
+    enableCH1.value = !enableCH1.value
+}
+
+const enableCH2 = ref(false)
+
+const updateEnableCH2 = () => {
+    enableCH2.value = !enableCH2.value
+}
+
+var resultVoltageValue: number = 0
+var resultFreqValue: number = 0
+
+const tipWordAllCorrect: string = '配置一切正常!'
+const tipWordTypeInvalidVoltage: string = '输入的电压必须是一个合法的数字!'
+const tipWordTypeInvalidFreq: string = '输入的频率必须是一个合法的数字!'
+const tipWordTooLargeOrTooSmallVoltage: string = '输入电压过大或过小!'
+const tipWordTooLargeOrTooSmallFreq: string = '输入频率过大或过小!'
+const tipWordTooMuchDecimalPlacesVoltage: string = '输入电压最多允许三位小数!'
+const tipWordTooMuchDecimalPlacesFreq: string = '输入频率最多允许三位小数!'
+
+const tipWordColorBlack: string = 'black'
+const tipWordColorRed: string = 'red'
+
+const tipWord = ref(tipWordTypeInvalidFreq)
+const tipWordColor = ref(tipWordColorRed)
+
+const tipWordVoltageBuffer = ref(tipWordTypeInvalidVoltage)
+const tipWordFreqBuffer = ref(tipWordTypeInvalidFreq)
+
+const updateTipWord = () => {
+    if (tipWordVoltageBuffer.value === tipWordAllCorrect && tipWordFreqBuffer.value === tipWordAllCorrect) {
+        tipWord.value = tipWordAllCorrect
+    }
+    else if (tipWordVoltageBuffer.value === tipWordAllCorrect) {
+        tipWord.value = tipWordFreqBuffer.value
+    }
+    else if (tipWordFreqBuffer.value === tipWordAllCorrect) {
+        tipWord.value = tipWordVoltageBuffer.value
+    }
+    else {
+        tipWord.value = tipWordFreqBuffer.value
+    }
+    if (tipWord.value === tipWordAllCorrect) {
+        tipWordColor.value = tipWordColorBlack
+    }
+    else {
+        tipWordColor.value = tipWordColorRed
+    }
+}
+
+function checkVoltageInputUpdate() {
+    const stringNumber = stringToNumber(inputVoltageValue.value)
+    if (stringNumber === null) {
+        tipWordVoltageBuffer.value = tipWordTypeInvalidVoltage
+    }
+    else if (stringNumber > 1000 || stringNumber < 0.001) {
+        tipWordVoltageBuffer.value = tipWordTooLargeOrTooSmallVoltage
+    }
+    else if (!hasThreeOrLessDecimalPlaces(stringNumber)) {
+        tipWordVoltageBuffer.value = tipWordTooMuchDecimalPlacesVoltage
+    }
+    else {
+        tipWordVoltageBuffer.value = tipWordAllCorrect
+    }
+    if (tipWordVoltageBuffer.value === tipWordAllCorrect) {
+        resultVoltageValue = stringNumber as any as number
+    }
+    else {
+        resultVoltageValue = 0
+    }
+    updateTipWord()
+}
+
+function checkFreqInputUpdate() {
+    const stringNumber = stringToNumber(inputFreqValue.value)
+    if (stringNumber === null) {
+        tipWordFreqBuffer.value = tipWordTypeInvalidVoltage
+        resultFreqValue = 0
+    }
+    else if (stringNumber > 1000 || stringNumber < 0.001) {
+        tipWordFreqBuffer.value = tipWordTooLargeOrTooSmallFreq
+    }
+    else if (!hasThreeOrLessDecimalPlaces(stringNumber)) {
+        tipWordFreqBuffer.value = tipWordTooMuchDecimalPlacesFreq
+    }
+    else {
+        tipWordFreqBuffer.value = tipWordAllCorrect
+        resultFreqValue = stringNumber
+    }
+    if (tipWordFreqBuffer.value === tipWordAllCorrect) {
+        resultFreqValue = stringNumber as any as number
+    }
+    else {
+        resultFreqValue = 0
+    }
+    updateTipWord()
+}
+
+function hasThreeOrLessDecimalPlaces(num: number): boolean {
+    const parts = num.toString().split(".");
+    if (parts.length !== 2) {
+        // 没有小数点,所以小数点后的位数为0
+        return true;
+    }
+
+    return parts[1].length <= 3;
+}
+
+function stringToNumber(input: string): number | null {
+    // 检查是否是空字符串
+    if (input.trim() === "") {
+        return null;
+    }
+
+    // 尝试解析数字
+    const parsedNumber = parseFloat(input);
+
+    // 检查结果是否是NaN或者解析后的数字与原始输入不同
+    if (isNaN(parsedNumber) || parsedNumber.toString() !== input.trim()) {
+        return null;
+    }
+
+    return parsedNumber;
 }
+
+
 </script>
 
 <template>
-  <div class="list-page-1">
-    <div class="page">
-      <div class="page-up">
-        <div class="control-zone">
-          <div class="title">
-            <div class="text">电磁干扰注入器: {{ valueBarHandler.targetValueString.value }} Ω</div>
-          </div>
-          <div class="config-zone">
-            <div class="text-line">调整:个位 / 十位</div>
-            <div
-              class="adjust-line"
-              @mouseup="valueBarHandler.progressMouseUp"
-              @mousedown="valueBarHandler.progressMouseDown"
-              @mouseover="valueBarHandler.progressMouseOver"
-              @mouseleave="valueBarHandler.progressMouseLeave"
-            >
-              <Progress
-                :width="'80%'"
-                :percent="valueBarHandler.percent.value"
-                :stroke-width="valueBarHandler.progressWidth.value"
-                :stroke-color="{
-                  '0%': '#108ee9',
-                  '100%': '#87d068',
-                  direction: 'right'
-                }"
-                :show-info="false"
-              />
-            </div>
-            <div class="btn-zone">
-              <div @click="updateDeviceValue" class="btn">
-                <div class="text">应用配置</div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-      <div class="page-down">
-        <div class="top-bar">
-          <div @mousedown="startResize" class="resizer" :class="{ dragging: isDragging }">
-            <div class="flag-bar">
-              <div class="text">测试输出终端</div>
-            </div>
-            <div class="middle"></div>
-            <div class="last-time">
-              <div class="text"></div>
+    <div class="list-page-1">
+        <div class="page">
+            <div class="page-up">
+                <div class="control-zone">
+                    <div class="title">
+                        <div class="text">电磁干扰注入器: {{ resultFreqValue }} {{ selectedFreqUnit }}, {{ resultVoltageValue }} {{
+                            selectedVoltageUnit }}
+                        </div>
+                    </div>
+                    <div class="config-zone">
+                        <div class="btn-zone">
+                            <div @click="updateWaveformType('SIN')"
+                                :class="{ 'btn-selected': selectedWaveformType === 'SIN' }" class="btn-narrow">
+                                <div class="text">正弦波</div>
+                            </div>
+                            <div @click="updateWaveformType('SQU')"
+                                :class="{ 'btn-selected': selectedWaveformType === 'SQU' }" class="btn-narrow">
+                                <div class="text">方波</div>
+                            </div>
+                            <div @click="updateWaveformType('RAMP')"
+                                :class="{ 'btn-selected': selectedWaveformType === 'RAMP' }" class="btn-narrow">
+                                <div class="text">锯齿波</div>
+                            </div>
+                            <div @click="updateWaveformType('PULS')"
+                                :class="{ 'btn-selected': selectedWaveformType === 'PULS' }" class="btn-narrow">
+                                <div class="text">脉冲波</div>
+                            </div>
+                            <div @click="updateWaveformType('NOIS')"
+                                :class="{ 'btn-selected': selectedWaveformType === 'NOIS' }" class="btn-narrow">
+                                <div class="text">噪声</div>
+                            </div>
+                        </div>
+                        <div class="btn-zone">
+                            <div class="input-box">
+                                <input class="input-box-inside" v-model="inputFreqValue" @input="handleInputFreqValue"
+                                    placeholder="输入波形频率......" />
+                            </div>
+                            <div @click="updateFreqUnit('MHz')" :class="{ 'btn-selected': selectedFreqUnit === 'MHz' }"
+                                class="btn-narrow">
+                                <div class="text">MHz</div>
+                            </div>
+                            <div @click="updateFreqUnit('kHz')" :class="{ 'btn-selected': selectedFreqUnit === 'kHz' }"
+                                class="btn-narrow">
+                                <div class="text">kHz</div>
+                            </div>
+                            <div @click="updateFreqUnit('Hz')" :class="{ 'btn-selected': selectedFreqUnit === 'Hz' }"
+                                class="btn-narrow">
+                                <div class="text">Hz</div>
+                            </div>
+                        </div>
+                        <div class="btn-zone">
+                            <div class="input-box">
+                                <input class="input-box-inside" v-model="inputVoltageValue" @input="handleInputVoltageValue"
+                                    placeholder="输入电压幅值......" />
+                            </div>
+                            <div @click="updateVoltageUnit('Vpp')"
+                                :class="{ 'btn-selected': selectedVoltageUnit === 'Vpp' }" class="btn-narrow">
+                                <div class="text">Vpp</div>
+                            </div>
+                            <div @click="updateVoltageUnit('mVpp')"
+                                :class="{ 'btn-selected': selectedVoltageUnit === 'mVpp' }" class="btn-narrow">
+                                <div class="text">mVpp</div>
+                            </div>
+                        </div>
+                        <div class="btn-zone">
+                            <div @click="updateEnableCH1()" :class="{ 'btn-selected': enableCH1 === true }"
+                                class="btn-narrow">
+                                <div class="text">CH1</div>
+                            </div>
+                            <div @click="updateEnableCH2()" :class="{ 'btn-selected': enableCH2 === true }"
+                                class="btn-narrow">
+                                <div class="text">CH2</div>
+                            </div>
+                            <div class="text" id="tip" :style="{ color: tipWordColor }">{{ tipWord }}</div>
+                        </div>
+                        <div class="btn-zone">
+                            <div @click="updateDeviceValue" class="btn">
+                                <div class="text">应用配置</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
             </div>
-          </div>
-        </div>
-        <div :style="{ height: height + 'px' }" class="content">
-          <div class="terminal-zone">
-            <!-- <div class="terminal-left">
+            <div class="page-down">
+                <div class="top-bar">
+                    <div @mousedown="startResize" class="resizer" :class="{ dragging: isDragging }">
+                        <div class="flag-bar">
+                            <div class="text">测试输出终端</div>
+                        </div>
+                        <div class="middle"></div>
+                        <div class="last-time">
+                            <div class="text"></div>
+                        </div>
+                    </div>
+                </div>
+                <div :style="{ height: height + 'px' }" class="content">
+                    <div class="terminal-zone">
+                        <!-- <div class="terminal-left">
                             <div class="select-area">
                             </div>
                         </div> -->
-            <div class="terminal-dividing"></div>
-            <div class="terminal-right">
-              <div class="terminal-output">
-                <div class="text" v-for="(text, index) in terminalOutput" :key="index">
-                  {{ text }}
+                        <div class="terminal-dividing"></div>
+                        <div class="terminal-right">
+                            <div class="terminal-output">
+                                <div class="text" v-for="(text, index) in terminalOutput" :key="index">
+                                    {{ text }}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
                 </div>
-              </div>
             </div>
-          </div>
         </div>
-      </div>
     </div>
-  </div>
 </template>
 
 <style lang="scss">
 .list-page-1 {
-  width: 100%;
-  height: 100%;
-  overflow-x: hidden;
-  overflow-y: hidden;
-
-  .page {
     width: 100%;
     height: 100%;
     overflow-x: hidden;
     overflow-y: hidden;
-    display: flex;
-    flex-direction: column;
-    justify-content: flex-start;
-    align-items: flex-start;
-    background-color: white;
-    padding: 0;
-  }
-
-  .page-up {
-    width: 100%;
-    height: 100%;
-    flex: 1;
-    overflow-x: hidden;
-    overflow-y: auto;
-    display: flex;
-    flex-direction: row;
-    justify-content: flex-start;
-    align-items: flex-start;
-
-    .control-zone {
-      width: 100%;
-      height: 100%;
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      align-items: center;
-      margin-top: 10vh;
-    }
-
-    .title {
-      font-size: 35px;
-      font-weight: 500;
-      margin-bottom: 0;
-      margin-bottom: 3vh;
-    }
-
-    .config-zone {
-      width: 100%;
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      align-items: center;
-    }
-
-    .text-line {
-      font-size: 25px;
-      font-weight: 500;
-      margin-top: 2vh;
-      margin-bottom: -2vh;
-    }
-
-    .adjust-line {
-      width: 100%;
-      height: auto;
-      padding-top: 3vh;
-      padding-bottom: 3vh;
-      padding-left: 0;
-      padding-right: 0;
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      align-items: center;
-    }
-
-    .btn-zone {
-      margin-top: 3vh;
-      display: flex;
-      flex-direction: row;
-      justify-content: flex-start;
-      align-items: center;
-
-      .btn {
-        width: 105px;
-        height: 35px;
-        overflow: hidden;
-        border: 1px solid #dfdfdf;
-        border-radius: 5px;
-        display: flex;
-        flex-direction: row;
-        justify-content: center;
-        align-items: center;
-        color: black;
-        position: relative;
-        cursor: pointer;
-        transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-      }
 
-      .btn::after {
-        content: '';
-        position: absolute;
+    .page {
         width: 100%;
         height: 100%;
-        background-color: rgba(255, 255, 255, 1);
-        z-index: 3;
-        transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-      }
-
-      .btn:hover {
-        background: linear-gradient(to right, #108ee9 0%, #87d068 100%);
+        overflow-x: hidden;
+        overflow-y: hidden;
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-start;
+        align-items: flex-start;
         background-color: white;
-        color: white;
-      }
+        padding: 0;
+    }
 
-      .btn:hover::after {
-        content: '';
-        position: absolute;
+    .page-up {
         width: 100%;
         height: 100%;
-        background-color: rgba(255, 255, 255, 0);
-        z-index: 3;
-      }
-
-      .text {
-        font-size: 20px;
-        font-weight: 400;
-        z-index: 5;
-      }
-    }
-  }
-
-  .page-down {
-    width: 100%;
-    // height: 200px;
-    background-color: white;
-    border-top: 1px solid #dfdfdf;
-    position: relative;
-
-    .content {
-      width: 100%;
-      height: 100%;
-      overflow: hidden;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-
-    .top-bar {
-      height: auto;
-      overflow-y: hidden;
-
-      .resizer {
-        cursor: ns-resize; // 调整为垂直调整的鼠标样式
-        background-color: white;
-        height: 22px; // 调整为较小的高度
-        width: 100%; // 确保宽度与父 div 一致
-        position: absolute;
-        top: 0;
-        border-top: 1px solid #dfdfdf;
-        border-bottom: 1px solid #dfdfdf;
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-        justify-content: flex-start;
-        overflow-y: hidden;
-      }
-
-      .text {
-        color: black;
-        font-size: 15px;
-      }
-
-      .flag-bar {
-        background-color: #2673e3;
-        width: 125px;
-        height: 32px;
-        padding-left: 10px;
+        flex: 1;
+        overflow-x: hidden;
+        overflow-y: auto;
         display: flex;
         flex-direction: row;
-        align-items: center;
         justify-content: flex-start;
-        clip-path: polygon(0% 0%, 100% 0%, 90% 100%, 0% 100%);
+        align-items: flex-start;
 
-        .text {
-          color: white;
+        .control-zone {
+            width: 100%;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: flex-start;
+            align-items: center;
+            margin-top: 10vh;
         }
-      }
 
-      .middle {
-        flex: 1;
-        background-color: red;
-      }
+        .title {
+            font-size: 35px;
+            font-weight: 500;
+            margin-bottom: 0;
+            margin-bottom: 3vh;
+        }
 
-      .last-time {
-        width: auto;
-        height: 100%;
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-        justify-content: flex-start;
-        padding-right: 15px;
-        font-weight: 500;
-      }
+        .config-zone {
+            width: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: flex-start;
+            align-items: center;
+        }
+
+        .text-line {
+            font-size: 25px;
+            font-weight: 500;
+            margin-top: 2vh;
+            margin-bottom: -2vh;
+        }
 
-      .dragging {
-        border-top: 6px solid #2673e3;
-        height: 34px;
-      }
+        .adjust-line {
+            width: 100%;
+            height: auto;
+            padding-top: 3vh;
+            padding-bottom: 3vh;
+            padding-left: 0;
+            padding-right: 0;
+            display: flex;
+            flex-direction: column;
+            justify-content: flex-start;
+            align-items: center;
+        }
+
+        .btn-zone {
+            margin-top: 3vh;
+            display: flex;
+            flex-direction: row;
+            justify-content: flex-start;
+            align-items: center;
+
+            .btn,
+            .btn-narrow {
+                width: 105px;
+                height: 35px;
+                overflow: hidden;
+                border: 1px solid #dfdfdf;
+                border-radius: 5px;
+                display: flex;
+                flex-direction: row;
+                justify-content: center;
+                align-items: center;
+                color: black;
+                position: relative;
+                cursor: pointer;
+                transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
+                margin-left: 16px;
+                margin-right: 16px;
+            }
+
+            .input-box {
+                width: 160px;
+                height: 35px;
+                overflow: hidden;
+                border: 1px solid #dfdfdf;
+                border-radius: 5px;
+                display: flex;
+                flex-direction: row;
+                justify-content: center;
+                align-items: center;
+                color: black;
+                position: relative;
+                cursor: pointer;
+                transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
+                margin-left: 16px;
+                margin-right: 16px;
+            }
+
+            .input-box-inside {
+                width: 100%;
+                height: 100%;
+                border: 1px solid #dfdfdf;
+                border-radius: 5px;
+                padding: 3px;
+                padding-left: 9px;
+            }
+
+            .btn-narrow {
+                width: 80px;
+            }
+
+            .btn::after,
+            .btn-narrow::after {
+                content: '';
+                position: absolute;
+                width: 100%;
+                height: 100%;
+                background-color: rgba(255, 255, 255, 1);
+                z-index: 3;
+                transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
+            }
+
+            .btn:hover,
+            .btn-narrow:hover {
+                background: linear-gradient(to right, #108ee9 0%, #87d068 100%);
+                background-color: white;
+                color: white;
+            }
+
+            .btn:hover::after,
+            .btn-narrow:hover::after {
+                content: '';
+                position: absolute;
+                width: 100%;
+                height: 100%;
+                background-color: rgba(255, 255, 255, 0);
+                z-index: 3;
+            }
+
+            .btn-selected {
+                background: linear-gradient(to right, #108ee9 0%, #87d068 100%);
+                background-color: white;
+                color: white;
+            }
+
+            .btn-selected::after {
+                content: '';
+                position: absolute;
+                width: 100%;
+                height: 100%;
+                background-color: rgba(255, 255, 255, 0);
+                z-index: 3;
+            }
+
+            .text {
+                font-size: 20px;
+                font-weight: 400;
+                z-index: 5;
+            }
+
+            #tip {
+                font-size: 23px;
+                font-weight: 600;
+                margin-left: 16px;
+            }
+        }
+
+        // #btn-zone-tip {
+        //     margin-top: 2vh;
+        //     margin-bottom: -1vh;
+        // }
     }
-  }
 
-  .terminal-zone {
-    width: 100%;
-    height: 100%;
-    overflow-x: hidden;
-    overflow-y: hidden;
-    display: flex;
-    flex-direction: row;
-    justify-content: flex-start;
-    align-items: flex-start;
-
-    .terminal-right {
-      flex: 5;
-      height: 100%;
-      overflow-x: hidden;
-      overflow-y: hidden;
-    }
-
-    .terminal-output {
-      height: 100%;
-      overflow-x: auto;
-      overflow-y: scroll;
-      background-color: white;
-      padding: 25px;
-      padding-top: 35px;
-    }
-
-    .terminal-dividing {
-      width: 0px;
-      height: 100%;
-      border: 0;
-      border-right: 1px solid #dfdfdf;
-    }
-
-    .terminal-left {
-      flex: 3;
-      height: 100%;
-      background-color: white;
-      overflow-y: auto;
-      overflow-x: auto;
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      align-items: flex-start;
-      padding: 25px;
-      padding-top: 40px;
-
-      .text {
-        color: black;
-      }
-
-      .title {
-        font-size: 20px;
-        font-weight: 500;
-        margin-top: 15px;
-        margin-bottom: 10px;
-      }
-
-      .line {
+    .page-down {
         width: 100%;
-        height: auto;
-        display: flex;
-        flex-direction: column;
-        justify-content: flex-start;
-        align-items: flex-start;
-        margin-bottom: 6px;
+        // height: 200px;
+        background-color: white;
+        border-top: 1px solid #dfdfdf;
+        position: relative;
 
-        .item {
-          font-size: 18px;
-          font-weight: 500;
-          flex: 1;
-          margin-bottom: 10px;
+        .content {
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+            display: flex;
+            align-items: center;
+            justify-content: center;
         }
-      }
 
-      .select-area {
+        .top-bar {
+            height: auto;
+            overflow-y: hidden;
+
+            .resizer {
+                cursor: ns-resize; // 调整为垂直调整的鼠标样式
+                background-color: white;
+                height: 22px; // 调整为较小的高度
+                width: 100%; // 确保宽度与父 div 一致
+                position: absolute;
+                top: 0;
+                border-top: 1px solid #dfdfdf;
+                border-bottom: 1px solid #dfdfdf;
+                display: flex;
+                flex-direction: row;
+                align-items: center;
+                justify-content: flex-start;
+                overflow-y: hidden;
+            }
+
+            .text {
+                color: black;
+                font-size: 15px;
+            }
+
+            .flag-bar {
+                background-color: #2673e3;
+                width: 125px;
+                height: 32px;
+                padding-left: 10px;
+                display: flex;
+                flex-direction: row;
+                align-items: center;
+                justify-content: flex-start;
+                clip-path: polygon(0% 0%, 100% 0%, 90% 100%, 0% 100%);
+
+                .text {
+                    color: white;
+                }
+            }
+
+            .middle {
+                flex: 1;
+                background-color: red;
+            }
+
+            .last-time {
+                width: auto;
+                height: 100%;
+                display: flex;
+                flex-direction: row;
+                align-items: center;
+                justify-content: flex-start;
+                padding-right: 15px;
+                font-weight: 500;
+            }
+
+            .dragging {
+                border-top: 6px solid #2673e3;
+                height: 34px;
+            }
+        }
+    }
+
+    .terminal-zone {
+        width: 100%;
+        height: 100%;
+        overflow-x: hidden;
+        overflow-y: hidden;
         display: flex;
         flex-direction: row;
         justify-content: flex-start;
-        align-items: center;
-
-        .text {
-          font-size: 20px;
-          font-weight: 500;
-        }
-
-        .select-box {
-          margin-top: 6px;
-          margin-bottom: 6px;
-
-          .select-button {
-            padding: 3px;
-            padding-left: 9px;
-            width: 100px;
-            border: 1px solid rgba(0, 0, 0, 0.35);
-            border-radius: 5px;
-            margin-left: 10px;
-            margin-right: 20px;
-          }
-        }
+        align-items: flex-start;
 
-        .button {
-          margin-top: 12px;
-          font-size: 18px;
-          border: 1px solid rgba(0, 0, 0, 0.35);
-          border-radius: 5px;
-          padding: 3px;
-          padding-left: 8px;
-          padding-right: 8px;
+        .terminal-right {
+            flex: 5;
+            height: 100%;
+            overflow-x: hidden;
+            overflow-y: hidden;
         }
 
-        .button:hover {
-          background-color: #2673e3;
-          color: white;
-          border: 1px solid rgba($color: #2673e3, $alpha: 1);
+        .terminal-output {
+            height: 100%;
+            overflow-x: auto;
+            overflow-y: scroll;
+            background-color: white;
+            padding: 25px;
+            padding-top: 35px;
         }
 
-        .button:active {
-          background-color: rgba($color: #2673e3, $alpha: 0.5);
-          border: 1px solid rgba($color: #2673e3, $alpha: 0.5);
-          color: white;
+        .terminal-dividing {
+            width: 0px;
+            height: 100%;
+            border: 0;
+            border-right: 1px solid #dfdfdf;
         }
 
-        .tip {
-          margin-top: 12px;
-          font-size: 18px;
-          margin-left: 16px;
-          font-weight: 500;
+        .terminal-left {
+            flex: 3;
+            height: 100%;
+            background-color: white;
+            overflow-y: auto;
+            overflow-x: auto;
+            display: flex;
+            flex-direction: column;
+            justify-content: flex-start;
+            align-items: flex-start;
+            padding: 25px;
+            padding-top: 40px;
+
+            .text {
+                color: black;
+            }
+
+            .title {
+                font-size: 20px;
+                font-weight: 500;
+                margin-top: 15px;
+                margin-bottom: 10px;
+            }
+
+            .line {
+                width: 100%;
+                height: auto;
+                display: flex;
+                flex-direction: column;
+                justify-content: flex-start;
+                align-items: flex-start;
+                margin-bottom: 6px;
+
+                .item {
+                    font-size: 18px;
+                    font-weight: 500;
+                    flex: 1;
+                    margin-bottom: 10px;
+                }
+            }
+
+            .select-area {
+                display: flex;
+                flex-direction: row;
+                justify-content: flex-start;
+                align-items: center;
+
+                .text {
+                    font-size: 20px;
+                    font-weight: 500;
+                }
+
+                .select-box {
+                    margin-top: 6px;
+                    margin-bottom: 6px;
+
+                    .select-button {
+                        padding: 3px;
+                        padding-left: 9px;
+                        width: 100px;
+                        border: 1px solid rgba(0, 0, 0, 0.35);
+                        border-radius: 5px;
+                        margin-left: 10px;
+                        margin-right: 20px;
+                    }
+                }
+
+                .button {
+                    margin-top: 12px;
+                    font-size: 18px;
+                    border: 1px solid rgba(0, 0, 0, 0.35);
+                    border-radius: 5px;
+                    padding: 3px;
+                    padding-left: 8px;
+                    padding-right: 8px;
+                }
+
+                .button:hover {
+                    background-color: #2673e3;
+                    color: white;
+                    border: 1px solid rgba($color: #2673e3, $alpha: 1);
+                }
+
+                .button:active {
+                    background-color: rgba($color: #2673e3, $alpha: 0.5);
+                    border: 1px solid rgba($color: #2673e3, $alpha: 0.5);
+                    color: white;
+                }
+
+                .tip {
+                    margin-top: 12px;
+                    font-size: 18px;
+                    margin-left: 16px;
+                    font-weight: 500;
+                }
+            }
         }
-      }
     }
-  }
 }
 </style>

二進制
release/PLC_SIM v0.6.0 无信号发生器.7z