From 577edb4400290865acb07f8342f7ee0c1055aa70 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@iotlink.com>
Date: 星期三, 29 七月 2020 10:39:56 +0800
Subject: [PATCH] appp:添加算力管理

---
 src/pages/analysisPower/index/mixins.ts     |   13 
 src/components/subComponents/SystemInfo.vue |  204 ++++++++++++
 package.json                                |    6 
 src/pages/analysisPower/index/main.ts       |   20 +
 src/pages/desktop/index/mock/userData.json  |   54 +-
 src/pages/analysisPower/index/App.vue       |  608 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 876 insertions(+), 29 deletions(-)

diff --git a/package.json b/package.json
index d3e822c..793a32b 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,8 @@
     "@hscmap/vue-window": "^2.4.2",
     "axios": "^0.19.2",
     "d3-force": "^2.0.1",
-    "element-ui": "^2.4.6",
+    "echarts": "^4.8.0",
+    "element-ui": "^2.13.2",
     "less-loader": "^6.2.0",
     "pug": "^3.0.0",
     "pug-plain-loader": "^1.0.0",
@@ -22,6 +23,7 @@
     "stylus-loader": "^3.0.2",
     "vue": "^2.6.11",
     "vue-awesome-swiper": "^3.1.3",
+    "vue-js-toggle-button": "^1.3.3",
     "vue-qrcode-component": "^2.1.1",
     "vuex": "^3.5.1"
   },
@@ -75,4 +77,4 @@
   "keywords": [],
   "author": "",
   "license": "ISC"
