From 005a057f47b07b0b36e4cc4f94ff0fdc47fd5b88 Mon Sep 17 00:00:00 2001
From: Xu Zhimeng <xuzhimeng@qq.com>
Date: Thu, 29 Jun 2023 17:43:15 +0800
Subject: [PATCH] =?UTF-8?q?WIP:=20=E5=AE=9E=E7=8E=B0=E4=BA=8C=E7=BA=A7?=
 =?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=B8=ADSpectra=E7=BB=84=E4=BB=B6=EF=BC=8C?=
 =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E7=BA=A7=E8=8F=9C=E5=8D=95=E7=BB=93?=
 =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=B9=B6=E5=9C=A8=E8=8F=9C=E5=8D=95=E4=B8=AD?=
 =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B7=B2=E9=80=89=E4=B8=AD=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9B=E7=BB=98=E5=88=B63D=20Scatter?=
 =?UTF-8?q?=E5=92=8C3D=20Surface=20=E5=9B=BE=E8=A1=A8=EF=BC=88=E8=BF=9B?=
 =?UTF-8?q?=E8=A1=8C=E4=B8=AD=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 package.json                                  |   1 +
 src/components/Custom3DChart/index.vue        |  51 +++
 src/components/CustomChart/index.vue          |   1 -
 .../components/BetaGammaSpectrumChart.vue     | 244 +++++++++++++--
 .../components/SpectraListInMenu.vue          |  65 ++++
 .../components/SpectrumLineChart.vue          |  14 +-
 .../sub-operators/PopOverWithIcon.vue         |  21 +-
 .../components/sub-operators/Spectra.vue      |  64 +++-
 src/views/spectrumAnalysis/index.vue          | 291 ++++++++++++++----
 9 files changed, 652 insertions(+), 100 deletions(-)
 create mode 100644 src/components/Custom3DChart/index.vue
 create mode 100644 src/views/spectrumAnalysis/components/SpectraListInMenu.vue

diff --git a/package.json b/package.json
index e92f39a..bbea7cf 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
     "dayjs": "^1.8.0",
     "dom-align": "1.12.0",
     "echarts": "^5.4.2",
+    "echarts-gl": "^2.0.9",
     "enquire.js": "^2.1.6",
     "js-cookie": "^2.2.0",
     "lodash.get": "^4.4.2",
