zouling 1 napja
szülő
commit
792772e47c

+ 1 - 0
ruoyi-ui/package.json

@@ -45,6 +45,7 @@
     "clipboard": "2.0.8",
     "core-js": "3.37.1",
     "echarts": "^5.1.0",
+    "echarts-liquidfill": "^3.1.0",
     "element-ui": "2.15.14",
     "file-saver": "2.0.5",
     "flv": "^0.0.1",

BIN
ruoyi-ui/src/assets/images/icon_gjht_wl_ss.png


BIN
ruoyi-ui/src/assets/images/icon_gjht_wl_xj.png


+ 328 - 0
ruoyi-ui/src/views/system/service/index.vue

@@ -0,0 +1,328 @@
+<template>
+  <div class="app-container">
+    <div class="flexcw" :class="{'toplinea':server&&server.netWorkList&&server.netWorkList.length>2}">
+      <div class="topa flex1 carboxs" v-if="server.sys">
+        <div class="cardbox">
+          <div class="titbox">服务器信息</div>
+          <div class="topbox flexc">
+            <div class="txts">
+              <div class="tit">服务器名称</div>
+              <div class="txt">{{server.sys.computerName}}</div>
+            </div>
+            <div class="txts">
+              <div class="tit">操作系统</div>
+              <div class="txt">{{ server.sys.osName }}</div>
+            </div>
+            <div class="txts">
+              <div class="tit">服务器IP</div>
+              <div class="txt">{{ server.sys.computerIp }}</div>
+            </div>
+            <div class="txts">
+              <div class="tit">系统架构</div>
+              <div class="txt">{{ server.sys.osArch }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <template v-if="server&&server.netWorkList&&server.netWorkList.length">
+        <div class="carboxs topb" v-for="(ite,idx) in server.netWorkList" :key="idx">
+          <div class="cardbox" >
+            <div class="titbox">网络占用<span>({{ite.networkName}})</span></div>
+            <div class="topbox flexc ">
+              <div class="txts">
+                <div class="tit">下行</div>
+                <div class="txt">{{ite.networkDown}}KB/S</div>
+              </div>
+              <div class="txts">
+                <div class="tit">上行</div>
+                <div class="txt">{{ ite.networkUp }}KB/S</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
+
+    </div>
+    <div class="flexcw">
+      <div class="carboxs boxb" style="min-width: 40%;">
+        <div class="cardbox ">
+          <div class="titbox">系统内存</div>
+          <div class="flexc" v-if="server.mem">
+            <div class="waterbox" >
+              <water-ball-chart :chartData="server.mem" :waterColors="waterColora"></water-ball-chart>
+            </div>
+            <div class="watxtbox">
+              <div class="txts">
+                <div class="tit">剩余内存</div>
+                <div class="txt">{{server.mem.free}}G</div>
+              </div>
+              <div class="txts">
+                <div class="tit">已用内存</div>
+                <div class="txt">{{server.mem.used}}G</div>
+              </div>
+              <div class="txts">
+                <div class="tit">总内存</div>
+                <div class="txt">{{server.mem.total}}G</div>
+              </div>
+              <div class="txts">
+                <div class="tit">使用率</div>
+                <div class="txt">{{server.mem.usage}}%</div>
+              </div>
+            </div>
+          </div>
+          <div class="titbox" style="margin-top: 9px;">JVM内存</div>
+          <div class="flexc"  v-if="server.jvm">
+            <div class="waterbox">
+              <water-ball-chart :chartData="server.jvm" :waterColors="waterColorb"></water-ball-chart>
+            </div>
+            <div class="watxtbox">
+              <div class="txts">
+                <div class="tit">剩余内存</div>
+                <div class="txt">{{server.jvm.free}}M</div>
+              </div>
+              <div class="txts">
+                <div class="tit">已用内存</div>
+                <div class="txt">{{server.jvm.used}}M</div>
+              </div>
+              <div class="txts">
+                <div class="tit">总内存</div>
+                <div class="txt">{{server.jvm.total}}M</div>
+              </div>
+              <div class="txts">
+                <div class="tit">使用率</div>
+                <div class="txt">{{server.jvm.usage}}%</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- cpu -->
+      <template v-if="server.cpuList&&server.cpuList.length">
+        <div class="carboxs boxb" style="min-width: 30%;" v-for="(cpuite,idx) in server.cpuList" :key="'cpu'+idx">
+          <div class="cardbox " >
+            <div class="titbox titboxa">CPU使用率 {{idx<9?'0'+(idx+1):idx+1}}</div>
+            <gaugea-chart v-if="cpuite" :chartData="cpuite"></gaugea-chart>
+            <div class="flexcw txtboxc">
+              <div class="txtcs">
+                <div class="tit">用户使用率</div>
+                <div class="txt">{{ cpuite.used }} %</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">系统使用率</div>
+                <div class="txt">{{ cpuite.sys }} %</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">当前空闲率</div>
+                <div class="txt">{{ cpuite.free }} %</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">核心数</div>
+                <div class="txt">{{ cpuite.cpuNum }}</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">温度</div>
+                <div class="txt flexc">{{cpuite.temperature}} ℃
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+      </template>
+      <template v-if="server.gpuList&&server.gpuList.length">
+        <!-- gpu -->
+        <div class="carboxs boxb" style="min-width: 30%;" v-for="(gpuite,idx) in server.gpuList" :key="'gpu'+idx">
+          <div class="cardbox " >
+            <div class="titbox titboxa">GPU使用率 {{idx<9?'0'+(idx+1):idx+1}}<span>({{gpuite.name}})</span></div>
+            <gaugeb-chart  v-if="gpuite" :chartData="gpuite"></gaugeb-chart>
+            <div class="flexcw txtboxc">
+              <div class="txtcs">
+                <div class="tit">总显存</div>
+                <div class="txt">{{gpuite.gpuMemory}}</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">使用率</div>
+                <div class="txt">{{gpuite.used}}</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">显存使用</div>
+                <div class="txt">{{gpuite.useMemory}}</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">温度</div>
+                <div class="txt">{{gpuite.temperature}}</div>
+              </div>
+              <div class="txtcs">
+                <div class="tit">功耗</div>
+                <div class="txt">{{gpuite.power}}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
+    </div>
+    <el-row :gutter="14">
+      <el-col :span="24" class="card-box">
+        <div class="cardbox">
+          <div class="titbox">磁盘状态</div>
+          <div class="el-table el-table--enable-row-hover el-table--medium">
+            <table cellspacing="0" style="width: 100%;">
+              <thead>
+                <tr>
+                  <th class="el-table__cell el-table__cell is-leaf"><div class="cell">盘符路径</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">文件系统</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">盘符类型</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">总大小</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">可用大小</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">已用大小</div></th>
+                  <th class="el-table__cell is-leaf"><div class="cell">已用百分比</div></th>
+                </tr>
+              </thead>
+              <tbody v-if="server.sysFiles">
+                <tr v-for="(sysFile, index) in server.sysFiles" :key="index">
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td>
+                  <td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getServer } from "@/api/monitor/server"
+ import waterBallChart from '../servicechart/waterBallChart'
+ import gaugeChart from '../servicechart/gaugeChart'
+ import gaugeaChart from '../servicechart/gaugeaChart'
+ import gaugebChart from '../servicechart/gaugebChart'
+export default {
+  name: "service",
+  components:{waterBallChart,gaugeChart,gaugeaChart,gaugebChart},
+  data() {
+    return {
+      // 服务器信息
+      server: {},
+      waterColora:['rgba(67, 129, 255, 1)','rgba(237, 244, 255, 1)'],
+      waterColorb:['rgba(27, 210, 158, 1)','rgba(237, 244, 255, 1)'],
+      timer:null
+    }
+  },
+  created() {
+    clearInterval(this.timer)
+    var that=this;
+    that.getList()
+    this.timer=setInterval(()=>{
+      that.getList()
+    },10000)
+    this.openLoading()
+  },
+  destroyed() {
+    clearInterval(this.timer)
+  },
+  mounted() {
+  },
+  methods: {
+    /** 查询服务器信息 */
+    getList() {
+      getServer().then(response => {
+        if(response.code!=200){
+          clearInterval(this.timer)
+        }
+        this.server = JSON.parse(JSON.stringify(response.data));
+        this.$modal.closeLoading()
+      })
+    },
+    // 打开加载层
+    openLoading() {
+      this.$modal.loading("正在加载服务监控数据,请稍候!")
+    },
+  }
+}
+</script>
+<style lang="scss" scoped>
+.card-box{padding: 0 7px !important;}
+.mb14{margin-bottom: 14px;}
+.cardbox ::v-deep{
+  .el-table::before{display: none;}
+  .el-table thead{color: #333;
+    th{border-bottom: 1px solid #E6E6E6 !important;}
+  }
+  .el-table th.el-table__cell.is-leaf,.el-table td.el-table__cell{border-bottom: none;}
+}
+  .flexc{display: flex;align-items: center;}
+  .flex0{flex: 0 0 auto;}
+  .flex1{flex: 1;}
+  .flex{display: flex;}
+  .w50{width: 50%;}
+  .flexcw{display: flex;flex-wrap: wrap;}
+.card-box{margin-bottom: 14px !important;}
+.toplinea{
+    .topa{width: 100%;flex: 0 0 auto;}
+    .topb{flex: 1;}
+  }
+.carboxs{padding: 0 7px 0px;margin-bottom: 14px;box-sizing: border-box;
+    &.topb{//信息
+      .topbox{flex: 1;}
+      .txts{padding-left: 8px !important;}
+    }
+    &.boxb{//cpu
+       min-height: 444px;flex: 1;
+       .titboxa{min-height:44px;}
+    }
+}
+.cardbox{
+  background: #FFFFFF;border-radius: 10px;padding: 24px 0 0;box-sizing: border-box;
+  .el-table{padding: 0 35px 10px;margin-top: 10px;color: #333}
+  .topbox{flex-wrap: wrap;padding: 16px 14px;margin-top: 2px;
+    .txts{min-width: 25%;display: flex;flex-direction: column;position: relative;padding: 13px 0px 13px 20px;box-sizing: border-box;flex: 1 0 auto;
+      .tit{font-weight: 500;font-size: 14px;color: #3D455B;margin-bottom: 12px;}
+      .txt{font-weight: bold;font-size: 16px;color: #333333;}
+    }
+  }
+  .waterbox{width: 48%;flex: 0 0 auto;}
+  .watxtbox{flex: 1;display: flex;flex-wrap: wrap;
+    .txts{width: 50%;flex: 0 0 auto;padding: 11px 6px;box-sizing: border-box;
+      .tit{font-weight: 500;font-size: 14px;color: #3D455B;margin-bottom: 8px;}
+      .txt{font-size: 20px;color: #333333;font-weight: bold;}
+    }
+  }
+  .guttit{margin: 0 auto;padding: 10px 0;max-width: 300px;
+      .tit{font-size: 18px;color: #3D455B;width: 33.3%;flex: 0 0 auto;display: flex;align-items: center;justify-content: center;
+        .txt{font-size: 14px;margin-left: 8px;color: #AAAAAA;}
+        img{width: 8px;height: 14px;margin-right: 7px;}
+      }
+      .num{font-size: 20px;color: #333333;flex: 1;text-align: center;
+        span{font-size: 16px;color: #333333;margin-left: 6px;}
+      }
+  }
+  .txtboxc{padding: 14px 17px 10px;
+    .txtcs{min-width: 33.3%;box-sizing: border-box;
+        display: flex;flex-wrap: wrap;flex: 0 0 auto;padding: 11px 0 11px 10px;flex-direction: column;
+        .tit{font-weight: 500;font-size: 14px;color: #3D455B;margin-bottom: 9px;}
+        .txt{font-size: 20px;color: #333333;font-weight: bold;
+          .txtbtn{display: inline-block;margin-left: 10px;height: 20px;padding: 0 6px;
+    font-weight: 500;font-size: 12px;color: #FFFFFF;border-radius: 4px;line-height: 20px;
+            &.bga{background: #45CB99;}
+            &.bgb{background: #FFCC51;}
+            &.bgc{background: #FD666D;}
+    }
+        }
+      }
+  }
+
+}
+.titbox{font-weight: bold;font-size: 16px;color: #333333;padding-left: 14px;position: relative;line-height: 22px;
+  &::before{content: '';left: 0;height: 20px;top: 1px;background-color: #03BF8A;width: 6px;position: absolute;}
+  span{font-size: 16px;color: #AAAAAA;font-weight: 400;}
+}
+</style>

+ 138 - 0
ruoyi-ui/src/views/system/servicechart/gaugeChart.vue

@@ -0,0 +1,138 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '140px'
+    },
+    chartData: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ } = {}) {
+      this.chart.setOption({
+         // 配置项
+        series: [{
+              type: 'gauge',
+              center: ["50%", "90%"], //调整位置
+              radius: '150%', //外圆半径55
+              startAngle: 180,
+              endAngle: 0, // 结束位置
+              progress: {
+                show: true,
+                width: 13,
+                color:'#6296FF',
+              },
+              pointer: {
+                length: "60%",
+                width: 5,
+                itemStyle: {
+                  type: 'linear',
+                    color: '#6296FF' // 修改指针颜色
+                }
+              },
+              itemStyle:{
+                normal: {
+                  //具体颜色显示
+                    color: '#6296FF',
+                  },
+              },
+              axisLine: {
+                lineStyle: {
+                  width: 10,
+                  color: [
+                    [1, '#E8EBF0']
+                  ]
+                }
+              },
+              axisTick: {
+                show: false
+              },
+              splitLine: {
+                length: 6,
+                distance: 8,
+                lineStyle: {
+                  width: 1,
+                  color: '#999'
+                }
+              },
+              axisLabel: {
+                distance: 14,
+                color: '#999',
+                fontSize: 12
+              },
+              anchor: {
+                show: true,
+                showAbove: true,
+                size: 12,
+                itemStyle: {
+                  borderWidth: 6,
+                  borderColor: "#6296FF"
+                }
+              },
+              title: {
+                show: false
+              },
+              detail: {
+                valueAnimation: true,
+                fontSize: 32,
+                offsetCenter: [0, '50%']
+              },
+              data: [
+                {
+                  value: 40
+                }
+              ]
+            }]
+      })
+    }
+  }
+}
+</script>

+ 144 - 0
ruoyi-ui/src/views/system/servicechart/gaugeaChart.vue

@@ -0,0 +1,144 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '200px'
+    },
+    chartData: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ speed} = {}) {
+      const val=speed||0
+      this.chart.setOption({
+         // 配置项
+        series: [{
+      type: 'gauge',
+      radius: "100%",
+      center: ["50%", "50%"], //调整位置
+      axisLine: {
+        lineStyle: {
+          width: 16,
+          color: [
+            [0.3, '#69E5AC'],
+            [0.7, '#6296FF'],
+            [1, '#FFCC51']
+          ]
+        }
+      },
+      pointer: {
+        itemStyle: {
+          color: 'auto'
+        }
+      },
+      axisTick: {
+        distance: -16,
+        length: 6,
+        splitNumber: 5,
+        lineStyle: {
+          color: '#fff',
+          width: 1
+        }
+      },
+      splitLine: {
+        distance: -30,
+        length: 30,
+        lineStyle: {
+          color: '#fff',
+          width: 4
+        }
+      },
+      axisLabel: {
+        color: 'inherit',
+        distance: 22,
+        fontSize: 12
+      },
+      detail: {
+        valueAnimation: true,
+        formatter: '{value} GHz',
+        color: '#AAAAAA',
+        fontSize: 16,
+        fontWeight: '400',
+         offsetCenter: [0, "60%"], // 居中显示(默认值)
+        formatter: function(value) {
+          // 使用富文本标签实现换行和不同样式
+              return [
+                  '{a|' + val +'}'+'GHz',
+                  // '{b|正常}'
+              ].join('\n');
+          },
+          // 定义富文本样式
+          rich: {
+              a: {
+                  fontSize: 22,
+                  color: '#333333',
+                  align: 'center',
+                  padding: [0, 5, 0, 0]
+              },
+              b: {
+                  fontSize: 16,
+                  fontWeight: '500',
+                  color: '#666666',
+                  align: 'center',
+              },
+          }
+      },
+      data: [
+        {
+          value: val
+        }
+      ]
+    }]
+      })
+    }
+  }
+}
+</script>

+ 147 - 0
ruoyi-ui/src/views/system/servicechart/gaugebChart.vue

@@ -0,0 +1,147 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '200px'
+    },
+    chartData: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ used} = {}) {
+      var val=used?used.split('%')[0]:0
+      this.chart.setOption({
+         // 配置项
+        series: [{
+      type: 'gauge',
+      radius: "100%",
+      center: ["50%", "50%"], //调整位置
+      axisLine: {
+        lineStyle: {
+          width: 16,
+          color: [
+            [0.3, '#67E0E3'],
+            [0.7, '#37A2DA'],
+            [1, '#FD666D']
+          ]
+        }
+      },
+      pointer: {
+        itemStyle: {
+          color: 'auto'
+        }
+      },
+      axisTick: {
+        distance: -16,
+        length: 6,
+        splitNumber: 5,
+        lineStyle: {
+          color: '#fff',
+          width: 1
+        }
+      },
+      splitLine: {
+        distance: -30,
+        length: 30,
+        lineStyle: {
+          color: '#fff',
+          width: 4
+        }
+      },
+      axisLabel: {
+        color: 'inherit',
+        distance: 22,
+        fontSize: 12
+      },
+      detail: {
+        valueAnimation: true,
+        formatter: used,
+        color: '#AAAAAA',
+        fontSize: 16,
+        fontWeight: '400',
+         offsetCenter: [0, "60%"], // 居中显示(默认值)
+        formatter: function(value) {
+          // 使用富文本标签实现换行和不同样式
+              return [
+                  '{a|' + val +'}'+'%',
+              ].join('\n');
+              // return [
+              //     '{a|' + value +'}'+'GHz',
+              //     '{b|正常}'
+              // ].join('\n');
+          },
+          // 定义富文本样式
+          rich: {
+              a: {
+                  fontSize: 22,
+                  color: '#333333',
+                  align: 'center',
+                  padding: [0, 5, 0, 0]
+              },
+              b: {
+                  fontSize: 16,
+                  fontWeight: '500',
+                  color: '#666666',
+                  align: 'center'
+              },
+          }
+      },
+      data: [
+        {
+          value: val
+        }
+      ]
+    }]
+      })
+    }
+  }
+}
+</script>