-}
+}
\ No newline at end of file
diff --git a/src/components/subComponents/SystemInfo.vue b/src/components/subComponents/SystemInfo.vue
new file mode 100644
index 0000000..5dd0915
--- /dev/null
+++ b/src/components/subComponents/SystemInfo.vue
@@ -0,0 +1,204 @@
+<template>
+  <div :class="showClass">
+    <div class="card-box" :style="`width:${borderWidth}`">
+      <ul>
+        <li style="max-width:30px;" v-if="ShowLocalVedio">
+          <div class="total-box">
+            <div style="width:100%;margin-top:28px;">
+              <div class="top-text">
+                <em>{{"鎬荤畻鍔�"}}</em>
+              </div>
+              <div class="mid-text">
+                <em>{{` ${PollData.channelTotal}`}}</em>
+              </div>
+            </div>
+          </div>
+        </li>
+        <li style="max-width:120px" v-if="showRealPoll">
+          <DataStackCard
+            style="width:95%"
+            title="瀹炴椂绠楀姏"
+            fourTip="鏁呴殰瀵艰嚧鏈鐞�"
+            fourIcon="iconicon-test21"
+            :total="`${PollData.RealTimeValidCount}璺痐"
+            :ValidCount="`${PollData.RealTimeSum}璺痐"
+            :InValidCount="`${PollData.RealTimeInvalid}璺痐"
+            :RunningCount="`${PollData.RealTimeRun}璺痐"
+            :NoDeal="`${PollData.RealTimeNoDeal}璺痐"
+          />
+        </li>
+        <li style="max-width:120px" v-if="showRealPoll">
+          <DataStackCard
+            title="杞绠楀姏"
+            fourTip="绛夊緟杞澶勭悊"
+            fourIcon="iconicon-test2"
+            style="width:95%"
+            :total="`${PollData.PollValidCount}璺痐"
+            :ValidCount="`${PollData.PollSum}璺痐"
+            :InValidCount="`${PollData.PollInvalid}璺痐"
+            :RunningCount="`${PollData.PollRun}璺痐"
+            :NoDeal="`${PollData.PollNoDeal}璺痐"
+          />
+        </li>
+        <li style="max-width:120px" v-if="ShowLocalVedio">
+          <!-- <local-vedio-card
+            title="鏈湴绠楀姏"
+            style="width:95%"
+            :total="`${PollData.localVideo}閫氶亾`"
+            :success="`${PollData.PollRun}璺痐"
+            :warning="`${PollData.PollInvalid}璺痐"
+          />-->
+          <DataStackCard
+            title="鏁版嵁鏍堢畻鍔�"
+            style="width:95%"
+            fourTip="鏈煡鍘熷洜瀵艰嚧鏈鐞�"
+            fourIcon="iconicon-test5"
+            :total="`${PollData.stackChannelCount}璺痐"
+            :ValidCount="`${PollData.stackTotal}璺痐"
+            :InValidCount="`${PollData.stackInvalidCount}璺痐"
+            :RunningCount="`${PollData.stackRunningCount}璺痐"
+            :NoDeal="`${PollData.stackNoDeal}璺痐"
+          ></DataStackCard>
+        </li>
+      </ul>
+    </div>
+    <!-- <div :class="marginTop" :style="`width:${liquidWidth};`">
+      <ul>
+        <li>
+          <liquid-fill-chart title="鍐呭瓨" :value="PollData.MemUsedPercent" :size="75" />
+        </li>
+        <li>
+          <liquid-fill-chart title="绠楀姏" :value="PollData.GpuUsedPercent" :size="75" />
+        </li>
+        <li>
+          <liquid-fill-chart title="CPU" :value="PollData.CpuUsedPercent" :size="75" />
+        </li> 
+      </ul>
+    </div>-->
+    <div class="eCharts-box" :style="`width:${liquidWidth}`">
+      <eChartsBar ref="cpuMeneryCharts" :xAxisData="PollData.barCharts"></eChartsBar>
+    </div>
+  </div>
+</template>
+
+<script>
+import DataStackCard from "@/components/subComponents/DataStackCard"
+import eChartsBar from '@/components/subComponents/eChartsBar'
+
+export default {
+  name: "SystemInfo",
+  components: {
+    DataStackCard,
+    eChartsBar,
+  },
+  props: {
+    showTask: {
+      type: Boolean,
+      default: false
+    },
+    showClass: {
+      type: String,
+      default: 'sysinfo-box flex-box'
+    },
+    ShowLocalVedio: {
+      type: Boolean,
+      default: false
+    },
+    showRealPoll: {
+      type: Boolean,
+      default: true
+    },
+    marginTop: {
+      type: String,
+      default: 'ma'
+    },
+    borderWidth: {
+      type: String,
+      default: '70%'
+    },
+    liquidWidth: {
+      type: String,
+      default: '30%'
+    }
+  },
+  methods: {
+    initCpuCharts() {
+      this.$forceUpdate();
+    }
+  },
+}
+</script>
+<style lang="scss">
+.sysinfo-box {
+  height: 100%;
+  .card-box {
+    width: 50%;
+    @media screen and (min-width: 1280px) and (max-width: 1440px) {
+      width: 65%;
+    }
+    @media screen and (max-width: 1279px) {
+      width: 70%;
+    }
+    .total-box {
+      height: 120px;
+      width: 100%;
+      display: inline-block;
+      margin: 10px 5px;
+      background: #ffffff;
+      border: 1px solid #e2e2e2;
+      box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+      border-radius: 4px;
+      cursor: pointer;
+      .top-text {
+        line-height: 30px;
+        font-family: PingFangSC-Medium;
+        font-size: 14px;
+        color: #222222;
+      }
+      .mid-text {
+        margin-bottom: 18px;
+        font-family: PingFangSC-Medium;
+        font-size: 18px;
+        color: #ff7733;
+      }
+      .bottom-text {
+        position: relative;
+        top: 3px;
+        left: 1px;
+        color: #666666;
+        font-size: 13px;
+      }
+      em {
+        font-weight: 700;
+      }
+    }
+  }
+  .eCharts-box {
+    width: 50%;
+    height: 100%;
+    margin-left: 5px;
+    @media screen and (min-width: 1280px) and (max-width: 1440px) {
+      width: 35%;
+    }
+    @media screen and (max-width: 1279px) {
+      width: 30%;
+    }
+  }
+  .chart-box {
+    float: left;
+    width: 50%;
+    margin-top: 20px;
+    margin-left: 20px;
+  }
+  ul {
+    list-style: none;
+    display: table;
+    width: 100%;
+    li {
+      display: table-cell;
+      text-align: center;
+      vertical-align: top;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/analysisPower/index/App.vue b/src/pages/analysisPower/index/App.vue
new file mode 100644
index 0000000..ed19b56
--- /dev/null
+++ b/src/pages/analysisPower/index/App.vue
@@ -0,0 +1,608 @@
+<template>
+  <div class="s-poll-setting">
+    <div class="top" v-show="!strethTable">
+      <div class="percentBall">
+        <sysinfo
+          ref="sysInfo"
+          v-if="showSysInfo"
+          :ShowLocalVedio="true"
+          showTask
+          showClass="sysinfo-box flex-row-left"
+        />
+      </div>
+
+      <div class="barGraph">
+        <div id="barSimple"></div>
+      </div>
+    </div>
+
+    <div class="bottom">
+      <div style="width: 100%;height: 10px;background-color: #E9EBF2;"></div>
+      <div class="content">
+        <div class="toolBar">
+          <el-input
+            size="small"
+            style="width: 180px;"
+            placeholder="璇疯緭鍏ユ悳绱㈠唴瀹�"
+            prefix-icon="el-icon-search"
+            clearable
+            v-model="PollData.SearchName"
+          ></el-input>
+          <el-button
+            size="small"
+            type="primary"
+            style="margin-left: 20px; margin-right: 50px;"
+            @click="pollSeach"
+          >鎼滅储</el-button>
+          <div class="tip">
+            <span>
+              杞鏃堕棿 :
+              <b>{{PollData.Config.poll_period}}</b>鍒嗛挓
+            </span>
+            <span>
+              杞鍛ㄦ湡 :
+              <b>{{pollCycle}}</b>鍒嗛挓
+            </span>
+            <span>
+              杞寮�鍏� :
+              <b>{{PollData.Enabled | switchText}}</b>
+            </span>
+          </div>
+          <span :class="stretchStyle" @click="strethTable = !strethTable"></span>
+
+          <el-button size="small" type="primary" style="float:right" @click="openDrawer">璁剧疆</el-button>
+        </div>
+
+        <el-table
+          :header-cell-style="{background:'#F8F8F8', color: '#222222'}"
+          :data="PollData.CameraList"
+          height="93%"
+          border
+        >
+          <el-table-column label="搴忓彿" type="index" align="center" width="100px"></el-table-column>
+          <el-table-column label="鎽勫儚鏈哄悕绉�" align="center" show-overflow-tooltip sortable>
+            <template slot-scope="scope">
+              <span
+                :style="scope.row.is_running ? `color:#3d68e1` : '' "
+              >{{scope.row.alias !== '' ? scope.row.alias: scope.row.name}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎽勫儚鏈哄湴鍧�" prop="addr" align="center" show-overflow-tooltip sortable></el-table-column>
+          <el-table-column label="鎽勫儚鏈篒P" prop="ip" align="center" width="130px" sortable></el-table-column>
+          <el-table-column label="鎽勫儚鏈虹被鍨�" align="center" width="110px" sortable>
+            <template slot-scope="scope">
+              <span>{{scope.row.run_type | cameraType}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎵ц绠楁硶" align="center" show-overflow-tooltip sortable>
+            <template slot-scope="scope">
+              <span v-if="scope.row.run_type === -1 ">-</span>
+              <span v-else>{{scope.row.tasks | taskList}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="杩愯璁惧" align="center" width="160px">
+            <template slot-scope="scope">
+              <span v-if="scope.row.run_type === -1 ">-</span>
+              <span v-else>{{scope.row.runServerName}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" align="center" show-overflow-tooltip sortable width="100px">
+            <template slot-scope="scope">
+              <span v-if="scope.row.status === -1 ">-</span>
+              <span v-else-if="scope.row.status === 2">{{"澶勭悊涓�"}}</span>
+              <span v-else-if="scope.row.status === 1">{{"绛夊緟澶勭悊"}}</span>
+              <span v-else-if="scope.row.status === 0">{{"瑙勫垯涓嶅叏"}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="瀹炴椂/杞" align="center" width="100px">
+            <template slot-scope="scope">
+              <span v-if="scope.row.run_type === -1 ">-</span>
+              <toggle-button
+                v-else
+                :value="scope.row.run_type === 1"
+                :width="60"
+                :labels="{checked: '瀹炴椂', unchecked: '杞'}"
+                :color="{checked: '#4D88FF', unchecked: '#FF7733', disabled: '#CCCCCC'}"
+                :sync="true"
+                @change="pollSwitch(scope.row)"
+              />
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+    <!-- 璁剧疆寮圭獥 -->
+    <el-drawer
+      title="绠楀姏璁剧疆"
+      :visible.sync="drawer"
+      direction="rtl"
+      size="350px"
+      custom-class="e-drawer"
+      :before-close="closeDrawer"
+    >
+      <div class="dawer_details">
+        <span>鎬荤畻鍔� {{formData.totalChanle}} 閫氶亾</span>
+        <span style="margin-left:20px">瀹炴椂绠楀姏 {{formData.realTime}} 閫氶亾</span>
+      </div>
+      <div class="e-drawer_rate">
+        <div class="rate">
+          <label>杞鏃堕棿</label>
+          <el-input-number
+            size="small"
+            style="width: 60px;margin-left:25px"
+            v-model.number="formData.pollPeriod"
+            :controls="false"
+            :min="0"
+            :max="60 * 24 * 1"
+          ></el-input-number>
+          <span>鍒嗛挓</span>
+
+          <label>杞寮�鍏�</label>
+          <el-switch style="margin-left: 10px;" v-model="formData.pollEnable"></el-switch>
+        </div>
+        <div class="rate">
+          <label>杞绠楀姏</label>
+          <el-input-number
+            style="margin-left:25px;width:90px"
+            size="small"
+            v-model="formData.polling"
+            @change="changePoll"
+            controls-position="right"
+            :min="0"
+            :max="maxPoll"
+          ></el-input-number>
+        </div>
+        <div class="rate">
+          <label>鏁版嵁鏍堢畻鍔�</label>
+          <el-input-number
+            style="margin-left:11px;width:90px"
+            size="small"
+            v-model="formData.dataStack"
+            @change="changeStack"
+            controls-position="right"
+            :min="0"
+            :max="maxDataStack"
+          ></el-input-number>
+        </div>
+
+        <el-button
+          size="small"
+          type="primary"
+          style="margin:10px 10px 0px 200px"
+          @click="saveSetting"
+        >淇濆瓨</el-button>
+        <el-button size="small" type="info" style="color:black" @click="closeDrawer">鍙栨秷</el-button>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import echarts from "echarts";
+import { changeRunType, updatePollEnable, updatePollPeriod, updateChannelCount } from "@/api/pollConfig";
+
+import Sysinfo from "@/components/subComponents/SystemInfo"
+// import SliderVedio from '@/components/camera/slider-vedio'
+// import eChartsBar from '@/components/subComponents/eChartsBar'
+export default {
+  name: "PollSeting",
+  components: {
+    Sysinfo,
+    // SliderVedio,
+    // eChartsBar
+  },
+  filters: {
+    cameraType(type) {
+      return type === -1 ? "鐩戞帶鎽勫儚鏈�" : "AI鎽勫儚鏈�";
+    },
+    taskList(tasks) {
+      return tasks.filter(task => {
+        return task.hasRule;
+      }).map(task => {
+        return task.taskname
+      }).join(',')
+    },
+    switchText(type) {
+      return type ? "宸插紑鍚�" : "鏈紑鍚�";
+    }
+  },
+  computed: {
+    maxPoll() {
+      return this.formData.totalChanle - this.formData.realTime;
+    },
+    maxDataStack() {
+      return this.formData.totalChanle - this.formData.realTime;
+    },
+    stretchStyle() {
+      let arry = ["iconfont", "stretch-btn"];
+      arry.push(this.strethTable ? "iconzhankai" : "iconshouqi")
+      return arry;
+    },
+    pollCycle() {
+      let sumPollingCamera = 0;
+      this.PollData.CameraList.forEach(cam => {
+        if (cam.run_type === 0) {
+          sumPollingCamera++
+        }
+      })
+
+      return sumPollingCamera * this.PollData.Config.poll_period
+    }
+  },
+  data() {
+    return {
+      switchValue: true,
+      search: "",
+      timeout: null,
+      taskName: [],
+      dataList: [],
+      barChart: {},
+      localDataChannel: 2,
+      showSysInfo: false,
+      drawer: false,
+      formData: {},
+      strethTable: false
+    };
+  },
+  mounted() {
+    this.PollData.init();
+    this.statistic();
+    this.barChart = echarts.init(document.getElementById("barSimple"));
+    this.initLineChart();
+  },
+  beforeDestroy() {
+    clearTimeout(this.timeout);
+  },
+  methods: {
+    openDrawer() {
+      this.initFormData();
+      this.drawer = true;
+    },
+    closeDrawer() {
+      this.drawer = false;
+      this.initFormData();
+    },
+    initFormData() {
+      this.formData = {
+        totalChanle: this.PollData.channelTotal,
+        realTime: this.PollData.RealTimeSum,
+        pollEnable: this.PollData.Enabled,
+        pollPeriod: this.PollData.Config.poll_period,
+        polling: this.PollData.PollChannelTotal,
+        dataStack: this.PollData.localVideo,
+      }
+    },
+    pollSeach() {
+      this.PollData.fetchPollList();
+    },
+    pollEnable() {
+      updatePollEnable({ enable: this.PollData.Enabled }).then(rsp => {
+        this.$notify({
+          type: "success",
+          message: "淇敼鎴愬姛"
+        });
+        // this.PollData.fetchPollConfig()
+      })
+    },
+    updateDelayTime() {
+      updatePollPeriod({ period: this.PollData.Config.poll_period }).then(rsp => {
+        if (rsp && rsp.success) {
+          this.$notify({
+            type: 'success',
+            message: '杞鏃堕棿淇敼鎴愬姛锛�'
+          })
+        } else {
+          this.$notify({
+            type: 'error',
+            message: '杞鏃堕棿淇敼澶辫触锛�'
+          })
+        }
+      })
+    },
+    statistic() {
+      this.PollData.statistics();
+      let _this = this;
+      _this.timeout = setTimeout(() => {
+        _this.statistic();
+      }, 10 * 1000);
+    },
+    pollSwitch(row) {
+      changeRunType({ camera_ids: [row.id], run_type: row.run_type ^ 1 }).then(
+        rsp => {
+          if (rsp && rsp.success) {
+            this.$notify({
+              type: "success",
+              message: "閰嶇疆鎴愬姛"
+            });
+
+            row.run_type = row.run_type ^ 1
+
+          } else {
+            this.$notify({
+              type: "error",
+              message: "閰嶇疆澶辫触"
+            });
+          }
+
+          // this.PollData.fetchPollList();
+        }
+      );
+    },
+    initLineChart() {
+      // console.log(this.barChart,'initLineChart')
+      // this.$refs.sysInfo.initCpuCharts();
+      let optionBar = {
+        color: ["#3D68E1"],
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            // 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
+            type: "shadow" // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
+          }
+        },
+        grid: {
+          top: 40,
+          // bottom: '45%',
+          left: 0,
+          containLabel: true
+        },
+
+        xAxis: [
+          {
+            type: "category",
+            data: this.taskName,
+            axisTick: {
+              // alignWithLabel: true
+            },
+            axisLine: {
+              show: false
+            },
+            nameLocation: 'start',
+            axisTick: {
+              show: false
+            },
+            axisLabel: {
+              rotate: 45,
+              formatter: function (value, index) {
+                let name = ""
+                if (value.length > 2) {
+                  name = value.substring(0, 2) + '...'
+                } else {
+                  name = value
+                }
+                let text = [`{a|${name}}`]
+                return text
+              },
+              rich: {
+                a: {
+                  fontSize: 10,
+                  with: 30
+                }
+              }
+            }
+          }
+        ],
+        yAxis: [
+          {
+            type: "value",
+            show: true,
+            axisLine: {
+              show: false
+            },
+            splitLine: {
+              lineStyle: {
+                type: "dotted",
+                color: ['#f1f1f1']
+              }
+            },
+            axisTick: {
+              show: false
+            }
+          }
+        ],
+        series: [
+          {
+            name: "鏁伴噺",
+            type: "bar",
+            barWidth: "30%",
+            data: this.dataList
+          }
+        ]
+      };
+      this.showSysInfo = true
+      this.barChart.setOption(optionBar);
+      this.barChart.resize()
+      this.$nextTick(() => {
+        this.barChart.resize()
+      })
+    },
+
+    //婊戝潡鏁版嵁鏇存柊鍥炶皟
+    changeSlider(val) {
+      // console.log(val, '婊戝潡鍊煎彉鍔�')
+      let fileChannelCount = val[val.length - 1] - val[val.length - 2]
+      let pollChannelCount = val[val.length - 2] - val[val.length - 3]
+      this.PollData.updateChannelCount(fileChannelCount, pollChannelCount)
+    },
+
+    async saveSetting() {
+      let rsp = await updatePollEnable({ enable: this.formData.pollEnable })
+      if (!rsp || !rsp.success) {
+        this.formData.pollEnable = !this.formData.pollEnable
+        this.$notify({
+          type: "error",
+          message: "杞寮�鍏冲垏鎹㈠け璐ワ紒"
+        });
+        return
+      }
+
+      rsp = await updatePollPeriod({ period: this.formData.pollPeriod })
+      if (!rsp || !rsp.success) {
+        this.$notify({
+          type: "error",
+          message: "杞鏃堕棿淇敼澶辫触锛�"
+        });
+        return
+      }
+      rsp = await updateChannelCount({ videoChannelCount: this.formData.dataStack, pollChannelCount: this.formData.polling })
+      if (!rsp || !rsp.success) {
+        this.$notify({
+          type: "error",
+          message: "绠楀姏閰嶇疆澶辫触锛�"
+        });
+        return
+      } else {
+        this.$notify({
+          type: "success",
+          message: "閰嶇疆淇濆瓨鎴愬姛"
+        });
+      }
+      this.PollData.statisticTaskInfo()
+      this.PollData.fetchPollConfig()
+    },
+
+    //鐩戝惉杞绠楀姏
+    changePoll(newVal, oldVal) {
+      if (newVal > oldVal) {
+        this.formData.dataStack--
+      }
+      if (newVal < oldVal) {
+        this.formData.dataStack++
+      }
+      // console.log("this.formData.dataStack:"+this.formData.dataStack)
+    },
+    //鐩戝惉鏁版嵁鏍堢畻鍔�
+    changeStack(newVal, oldVal) {
+      if (newVal > oldVal) {
+        this.formData.polling--
+      }
+      if (newVal < oldVal) {
+        this.formData.polling++
+      }
+      // console.log("this.formData.polling:"+this.formData.polling)
+    }
+  }
+};
+</script>
+<style lang="scss">
+.s-poll-setting {
+  width: 100%;
+  height: 100%;
+  font-size: 14px;
+  position: relative;
+  .top {
+    width: 100%;
+    height: 190px;
+    // border-bottom: 1px solid #ccc;
+    .progressBar {
+      width: 26%;
+    }
+    .percentBall {
+      width: 80%;
+      height: 82%;
+      float: left;
+      // @media screen and (min-width: 1280px) and (max-width: 1440px) {
+      //   width: 75%;
+      // }
+      // @media screen and (max-width: 1280px) {
+      //   width: 80%;
+      // }
+    }
+    .barGraph {
+      width: 20%;
+      height: 100%;
+      float: right;
+      // @media screen and (min-width: 1280px) and (max-width: 1440px) {
+      //   width: 25%;
+      // }
+      // @media screen and (max-width: 1280px) {
+      //   width: 20%;
+      // }
+      #barSimple {
+        width: 100%;
+        height: 250px;
+        margin-top: -30px;
+      }
+    }
+    .point {
+      text-align: right;
+      margin-left: 64px;
+      b {
+        display: inline-block;
+        width: 9px;
+        height: 9px;
+        border-radius: 50%;
+        background-color: #f53d3d;
+      }
+    }
+  }
+  .bottom {
+    width: calc(100% + 76px);
+    height: 100%;
+    // height: calc(100% - 220px);
+    position: absolute;
+    // top: 220px;
+    left: -38px;
+    .tip {
+      display: inline-block;
+      font-family: PingFangSC-Medium;
+      font-size: 14px;
+      span {
+        margin: 0px 10px;
+      }
+    }
+    .content {
+      padding: 20px 38px 38px 38px;
+      box-sizing: border-box;
+      width: 100%;
+      height: 100%;
+      .toolBar {
+        width: 100%;
+        height: 42px;
+        text-align: left;
+        margin-bottom: 15px;
+      }
+      .el-table {
+        border: 1px solid #e0e0e0;
+      }
+    }
+
+    .stretch-btn {
+      float: right;
+      margin-left: 10px;
+      line-height: 35px;
+      cursor: pointer;
+    }
+  }
+}
+
+.e-drawer {
+  // margin-top: 150px;
+
+  font-family: PingFangSC-Medium;
+  font-size: 14px;
+  .dawer_details {
+    text-align: left;
+    margin-left: 70px;
+    margin-top: 30px;
+  }
+  .e-drawer_rate {
+    width: 100%;
+    margin-top: 15px;
+    .rate {
+      width: 100%;
+      text-align: left;
+      margin-top: 15px;
+      margin-left: 50px;
+    }
+    label {
+      margin-left: 20px;
+    }
+  }
+
+  .el-drawer__header {
+    margin-bottom: 0px;
+  }
+}
+</style>
diff --git a/src/pages/analysisPower/index/main.ts b/src/pages/analysisPower/index/main.ts
new file mode 100644
index 0000000..fdbeeda
--- /dev/null
+++ b/src/pages/analysisPower/index/main.ts
@@ -0,0 +1,20 @@
+import Vue from 'vue'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css';
+import "@/assets/css/element-variables.scss";
+import "../../../assets/icons/alibaba/iconfont.css";
+import "../../../assets/icons/basic/iconfont.css";
+import "../../../assets/icons/iconfont.css";
+import "../../../assets/icons/symbol.js";
+
+import App from './App.vue'
+import ToggleButton from 'vue-js-toggle-button';
+import Mixin from "./mixins";
+
+Vue.use(ElementUI)
+Vue.use(ToggleButton)
+Vue.mixin(Mixin);
+new Vue({
+  el: '#app',
+  render: h => h(App)
+})
diff --git a/src/pages/analysisPower/index/mixins.ts b/src/pages/analysisPower/index/mixins.ts
new file mode 100644
index 0000000..9c6bb20
--- /dev/null
+++ b/src/pages/analysisPower/index/mixins.ts
@@ -0,0 +1,13 @@
+import DataPool from "@/Pool/PollData"
+
+/* eslint-disable */
+const onlyDataPool = new DataPool
+
+const mixin = {
+  data() {
+    return {
+      PollData: onlyDataPool
+    };
+  },
+};
+export default mixin;
\ No newline at end of file
diff --git a/src/pages/desktop/index/mock/userData.json b/src/pages/desktop/index/mock/userData.json
index f6e7281..a08717b 100644
--- a/src/pages/desktop/index/mock/userData.json
+++ b/src/pages/desktop/index/mock/userData.json
@@ -4,12 +4,36 @@
   "data": {
     "docks": [
       {
+        "id": "5",
+        "src": "../../images/app-mid/GB-config.png",
+        "alt": "GB28281閰嶇疆",
+        "type": "2",
+        "url": "/view/gb28181",
+        "name": "GB28281閰嶇疆"
+      },
+      {
+        "id": "12",
+        "src": "../../images/app-mid/monitor.png",
+        "alt": "瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁",
+        "type": "2",
+        "url": "/view/cameraVideo",
+        "name": "瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁"
+      },
+      {
+        "id": "9",
+        "src": "../../images/app-mid/algorithm-manage.png",
+        "alt": "绠楁硶绠$悊",
+        "type": "2",
+        "url": "/view/algorithmManage",
+        "name": "绠楁硶绠$悊"
+      },
+      {
         "id": "1",
         "src": "../../images/app-mid/camera-access.png",
         "alt": "camera-access",
         "type": "2",
         "url": "/view/camera",
-        "name":"鎽勫儚鏈烘帴鍏�"
+        "name": "鎽勫儚鏈烘帴鍏�"
       },
       {
         "id": "2",
@@ -17,7 +41,7 @@
         "alt": "datastack-config",
         "type": "2",
         "url": "/view/datastack",
-        "name":"鏁版嵁鏍堥厤缃�"
+        "name": "鏁版嵁鏍堥厤缃�"
       },
       {
         "id": "3",
@@ -34,14 +58,6 @@
         "type": "2",
         "url": "/view/datapush",
         "name": "鏁版嵁鎺ㄩ��"
-      },
-      {
-        "id": "5",
-        "src": "../../images/app-mid/GB-config.png",
-        "alt": "GB28281閰嶇疆",
-        "type": "2",
-        "url": "/view/gb28181",
-        "name": "GB28281閰嶇疆"
       },
       {
         "id": "6",
@@ -68,14 +84,6 @@
         "name": "杞绠$悊"
       },
       {
-        "id": "9",
-        "src": "../../images/app-mid/algorithm-manage.png",
-        "alt": "绠楁硶绠$悊",
-        "type": "2",
-        "url": "/view/algorithmManage",
-        "name": "绠楁硶绠$悊"
-      },
-      {
         "id": "10",
         "src": "../../images/app-mid/algorithm-store.png",
         "alt": "绠楁硶鍟嗗煄",
@@ -88,16 +96,8 @@
         "src": "../../images/app-mid/hashrate-manage.png",
         "alt": "绠楀姏绠$悊",
         "type": "2",
-        "url": "/view/hashrateManage",
+        "url": "/view/analysisPower",
         "name": "绠楀姏绠$悊"
-      },
-      {
-        "id": "12",
-        "src": "../../images/app-mid/monitor.png",
-        "alt": "瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁",
-        "type": "2",
-        "url": "/view/monitor",
-        "name": "瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁"
       },
       {
         "id": "13",

--
Gitblit v1.8.0