diff --git a/src/components/Custom3DChart/index.vue b/src/components/Custom3DChart/index.vue
new file mode 100644
index 0000000..da5b31b
--- /dev/null
+++ b/src/components/Custom3DChart/index.vue
@@ -0,0 +1,51 @@
+<template>
+  <div class="custom-chart" ref="containerRef" :style="{ height: height + 'px' }"></div>
+</template>
+<script>
+import * as echarts from 'echarts'
+import 'echarts-gl'
+export default {
+  props: {
+    option: {
+      type: Object,
+      default: () => ({})
+    },
+    height: {
+      type: Number,
+      default: 0
+    }
+  },
+  data() {
+    return {}
+  },
+  mounted() {
+    this.chart = echarts.init(this.$refs.containerRef)
+    this.chart.setOption(this.option)
+  },
+  methods: {
+    resize() {
+      this.chart && this.chart.resize()
+    }
+  },
+  watch: {
+    option: {
+      handler() {
+        if (this.chart) {
+          this.chart.setOption(this.option)
+        }
+      },
+      deep: true
+    },
+    height() {
+      this.$nextTick(() => {
+        this.chart && this.chart.resize()
+      })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.custom-chart {
+  height: 100% !important;
+}
+</style>
diff --git a/src/components/CustomChart/index.vue b/src/components/CustomChart/index.vue
index a39c9ff..f1157bc 100644
--- a/src/components/CustomChart/index.vue
+++ b/src/components/CustomChart/index.vue
@@ -30,7 +30,6 @@ export default {
     option: {
       handler() {
         if(this.chart) {
-          this.chart.clear()
           this.chart.setOption(this.option)
         }
       },
diff --git a/src/views/spectrumAnalysis/components/BetaGammaSpectrumChart.vue b/src/views/spectrumAnalysis/components/BetaGammaSpectrumChart.vue
index 9ab5d17..46c4bf1 100644
--- a/src/views/spectrumAnalysis/components/BetaGammaSpectrumChart.vue
+++ b/src/views/spectrumAnalysis/components/BetaGammaSpectrumChart.vue
@@ -10,34 +10,51 @@
       >
     </div>
     <div class="beta-gamma-spectrum-chart-main">
-      <custom-chart ref="chartRef" :option="option" />
+      <!-- 2D 图表 -->
+      <div class="_2d-chart" v-if="active == 0">
+        <custom-chart ref="chartRef" :option="twoDOption" />
+        <div class="bar">
+          <div>256</div>
+          <div class="bar-main"></div>
+          <div>0</div>
+        </div>
+      </div>
+      <!-- 2D图表结束 -->
+
+      <!-- 3D Surface开始 -->
+      <Custom3DChart v-if="active == 1" key="1" ref="_3dSurfaceRef" :option="threeDSurfaceOption" />
+      <!-- 3D Surface结束 -->
+      <!-- 3D Scatter -->
+      <Custom3DChart v-if="active == 2" key="2" ref="_3dScannerRef" :option="threeDScatterOption" />
+      <!-- 3D Scatter结束 -->
     </div>
   </div>
 </template>
 
 <script>
 import CustomChart from '@/components/CustomChart/index.vue'
+import Custom3DChart from '@/components/Custom3DChart/index.vue'
 const buttons = ['2D', '3D Surface', '3D Scatter', 'Unzoom']
 
-const option = {
-  visualMap: [{
-    min: 0,
-    max: 256,
-    calculable: true,
-    orient: 'vertical',
-    right: 0,
-    top: 0,
-    bottom: 0,
-    inRange: {
-      color: ['#fff', '#f00']
-    }
-  }],
+// 2D 配置
+const twoDOption = {
   grid: {
     top: 15,
     left: 55,
-    right: 40,
+    right: 10,
     bottom: 45
   },
+  tooltip: {
+    trigger: 'axis',
+    showContent: false,
+    axisPointer: {
+      animation: false,
+      type: 'cross',
+      lineStyle: {
+        type: 'dashed'
+      }
+    }
+  },
   xAxis: {
     name: 'Beta Channel',
     nameTextStyle: {
@@ -61,8 +78,7 @@ const option = {
     },
     min: 0,
     max: 256,
-    interval: 64,
-    data: new Array(256).fill(0).map((_, index) => index)
+    interval: 64
   },
   yAxis: {
     name: 'Gamma Channel',
@@ -87,24 +103,169 @@ const option = {
     },
     min: 0,
     max: 256,
-    interval: 64,
-    data: new Array(256).fill(0).map((_, index) => index)
+    interval: 64
+  },
+  series: [
+    {
+      xAxisIndex: 0,
+      yAxisIndex: 0,
+      type: 'scatter',
+      symbolSize: 2.5,
+      itemStyle: {
+        color: '#fff'
+      },
+      data: new Array(1256).fill(0).map(() => [parseInt(Math.random() * 256), parseInt(Math.random() * 256)])
+    },
+    {
+      type: 'line'
+    }
+  ]
+}
+
+//3D Surface 配置
+
+const threeDSurfaceOption = {
+  visualMap: {
+    show: false,
+    dimension: 2,
+    min: 0,
+    max: 5,
+    inRange: ['#47C134', '#f00']
+  },
+  grid3D: {
+    axisLabel: {
+      color: '#C4E5A6'
+    },
+    axisPointer: {
+      show: false
+    },
+    axisLine: {
+      lineStyle: {
+        color: '#fff'
+      }
+    },
+    splitLine: {
+      lineStyle: {
+        color: '#fff'
+      }
+    }
+  },
+  xAxis3D: {
+    name: 'Beta Channel',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    min: 0,
+    max: 256,
+    interval: 64
+  },
+  yAxis3D: {
+    name: 'Gamma Channel',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    min: 0,
+    max: 256,
+    interval: 64
+  },
+  zAxis3D: {
+    name: 'Count',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    max: 5
   },
   series: {
-    type: 'scatter',
-    symbolSize: 2,
-    data: new Array(256).fill(0).map(() => [parseInt(Math.random() * 256), parseInt(Math.random() * 256)])
+    type: 'surface',
+    data: [
+      [64, 64, 0],
+      [66, 66, 0],
+      [66, 66, 0],
+      [65, 65, 4],
+
+      [128, 128, 0],
+      [130, 130, 0],
+      [130, 130, 0],
+      [129, 129, 4]
+    ]
   }
 }
+
+// 3D Scatter 配置
+const threeDScatterOption = {
+  grid3D: {
+    axisLabel: {
+      color: '#C4E5A6'
+    },
+    axisPointer: {
+      show: false
+    },
+    axisLine: {
+      lineStyle: {
+        color: '#fff'
+      }
+    },
+    splitLine: {
+      lineStyle: {
+        color: '#fff'
+      }
+    }
+  },
+  xAxis3D: {
+    name: 'Beta Channel',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    min: 0,
+    max: 256,
+    interval: 64
+  },
+  yAxis3D: {
+    name: 'Gamma Channel',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    min: 0,
+    max: 256,
+    interval: 64
+  },
+  zAxis3D: {
+    name: 'Count',
+    nameTextStyle: {
+      color: '#C4E5A6',
+      fontSize: 14
+    },
+    max: 6
+  },
+  series: {
+    type: 'scatter3D',
+    symbolSize: 2.5,
+    itemStyle: {
+      color: '#a2d092'
+    },
+    data: new Array(512)
+      .fill(0)
+      .map(() => [parseInt(Math.random() * 256), parseInt(Math.random() * 256), 4.5 + Math.random() * 0.1])
+  }
+}
+
 export default {
   components: {
-    CustomChart
+    CustomChart,
+    Custom3DChart
   },
   data() {
     this.buttons = buttons
     return {
-      active: 0,
-      option
+      active: 1,
+      twoDOption,
+      threeDSurfaceOption,
+      threeDScatterOption
     }
   },
   methods: {
@@ -113,7 +274,9 @@ export default {
     },
 
     resize() {
-      this.$refs.chartRef.resize()
+      this.$refs.chartRef && this.$refs.chartRef.resize()
+      this.$refs._3dSurfaceRef && this.$refs._3dSurfaceRef.resize()
+      this.$refs._3dScannerRef && this.$refs._3dScannerRef.resize()
     }
   }
 }
@@ -152,7 +315,34 @@ export default {
   }
 
   &-main {
-    height: calc(100% - 26px);
+    height: calc(100% - 40px);
+    margin-top: 15px;
+
+    ._2d-chart {
+      height: 100%;
+      display: flex;
+
+      .custom-chart {
+        width: calc(100% - 45px);
+      }
+
+      .bar {
+        width: 30px;
+        margin-left: 15px;
+        height: 100%;
+        color: #ade6ee;
+        padding-top: 5px;
+        padding-bottom: 38px;
+        text-align: center;
+
+        &-main {
+          display: inline-block;
+          width: 14px;
+          height: calc(100% - 42px);
+          background: linear-gradient(to bottom, #ff0000 0, #fff 100%);
+        }
+      }
+    }
   }
 }
 </style>
diff --git a/src/views/spectrumAnalysis/components/SpectraListInMenu.vue b/src/views/spectrumAnalysis/components/SpectraListInMenu.vue
new file mode 100644
index 0000000..ae86d3e
--- /dev/null
+++ b/src/views/spectrumAnalysis/components/SpectraListInMenu.vue
@@ -0,0 +1,65 @@
+<template>
+  <a-menu class="spectra-list-in-menu">
+    <a-menu-item v-for="item in list" :key="item.id" @click="handleClick(item)">
+      <span class="checkbox">
+        <a-icon v-if="item.checked" type="check" style="color: #0de30d" />
+      </span>
+      <span class="name">{{ item.name }}</span>
+      <a-icon type="delete" @click.stop="handleRemove(item)" />
+    </a-menu-item>
+  </a-menu>
+</template>
+
+<script>
+export default {
+  props: {
+    list: {
+      type: Array,
+      default: () => []
+    }
+  },
+  methods: {
+    handleClick(spectraItem) {
+      this.list.forEach(item => (item.checked = false))
+      spectraItem && (spectraItem.checked = true)
+      this.$emit('change', spectraItem)
+      this.$forceUpdate()
+    },
+
+    handleRemove(spectraItem) {
+      const index = this.list.findIndex(item => item == spectraItem)
+      this.list.splice(index, 1)
+      // 如果删除了一个选中的
+      if (spectraItem.checked) {
+        if (index == 0) {
+          // 如果是第一个,则选中下一个
+          this.handleClick(this.list[0])
+        } else {
+          // 如果不是第一个,则选中上一个
+          this.handleClick(this.list[index - 1])
+        }
+      }
+      this.$forceUpdate()
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.spectra-list-in-menu {
+  .checkbox {
+    width: 14px;
+    height: 14px;
+    display: inline-block;
+  }
+
+  .name {
+    display: inline-block;
+    width: 300px;
+    margin: 0 5px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    vertical-align: top;
+  }
+}
+</style>
diff --git a/src/views/spectrumAnalysis/components/SpectrumLineChart.vue b/src/views/spectrumAnalysis/components/SpectrumLineChart.vue
index 4bcdfd4..116ab17 100644
--- a/src/views/spectrumAnalysis/components/SpectrumLineChart.vue
+++ b/src/views/spectrumAnalysis/components/SpectrumLineChart.vue
@@ -12,7 +12,7 @@ import { cloneDeep } from 'lodash'
 const initialOption = {
   grid: {
     top: 25,
-    right: 0,
+    right: 12,
     bottom: 40
   },
   title: {
@@ -33,7 +33,9 @@ const initialOption = {
     }
   },
   xAxis: {
-    type: 'category',
+    min: 0,
+    max: 256,
+    interval: 64,
     axisLine: {
       lineStyle: {
         color: 'rgb(119, 181, 213, 0.5)'
@@ -57,10 +59,12 @@ const initialOption = {
       fontSize: 14,
       color: '#5b9cba'
     },
-    nameGap: 25,
-    data: new Array(256).fill(0).map((_, index) => index)
+    nameGap: 25
   },
   yAxis: {
+    min: 0,
+    max: 21099,
+    interval: 21000 / 4,
     axisLine: {
       show: true,
       lineStyle: {
@@ -84,7 +88,7 @@ const initialOption = {
     symbol: 'none',
     data: new Array(256)
       .fill(0)
-      .map((_, index) => (Math.random() < 0.05 ? parseInt(Math.random() * 19644) : parseInt(Math.random() * 800)))
+      .map((_, index) => [index, (Math.random() < 0.05 ? parseInt(Math.random() * 19644) : parseInt(Math.random() * 800))])
   }
 }
 
diff --git a/src/views/spectrumAnalysis/components/sub-operators/PopOverWithIcon.vue b/src/views/spectrumAnalysis/components/sub-operators/PopOverWithIcon.vue
index 3ac6b89..7e52eb8 100644
--- a/src/views/spectrumAnalysis/components/sub-operators/PopOverWithIcon.vue
+++ b/src/views/spectrumAnalysis/components/sub-operators/PopOverWithIcon.vue
@@ -1,5 +1,5 @@
 <template>
-  <a-popover :placement="placement" overlayClassName="popover-with-icon">
+  <a-popover :placement="placement" overlayClassName="popover-with-icon" v-model="innerVisible">
     <div class="pop-over-with-icon">
       <span class="text">
         <slot />
@@ -17,6 +17,25 @@ export default {
     placement: {
       type: String,
       default: 'bottom'
+    },
+    value: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      innerVisible: false
+    }
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.innerVisible = val
+      },
+      immediate: true
+    },
+    innerVisible(val) {
+      this.$emit('input', val)
     }
   }
 }
diff --git a/src/views/spectrumAnalysis/components/sub-operators/Spectra.vue b/src/views/spectrumAnalysis/components/sub-operators/Spectra.vue
index 5ec32e2..83a6b04 100644
--- a/src/views/spectrumAnalysis/components/sub-operators/Spectra.vue
+++ b/src/views/spectrumAnalysis/components/sub-operators/Spectra.vue
@@ -1,14 +1,74 @@
 <template>
   <div class="spectra">
-    spectra
+    <div
+      :class="'spectra-item' + (item.title == innerValue ? ' active' : '')"
+      v-for="(item, index) in list"
+      :key="index"
+      @click="handleClick(item)"
+    >
+      {{ item.title }}
+    </div>
   </div>
 </template>
 
 <script>
-export default {}
+const list = [
+  {
+    title: 'Sample Data'
+  },
+  {
+    title: 'GasBg Data'
+  },
+  {
+    title: 'DetBg Data'
+  },
+  {
+    title: 'QC Data'
+  }
+]
+export default {
+  props: {
+    value: {
+      type: String,
+      required: true
+    }
+  },
+  data() {
+    this.list = list
+    return {}
+  },
+  methods: {
+    handleClick(item) {
+      this.innerValue = item.title
+    }
+  },
+  computed: {
+    innerValue: {
+      set(val) {
+        this.$emit('input', val)
+      },
+      get() {
+        return this.value
+      }
+    }
+  }
+}
 </script>
 
 <style lang="less" scoped>
 .spectra {
+  width: 159px;
+  max-height: 200px;
+  overflow: auto;
+
+  &-item {
+    padding: 4px 14px;
+    cursor: pointer;
+
+    &:hover,
+    &.active {
+      background-color: #055565;
+    }
+  }
 }
 </style>
diff --git a/src/views/spectrumAnalysis/index.vue b/src/views/spectrumAnalysis/index.vue
index 923d3a7..55af364 100644
--- a/src/views/spectrumAnalysis/index.vue
+++ b/src/views/spectrumAnalysis/index.vue
@@ -2,15 +2,23 @@
   <div class="spectrum-analysis">
     <!-- 顶部操作栏 -->
     <div class="spectrum-analysis-operators">
-      <a-dropdown class="spectrum-analysis-operators-item" v-for="operation in operations" :key="operation.title">
+      <a-dropdown
+        class="spectrum-analysis-operators-item"
+        overlayClassName="spectrum-analysis-operators-dropdown-overlay"
+        :overlay-style="operation.style"
+        v-for="operation in operations"
+        :key="operation.title"
+      >
         <a-button type="primary">{{ operation.title }}</a-button>
-        <template slot="overlay">
-          <a-menu>
-            <a-menu-item v-for="child in operation.children" :key="child.title" @click="child.handler">
-              {{ child.title }}
-            </a-menu-item>
-          </a-menu>
-        </template>
+        <div slot="overlay">
+          <template v-for="(child, index) in operation.children">
+            <component :is="child.type" :key="index" v-bind="child.attrs" v-on="child.on">
+              <component :is="item.type" v-for="item in child.children" :key="item.title" @click="item.handler">
+                {{ item.title }}
+              </component>
+            </component>
+          </template>
+        </div>
       </a-dropdown>
     </div>
     <!-- 顶部操作栏结束 -->
@@ -46,9 +54,9 @@
 
       <!-- beta-gamma 独有的二级交互栏 -->
       <template v-if="analysisType == ANALYZE_TYPE.BETA_GAMMA">
-        <pop-over-with-icon placement="bottomLeft" style="width: 159px">
+        <pop-over-with-icon placement="bottomLeft" style="width: 159px" v-model="spectraVisible">
           Spectra
-          <spectra slot="content" />
+          <spectra slot="content" v-model="spectraType" @input="spectraVisible = false" />
         </pop-over-with-icon>
       </template>
       <!-- beta-gamma 独有的二级交互栏结束 -->
@@ -74,6 +82,7 @@ import QcFlags from './components/sub-operators/QcFlags.vue'
 import GammaAnalysis from './gamma-analysis.vue'
 import BetaGammaAnalysis from './beta-gamma-analysis.vue'
 import Spectra from './components/sub-operators/Spectra.vue'
+import SpectraListInMenu from './components/SpectraListInMenu.vue'
 
 // 分析类型
 const ANALYZE_TYPE = {
@@ -90,24 +99,39 @@ export default {
     GraphAssistance,
     DetailedInfomation,
     NuclearLibrary,
-    Spectra
+    Spectra,
+    SpectraListInMenu
   },
   data() {
     this.ANALYZE_TYPE = ANALYZE_TYPE
 
     return {
-      analysisType: ANALYZE_TYPE.BETA_GAMMA // 分析类型
+      analysisType: ANALYZE_TYPE.BETA_GAMMA, // 分析类型
+      spectraType: 'Sample Data',
+      spectraVisible: false,
+
+      spectraList: [
+        { id: 1, name: 'AUX01 003-20151223 1855 S FULL 40183.7.PHD' },
+        { id: 2, name: 'AUX02 003-20151223 1855 S FULL 40183.7.PHD' }
+      ]
     }
   },
   methods: {
+    // 从数据库加载
     handleLoadFromDb() {
       console.log('%c [ handleLoadFromDb ]-46', 'font-size:13px; background:pink; color:#bf2c9f;')
     },
 
+    // 从文件加载
     handleLoadFromFile() {
       console.log('%c [ handleLoadFromFile ]-46', 'font-size:13px; background:pink; color:#bf2c9f;')
     },
 
+    // 清理全部
+    handleCleanAll() {
+      console.log('%c [ handleCleanAll ]-118', 'font-size:13px; background:pink; color:#bf2c9f;')
+    },
+
     // peak info 点击左右方向
     handlePeakInfoChange(direction) {
       this.$refs.gammaAnalysisRef.moveMarkLine(direction)
@@ -125,12 +149,46 @@ export default {
           title: 'SAMPLE',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
+              type: 'a-menu',
+              children: [
+                {
+                  type: 'a-menu-item',
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  type: 'a-menu-item',
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  type: 'a-menu-item',
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             },
             {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-divider',
+              attrs: {
+                style: {
+                  marginTop: '5px',
+                  marginBottom: '5px',
+                  display: this.spectraList.length ? '' : 'none'
+                }
+              }
+            },
+            {
+              type: 'SpectraListInMenu',
+              attrs: {
+                list: this.spectraList
+              },
+              on: {
+                change: event => {
+                  console.log('%c [ event ]-187', 'font-size:13px; background:pink; color:#bf2c9f;', event)
+                  console.log('%c [  ]-188', 'font-size:13px; background:pink; color:#bf2c9f;', this)
+                }
+              }
             }
           ]
         },
@@ -138,12 +196,21 @@ export default {
           title: 'SAVE',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -151,12 +218,21 @@ export default {
           title: 'ANALYZE',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -164,12 +240,21 @@ export default {
           title: 'CALIBRATION',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -177,12 +262,21 @@ export default {
           title: 'NUCLIDELIBRARY',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -190,12 +284,21 @@ export default {
           title: 'COMMENTS',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -203,12 +306,21 @@ export default {
           title: 'REPORTS',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -216,12 +328,21 @@ export default {
           title: 'LOG',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         },
@@ -229,12 +350,21 @@ export default {
           title: 'HELP',
           children: [
             {
-              title: 'Load From DB',
-              handler: this.handleLoadFromDb
-            },
-            {
-              title: 'Load From File',
-              handler: this.handleLoadFromFile
+              type: 'a-menu',
+              children: [
+                {
+                  title: 'Load From DB',
+                  handler: this.handleLoadFromDb
+                },
+                {
+                  title: 'Load From File',
+                  handler: this.handleLoadFromFile
+                },
+                {
+                  title: 'Clean All',
+                  handler: this.handleCleanAll
+                }
+              ]
             }
           ]
         }
@@ -343,3 +473,36 @@ export default {
   // 主体部分结束
 }
 </style>
+<style lang="less">
+.spectrum-analysis-operators-dropdown-overlay {
+  background-color: #03353f;
+  .ant-menu {
+    background: transparent;
+    padding: 0;
+    position: relative;
+    border-right: 0;
+
+    &-item {
+      color: #fff;
+      font-family: Arial;
+      border: 0;
+      background-color: transparent !important;
+      padding: 4px 14px;
+      height: 30px;
+      line-height: 22px;
+      &:hover {
+        background-color: #055565 !important;
+      }
+      &-selected {
+        font-weight: normal;
+      }
+      &-disabled {
+        color: #476d74 !important;
+        &:hover {
+          background-color: transparent !important;
+        }
+      }
+    }
+  }
+}
+</style>