+ 56 - 0
ruoyi-ui/src/views/system/servicechart/mixins/resize.js

@@ -0,0 +1,56 @@
+import { debounce } from '@/utils'
+
+export default {
+  data() {
+    return {
+      $_sidebarElm: null,
+      $_resizeHandler: null
+    }
+  },
+  mounted() {
+    this.initListener()
+  },
+  activated() {
+    if (!this.$_resizeHandler) {
+      // avoid duplication init
+      this.initListener()
+    }
+
+    // when keep-alive chart activated, auto resize
+    this.resize()
+  },
+  beforeDestroy() {
+    this.destroyListener()
+  },
+  deactivated() {
+    this.destroyListener()
+  },
+  methods: {
+    // use $_ for mixins properties
+    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
+    $_sidebarResizeHandler(e) {
+      if (e.propertyName === 'width') {
+        this.$_resizeHandler()
+      }
+    },
+    initListener() {
+      this.$_resizeHandler = debounce(() => {
+        this.resize()
+      }, 100)
+      window.addEventListener('resize', this.$_resizeHandler)
+
+      this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
+      this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
+    },
+    destroyListener() {
+      window.removeEventListener('resize', this.$_resizeHandler)
+      this.$_resizeHandler = null
+
+      this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
+    },
+    resize() {
+      const { chart } = this
+      chart && chart.resize()
+    }
+  }
+}

+ 123 - 0
ruoyi-ui/src/views/system/servicechart/waterBallChart.vue

@@ -0,0 +1,123 @@
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+import 'echarts-liquidfill'; // 引入液体填充插件
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '182px'
+    },
+    chartData: {
+      type: Object,
+      required: true
+    },
+    waterColors:{
+      type: Array,
+      default: ['rgba(67, 129, 255, 1)','rgba(237, 244, 255, 1)']
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ usage } = {}) {
+      const datanum=usage/100||0;
+      const val=usage||0
+      // 定义渐变颜色 - 水的颜色
+      const waterColor = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+           { offset: 0, color: this.waterColors[0] },   // 上部颜色
+          { offset: 1, color: this.waterColors[1] }   // 下部颜色
+       ]);
+      this.chart.setOption({
+         // 配置项
+        series: [{
+          type: 'liquidFill',//设置图表类型
+          data: [datanum], // 设置水位,值为0到1之间
+          radius: '80%', // 设置图的大小
+          outline: {
+            borderDistance: 4, // 外边框距离
+            itemStyle: {
+              borderWidth: 8, // 外边框宽度
+              borderColor: '#F6F6F6' ,// 外边框颜色
+              shadowBlur:0,// 阴影模糊度
+            }
+          },
+          color: [waterColor],
+          backgroundStyle: {
+            color: '#F4F7FE' ,// 背景色
+          },
+          label: {
+            formatter: function(value) {
+              // 使用富文本标签实现换行和不同样式
+                  return [
+                      '{a|' + val +'}{b|%}',
+                      // '{b|正常}'
+                  ].join('\n');
+              },
+              // 定义富文本样式
+              rich: {
+                  a: {
+                      fontSize: 22,
+                      color: '#333333',
+                      align: 'center',
+                      padding: [0, 9, 10, 0]
+                  },
+                  b: {
+                      fontSize: 16,
+                      color: '#333333',
+                  },
+                  c: {
+                      fontSize: 16,
+                      fontWeight: '500',
+                      color: '#666666',
+                      align: 'center'
+                  },
+              }
+          }
+        }]
+      })
+    }
+  }
+}
+</script>