From 1e1e5f612f252d66b0d0386cf52873bb1f3f7d7b Mon Sep 17 00:00:00 2001
From: haoxuan <haoxuan>
Date: 星期五, 01 九月 2023 16:10:37 +0800
Subject: [PATCH] 系统维护+系统监控器+调试工具的app 增加

---
 public/images/app-mid/productionSign.png          |    0 
 public/images/desktop/header-icon/SmartAI-新.png   |    0 
 public/images/app-mid/debuggTool.png              |    0 
 src/pages/vindicate/index/App.vue                 |  617 ++++++++++++++++
 src/pages/vindicate/index/main.ts                 |   16 
 src/pages/desktop/index/components/ToolsEntry.vue |    3 
 src/pages/systemMonitor/index/main.ts             |   16 
 src/pages/systemMonitor/index/App.vue             |  853 ++++++++++++++++++++++
 src/pages/systemMonitor/api/api.ts                |   22 
 public/apps.json                                  |   74 +
 src/pages/debuggTool/index/App.vue                |  617 ++++++++++++++++
 src/pages/debuggTool/index/main.ts                |   16 
 12 files changed, 2,231 insertions(+), 3 deletions(-)

diff --git a/public/apps.json b/public/apps.json
index b066097..64f07a2 100644
--- a/public/apps.json
+++ b/public/apps.json
@@ -93,17 +93,85 @@
       "isUpgrade": false,
       "progressMsg": ""
     },
-    
+    {
+      "id": "ee64fe23-7631-4ef9-9aca-ea09673693be",
+      "name": "绯荤粺缁存姢",
+      "package": "vindicate",
+      "type": "2",
+      "url": "/view/vindicate/",
+      "title": "绯荤粺缁存姢",
+      "width": 760,
+      "height": 534,
+      "iconBlob": "",
+      "icon": "../../images/app-mid/vindicate.png",
+      "version": "1.0.0",
+      "create_time": "2020-10-09 14:00:11",
+      "create_by": "",
+      "update_time": "",
+      "update_by": "",
+      "isDelete": 0,
+      "isDefault": true,
+      "remoteVersion": "",
+      "installed": true,
+      "isUpgrade": false,
+      "progressMsg": ""
+    },
     {
       "id": "fa5674ee-70cf-4e22-8a06-c17429fb777",
-      "name": "鐢熶骇绠$悊鐪嬫澘",
+      "name": "鐢熶骇浠诲姟",
       "package": "shuohuangMonitorAnalyze",
       "type": "1",
       "url": "http://192.168.20.125:8080",
-      "title": "鐢熶骇绠$悊鐪嬫澘",
+      "title": "鐢熶骇浠诲姟",
+      "width": 0,
+      "height": 0,
+      "iconBlob": "",
+      "icon": "../../images/app-mid/productionSign.png",
+      "version": "1.0.0",
+      "create_time": "2020-10-09 14:00:08",
+      "create_by": "",
+      "update_time": "",
+      "update_by": "",
+      "isDelete": 0,
+      "isDefault": false,
+      "remoteVersion": "",
+      "installed": true,
+      "isUpgrade": false,
+      "progressMsg": ""
+    },
+    {
+      "id": "fa5674ee-70cf-4e22-8a06-c17429fb777",
+      "name": "璋冭瘯宸ュ叿",
+      "package": "debuggTool",
+      "type": "2",
+      "url": "/view/debuggTool/",
+      "title": "璋冭瘯宸ュ叿",
       "width": 1500,
       "height": 750,
       "iconBlob": "",
+      "icon": "../../images/app-mid/debuggTool.png",
+      "version": "1.0.0",
+      "create_time": "2020-10-09 14:00:08",
+      "create_by": "",
+      "update_time": "",
+      "update_by": "",
+      "isDelete": 0,
+      "isDefault": false,
+      "remoteVersion": "",
+      "installed": true,
+      "isUpgrade": false,
+      "progressMsg": ""
+    },
+    {
+      "id": "fa5674ee-70cf-4e22-8a06-c171292b777",
+      "name": "绯荤粺鐩戞帶",
+      "package": "systemMonitor",
+      "type": "2",
+      "url": "/view/systemMonitor/",
+      "title": "绯荤粺鐩戞帶",
+      "width": 1220,
+      "height": 800,
+      "iconBlob": "",
       "icon": "../../images/app-mid/visual.png",
       "version": "1.0.0",
       "create_time": "2020-10-09 14:00:08",
diff --git a/public/images/app-mid/debuggTool.png b/public/images/app-mid/debuggTool.png
new file mode 100644
index 0000000..3e3957a
--- /dev/null
+++ b/public/images/app-mid/debuggTool.png
Binary files differ
diff --git a/public/images/app-mid/productionSign.png b/public/images/app-mid/productionSign.png
new file mode 100644
index 0000000..8bd7c19
--- /dev/null
+++ b/public/images/app-mid/productionSign.png
Binary files differ
diff --git "a/public/images/desktop/header-icon/SmartAI-\346\226\260.png" "b/public/images/desktop/header-icon/SmartAI-\346\226\260.png"
index a5546cc..f865095 100644
--- "a/public/images/desktop/header-icon/SmartAI-\346\226\260.png"
+++ "b/public/images/desktop/header-icon/SmartAI-\346\226\260.png"
Binary files differ
diff --git a/src/pages/debuggTool/index/App.vue b/src/pages/debuggTool/index/App.vue
new file mode 100644
index 0000000..7f0e417
--- /dev/null
+++ b/src/pages/debuggTool/index/App.vue
@@ -0,0 +1,617 @@
+<template>
+  <div class="s-system-manage">
+    <el-tabs
+      id="systemMaintenance"
+      v-model="activeName"
+      v-loading="loading"
+      :element-loading-text="loadingText"
+    >
+      <el-tab-pane label="璁惧缁存姢" name="device" v-if="isShow('vindicate:device')">
+        <div class="s-system-maintenance">
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">閲嶅惎</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-button type="primary" size="small" style="width:80px" @click="reboot">閲嶅惎</el-button>
+
+              <b class="card-text">閲嶅惎鑺傜偣</b>
+
+              <el-row style="margin-top:20px">
+                <el-col>
+                  <vue-cron :expression="rebootCron" @update="setRebootCron" />
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          <!--
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鎭㈠榛樿鍊�</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-row>
+                <el-col :span="1">
+                  <el-button type="primary" size="small">绠�鍗曟仮澶�</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">绠�鍗曟仮澶嶈澶囧弬鏁�</b>
+                </el-col>
+              </el-row>
+              <el-row style="margin-top:20px">
+                <el-col :span="1">
+                  <el-button type="primary" size="small">瀹屽叏鎭㈠</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">瀹屽叏鎭㈠璁惧鍙傛暟鍒板嚭鍘傝缃�</b>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鍙傛暟瀵煎叆瀵煎嚭</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-row :gutter="4">
+                <el-col :span="1">
+                  <el-button type="info" size="small" style="width:80px">瀵煎叆</el-button>
+                </el-col>
+                <el-col :span="3" style="padding-left:30px">
+                  <el-input placeholder="涓婁紶鍙傛暟鏂囦欢" size="small" :readonly="true">
+                    <el-upload slot="suffix" action="https://jsonplaceholder.typicode.com/posts/">
+                      <el-button
+                        type="text"
+                        icon="el-icon-upload2"
+                        size="small"
+                        style="font-size:18px; color:#0088ff"
+                      ></el-button>
+                    </el-upload>
+                  </el-input>
+                </el-col>
+              </el-row>
+              <el-row style="margin-top:20px">
+                <el-col :span="1">
+                  <el-button type="primary" size="small">璁惧鍙傛暟</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">鍙傛暟瀵煎嚭</b>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          -->
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鍗囩骇</div>
+            </div>
+          </div>
+          <el-divider></el-divider>
+          <div class="box-card-content">
+            <el-row :gutter="4">
+              <el-col :span="12">
+                <file-uploader
+                  single
+                  uploadPlaceholder="涓婁紶鍗囩骇鏂囦欢"
+                  url="/data/api-v/sysset/patchUpdate"
+                  @complete="onFileUpload"
+                  @file-added="onFileAdded"
+                />
+              </el-col>
+              <el-col :span="2">
+                <el-button
+                  type="primary"
+                  size="small"
+                  style="width:80px"
+                  @click="upgrade"
+                  :disabled="!fileAdded"
+                  :loading="upgrading"
+                >鍗囩骇</el-button>
+              </el-col>
+              <el-col :span="16" class="upload-msg">
+                <span v-html="patchUpdateStatus"></span>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="鏁版嵁搴撶淮鎶�" name="dbvdc" v-if="isShow('vindicate:db')">
+        <div class="box">
+          <p class="title">
+            <label>鏁版嵁娓呯悊</label>
+          </p>
+          <div class="range">
+            <div class="left">
+              <p>閫夋嫨鏁版嵁鑼冨洿锛�</p>
+            </div>
+            <div class="middle">
+              <el-date-picker
+                v-model="dataRange"
+                type="daterange"
+                range-separator="鑷�"
+                start-placeholder="寮�濮嬫棩鏈�"
+                end-placeholder="缁撴潫鏃ユ湡"
+                style="height:38px"
+                :picker-options="pickerOptions"
+              ></el-date-picker>
+            </div>
+            <div class="right">
+              <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">鍒犻櫎鏁版嵁</el-button>
+            </div>
+          </div>
+          <div class="tip">
+            <i class="iconfont icontishi-zhuyi"></i>
+            <p class="zhuyi">璇锋敞鎰忥紝鎸変互涓婃棩鏈熻寖鍥村垹闄ょ殑鏁版嵁涓嶅彲鎭㈠锛岀珛鍗崇敓鏁堬紝璇疯皑鎱庢搷浣�</p>
+          </div>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade, deleteDate } from "@/api/system"
+import VueCron from "@/components/subComponents/VueCron"
+import FileUploader from "@/components/subComponents/FileUpload/index"
+
+export default {
+  components: {
+    VueCron,
+    FileUploader
+  },
+  data() {
+    return {
+      timer: null,
+      buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
+      rebootCron: "",
+      activeName: "device",
+      restartValue: "涓嶉噸鍚�",
+      restartTimeValue: new Date(2019, 9, 10, 18, 40),
+      loading: false,
+      loadingText: '',
+      probeSum: 0,
+      patchUpdateStatus: "",
+      dataRange: [
+        this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+        this.$moment().format("YYYY-MM-DD HH:mm:ss")
+      ],
+      fileUploadUrl: fileUpload,
+      patchFile: {},
+      pickerOptions: {
+        disabledDate(time) {
+          var day = new Date()
+          day.setTime(day.getTime() - 24 * 60 * 60 * 1000)
+          return time.getTime() > day;
+        },
+      },
+      upgrading: false,
+      fileAdded: false,
+    };
+  },
+  mounted() {
+    this.getRebootCron()
+    if (!this.isShow('vindicate:device')) {
+      this.activeName = "dbvdc"
+    }
+  },
+  computed: {
+    isAdmin() {
+      if (
+        sessionStorage.getItem('userInfo') &&
+        sessionStorage.getItem('userInfo') !== ''
+      ) {
+        let loginName = JSON.parse(sessionStorage.getItem('userInfo')).username
+        return (
+          loginName === 'superadmin' || loginName === 'basic'
+        )
+      }
+      return false;
+    }
+  },
+  methods: {
+    isShow(authority) {
+      if (this.isAdmin) {
+        return true
+      } else if (
+        this.buttonAuthority.indexOf(',' + authority + ',') > -1
+      ) {
+        return true
+      } else {
+        return false
+      }
+    },
+    format(array) {
+      return [
+        this.$moment(array[0]).format("YYYY-MM-DD"),
+        this.$moment(array[1]).format("YYYY-MM-DD")
+      ];
+    },
+    getRebootCron() {
+      getRebootTask().then(rsp => {
+        this.rebootCron = rsp.data
+      })
+    },
+    setRebootCron(value) {
+      this.rebootCron = value
+      setRebootTask({ task: value }).then(rsp => {
+        if (rsp && rsp.success) {
+          this.$notify({
+            type: "success",
+            message: "閰嶇疆鎴愬姛"
+          })
+        }
+      }).catch(err => {
+        this.$notify({
+          type: "error",
+          message: "閰嶇疆澶辫触"
+        })
+      })
+    },
+    reboot() {
+      this.$confirm('纭畾瑕侀噸鍚鑺傜偣鍚�?', {
+        center: true,
+        cancelButtonClass: 'comfirm-class-cancle',
+        confirmButtonClass: 'comfirm-class-sure'
+      }).then(() => {
+        this.loading = true;
+        this.loadingText = "鏅鸿兘璁$畻鑺傜偣姝e湪閲嶅惎锛岃鑰愬績绛夊緟..."
+        rebootServer().then(rsp => {
+          this.probeServer(this.reLogin)
+        }).catch(err => {
+          if (err.status == 400) {
+            this.loading = false;
+            this.$notify({
+              type: "error",
+              message: "閲嶅惎璁$畻鑺傜偣澶辫触"
+            })
+          } else {
+            this.probeServer(this.reLogin)
+          }
+        })
+      })
+    },
+    deleteData() {
+      var timeRange = this.format(this.dataRange);
+      var showStartTime = timeRange[0]
+      var showEndTime = timeRange[1]
+      console.log("鏃堕棿锛�", showStartTime, showEndTime)
+      this.$confirm("鎻愮ず锛�" + showStartTime + " 鑷� " + showEndTime + " 浜х敓鐨勫叏閮ㄦ暟鎹皢琚垹闄わ紝姝ゆ搷浣滅珛鍗崇敓鏁堬紝涓嶅彲鎭㈠锛屾槸鍚﹀垹闄わ紵", {
+        center: true,
+        cancelButtonClass: "comfirm-class-cancle",
+        confirmButtonClass: "comfirm-class-sure"
+      }).then(() => {
+        this.loading = true
+        this.loadingText = "姝e湪鍒犻櫎鏁版嵁锛岃绋嶅�欙紒"
+        var param = {
+          startTime: showStartTime,
+          endTime: showEndTime
+        }
+        deleteDate(param).then(resp => {
+          if (resp.success) {
+            this.$message({
+              type: "success",
+              message: "鍒犻櫎鏁版嵁鎴愬姛"
+            })
+            this.loading = false
+          }
+        }).catch(err => {
+          this.$message({
+            type: "error",
+            message: "鍒犻櫎鏁版嵁澶辫触锛�"
+          })
+          this.loading = false
+        })
+
+      }).catch(() => {
+        console.log("鍙栨秷浜嗭紒")
+      })
+    },
+    reLogin() {
+      this.$router.push("/")
+    },
+    probeServer(callback) {
+      this.probeSum++;
+      let _this = this
+      if (this.probeSum > 60) {
+        this.$confirm('杩炴帴鏈嶅姟鍣ㄥけ璐�, 璇峰埛鏂伴〉闈㈡垨鑱旂郴绠$悊鍛�', '澶辫触', {
+          type: 'error',
+          cancelButtonClass: 'comfirm-class-cancle',
+          confirmButtonClass: 'comfirm-class-sure'
+        }).then(() => {
+          // _this.$router.push("/")
+          callback()
+        })
+        return
+      }
+
+      this.timer = setTimeout(() => {
+        getDevInfo().then(() => {
+          // _this.$router.push("/")
+          callback()
+        }).catch(err => {
+          _this.probeServer(callback)
+        })
+      }, 10000)
+    },
+    onFileUpload(file) {
+      this.patchUpdateStatus = `<span style="color:green">涓婁紶鎴愬姛, 鐐瑰嚮鍗囩骇鎸夐挳寮�濮嬪崌绾�</span>`
+      this.patchFile = { ...file }
+      this.fileAdded = true
+    },
+    onFileAdded() {
+      this.patchUpdateStatus = ""
+    },
+    upgrade() {
+      this.upgrading = true
+      this.patchUpdateStatus = `<span style="color:red">姝e湪鍗囩骇...</span>`
+      doUpgrade(this.patchFile).then(rsp => {
+        this.upgrading = false
+
+        if (rsp && rsp.success) {
+          clearTimeout(this.timer)
+          this.doneUpgrade()
+        }
+      }).catch(err => {
+        if (err.code) {
+          this.upgrading = false
+          this.patchUpdateStatus = `<span style="color:red">${err.data}</span>`
+          clearTimeout(this.timer)
+        } else {
+          this.probeServer(this.doneUpgrade)
+        }
+      })
+    },
+    doneUpgrade() {
+      this.upgrading = false
+      this.patchUpdateStatus = `<span style="color:green">鍗囩骇鎴愬姛</span>`
+      let _this = this
+      this.$confirm('鍗囩骇鎴愬姛, 璇烽噸鏂扮櫥褰曠郴缁�', '鎴愬姛', {
+        type: 'success',
+        cancelButtonClass: 'comfirm-class-cancle',
+        confirmButtonClass: 'comfirm-class-sure'
+      }).then(() => {
+        _this.reLogin()
+      })
+    }
+  }
+};
+</script>
+<style lang="scss">
+.s-system-manage {
+  width: 100% !important;
+  min-width: 759px;
+  box-sizing: border-box;
+  padding: 10px;
+  // background-color: #e9ebf2;
+  background-color: #fff;
+  .s-system-manage-breadcrumb {
+    height: 5%;
+    box-sizing: border-box;
+    border: 1px solid #e4e7ed;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    border-radius: 5px;
+  }
+
+  .el-tabs--border-card {
+    border: 0px solid #dcdfe6;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+    .el-tabs__header {
+      border: 0px solid #dcdfe6;
+      .el-tabs__item {
+        padding: 5px 50px;
+        height: 50px;
+        font-family: PingFangSC-Regular;
+        font-size: 15px;
+        color: #222222;
+        text-align: center;
+        border: 0px solid transparent;
+      }
+      .el-tabs__item:nth-child(2) {
+        padding-left: 50px !important;
+      }
+      .el-tabs__item:last-child {
+        padding-right: 50px !important;
+      }
+      .el-tabs__item.is-active {
+        color: #3d68e1;
+        font-weight: bold;
+        // border-right-color: #fff;
+        // border-left-color: #fff;
+      }
+      .el-tabs__item:not(.is-disabled):hover {
+        color: #3d68e1;
+      }
+    }
+  }
+  .el-tabs__content {
+    height: calc(100% - 64px);
+    width: calc(100% - 20px);
+    box-sizing: border-box;
+    overflow-y: auto;
+    padding: 10px 40px !important;
+    .el-tab-pane {
+      width: 100%;
+      .s-title {
+        text-align: left;
+        padding: 15px 0px;
+        font-size: 16px;
+      }
+    }
+  }
+
+  .s-table {
+    border: 1px solid #e8e8e9;
+    margin-top: 40px;
+  }
+
+  .ui-top-title {
+    padding-bottom: 10px;
+    /* border-bottom: 1px solid #ebebeb; */
+    position: relative;
+    text-align: left;
+    padding-left: 15px;
+    font-size: 16px;
+    font-weight: bold;
+  }
+
+  .ui-top-title:before {
+    content: " ";
+    border-left: 4px solid #f53d3d;
+    display: inline-block;
+    height: 16px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    margin-top: -13px;
+  }
+
+  .el-button--text {
+    color: #3d68e1;
+    text-decoration: underline;
+  }
+}
+.s-system-maintenance {
+  width: 100%;
+  height: 100%;
+  .el-button--primary {
+    color: #ffffff;
+    background-color: #3d68e1;
+    border-color: #3d68e1;
+  }
+  .el-button--primary.is-disabled,
+  .el-button--primary.is-disabled:hover,
+  .el-button--primary.is-disabled:focus,
+  .el-button--primary.is-disabled:active {
+    color: #ffffff;
+    background-color: #9eb4f0;
+    border-color: #9eb4f0;
+  }
+  .box-card {
+    text-align: left;
+    height: auto;
+    margin: 10px 0px;
+    .box-card-content {
+      padding-bottom: 40px;
+      .card-text {
+        padding: 0 30px;
+        line-height: 32px;
+      }
+    }
+  }
+
+  .upload-icon {
+    font-size: 18px;
+    color: #0088ff;
+  }
+  .upload-msg {
+    padding-left: 10px;
+    text-align: left;
+    span {
+      line-height: 32px;
+      font-size: 13px;
+    }
+  }
+}
+.box {
+  width: 50%;
+  min-width: 700px;
+  height: 270px;
+  border: 1px solid #eee;
+  .title {
+    font-size: 20px;
+    font-weight: bold;
+    text-align: left;
+    padding: 20px;
+    border-bottom: 1px solid #eee;
+  }
+  .range {
+    width: 100%;
+    padding-top: 30px;
+    height: 38px;
+    .left {
+      width: 120px;
+      float: left;
+      text-align: right;
+      font-size: 14px;
+      p {
+        height: 38px;
+        line-height: 38px;
+        margin: 0;
+      }
+    }
+    .middle {
+      width: 50%;
+      min-width: 400px;
+      height: 38px;
+      float: left;
+    }
+    .right {
+      width: 20%;
+      height: 38px;
+      float: left;
+    }
+  }
+  .tip {
+    width: 100%;
+    padding: 30px 0px 0px 30px;
+    height: 34px;
+
+    .zhuyi {
+      font-size: 14px;
+      height: 34px;
+      line-height: 34px;
+      margin-left: 20px;
+      float: left;
+    }
+    i {
+      font-size: 32px;
+      color: #e99038;
+      float: left;
+    }
+  }
+}
+#systemMaintenance {
+  .el-tabs__header {
+    border: 0px solid #dcdfe6;
+    .el-tabs__item {
+      padding: 5px 50px;
+      height: 50px;
+      font-family: PingFangSC-Regular;
+      font-size: 14px;
+      color: #222222;
+      text-align: center;
+      border: 0px solid transparent;
+    }
+    .el-tabs__item:nth-child(2) {
+      padding-left: 50px;
+    }
+    .el-tabs__item:last-child {
+      padding-right: 50px;
+    }
+    .el-tabs__item.is-active {
+      color: #ff7733;
+      font-weight: bold;
+      // border-right-color: #fff;
+      // border-left-color: #fff;
+    }
+    .el-tabs__item:not(.is-disabled):hover {
+      color: #ff7733;
+    }
+  }
+  .el-tabs__active-bar {
+    background-color: #ff7733;
+  }
+  .el-tabs__content {
+    padding-left: 15px !important;
+  }
+}
+</style>
diff --git a/src/pages/debuggTool/index/main.ts b/src/pages/debuggTool/index/main.ts
new file mode 100644
index 0000000..b5ea667
--- /dev/null
+++ b/src/pages/debuggTool/index/main.ts
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import App from './App.vue';
+
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import "@/assets/css/element-variables.scss";
+
+import moment from 'moment';
+
+Vue.use(ElementUI)
+Vue.prototype.$moment = moment;
+
+new Vue({
+  el: '#app',
+  render: h => h(App)
+})
\ No newline at end of file
diff --git a/src/pages/desktop/index/components/ToolsEntry.vue b/src/pages/desktop/index/components/ToolsEntry.vue
index 63730ea..4e9b703 100644
--- a/src/pages/desktop/index/components/ToolsEntry.vue
+++ b/src/pages/desktop/index/components/ToolsEntry.vue
@@ -190,6 +190,9 @@
       if (dock.type === "1") {
         window.open(dock.url);
       } else if (dock.type === "2" && !dock.isOpen) {
+        if(dock.url== "/view/debuggTool/"){
+          return true;
+        }
         this.$store.dispatch("desktop/addFrame", {
           id: dock.id,
           icon: dock.src,
diff --git a/src/pages/systemMonitor/api/api.ts b/src/pages/systemMonitor/api/api.ts
new file mode 100644
index 0000000..abba575
--- /dev/null
+++ b/src/pages/systemMonitor/api/api.ts
@@ -0,0 +1,22 @@
+import request from "@/scripts/httpRequest";
+
+export const showSystemStates = () => {
+  return request({
+    url: "/data/api-z/system/showSystemStates",
+    method: "get"
+  });
+};
+
+export const showService = () => {
+  return request({
+    url: "/data/api-z/system/showService",
+    method: "get"
+  });
+};
+
+export const showProcesses = () => {
+  return request({
+    url: "/data/api-z/system/showProcesses",
+    method: "get"
+  });
+};
diff --git a/src/pages/systemMonitor/index/App.vue b/src/pages/systemMonitor/index/App.vue
new file mode 100644
index 0000000..88437be
--- /dev/null
+++ b/src/pages/systemMonitor/index/App.vue
@@ -0,0 +1,853 @@
+<template>
+  <div class="s-system-monitor">
+    <el-tabs id="systemMonitor" v-model="activeName">
+      <el-tab-pane label="鍗曞厓" name="proc">
+        <div class="form-title">
+          <b>绠楁硶鍗曞厓</b>
+          (姝e湪杩涜{{algoProcessData.length}}涓畻娉曞崟鍏�)
+          <el-table :data="algoProcessData" style="width: 100%">
+            <el-table-column prop="desc" label="鍚嶇О" width="180"></el-table-column>
+            <el-table-column label="CPU" width="180">
+              <template slot-scope="scope">
+                <span>{{ scope.row.cpu.toFixed(2)}} %</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="鍐呭瓨">
+              <template slot-scope="scope">
+                <span>{{ scope.row.mem.toFixed(2)}} %</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="disk" label="纭洏"></el-table-column>
+            <el-table-column label="绠楀姏">
+              <template slot-scope="scope">
+                <span>{{ scope.row.gpu}} M</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="net" label="缃戠粶"></el-table-column>
+          </el-table>
+        </div>
+
+        <div class="form-title" style="margin-top:20px">
+          <b>搴旂敤鍗曞厓</b>
+          (姝e湪杩涜{{appProcessData.length}}涓簲鐢ㄥ崟鍏�)
+          <el-table :data="appProcessData" style="width: 100%">
+            <el-table-column prop="desc" label="鍚嶇О" width="180"></el-table-column>
+            <el-table-column prop="cpu" label="CPU" width="180"></el-table-column>
+            <el-table-column prop="mem" label="鍐呭瓨"></el-table-column>
+            <el-table-column prop="disk" label="纭洏"></el-table-column>
+            <el-table-column prop="gpu" label="绠楀姏"></el-table-column>
+            <el-table-column prop="net" label="缃戠粶"></el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <el-tab-pane label="鎬ц兘" name="top">
+        <div class="column-left" ref="left">
+          <div class="resize-bar">
+            <div
+              :class="['ax_default', activeChartItem == 'cpu' ?'selected': '']"
+              @click="setActiveChartItem('cpu')"
+            >
+              <div class="ax_default_pic color-cpu"></div>
+              <div class="ax_default_text">CPU</div>
+              <div class="ax_default_subtext">{{cpuUsedPercent}}%</div>
+            </div>
+
+            <div
+              :class="['ax_default', activeChartItem == 'mem' ?'selected': '']"
+              @click="setActiveChartItem('mem')"
+            >
+              <div class="ax_default_pic color-mem"></div>
+              <div class="ax_default_text">鍐呭瓨</div>
+              <div class="ax_default_subtext">{{memUsedPercent}}%</div>
+            </div>
+
+            <div
+              :class="['ax_default', activeChartItem == 'gpu' ?'selected': '']"
+              @click="setActiveChartItem('gpu')"
+            >
+              <div class="ax_default_pic color-gpu"></div>
+              <div class="ax_default_text">绠楀姏</div>
+              <div class="ax_default_subtext">{{gpuUsedPercent}}%</div>
+            </div>
+
+            <div
+              :class="['ax_default', activeChartItem == 'net' ?'selected': '']"
+              @click="setActiveChartItem('net')"
+            >
+              <div class="ax_default_pic color-net"></div>
+              <div class="ax_default_text">缃戠粶</div>
+              <div class="ax_default_subtext">{{netSend | byteConver}} / {{netRecive | byteConver}}</div>
+            </div>
+
+            <div
+              v-for="(v, k) in disks"
+              :key="k"
+              :class="['ax_default', activeChartItem == ('disk|' + k) ?'selected': '']"
+              @click="setActiveChartItem('disk|'+k)"
+            >
+              <div class="ax_default_pic color-disk"></div>
+              <div class="ax_default_text">纾佺洏 {{k}}</div>
+              <div class="ax_default_subtext">{{v.info.total | byteConver}}</div>
+            </div>
+          </div>
+
+          <div class="resize-line"></div>
+        </div>
+
+        <div class="column-right">
+          <div class="max-val">{{yAxisMaxVal}}</div>
+          <div ref="graphs" class="graphs-chart"></div>
+
+          <div v-show="activeChartItem == 'cpu'">
+            <div class="ax_default_label">
+              <b>鍗犵敤鐜�</b>
+              <p>{{cpuUsedPercent}}%</p>
+            </div>
+            <div class="ax_default_label">
+              <b>涓婚</b>
+              <p>{{cpuMaxRate}}Ghz</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鎻掓Ы</b>
+              <p>{{cpuCount}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鍐呮牳</b>
+              <p>{{cpuCore}}</p>
+            </div>
+          </div>
+
+          <div v-show="activeChartItem == 'mem'">
+            <div class="ax_default_label">
+              <b>浣跨敤涓�</b>
+              <p>{{memUsed}}G</p>
+            </div>
+            <div class="ax_default_label">
+              <b>宸茬紦瀛�</b>
+              <p>{{memCache}}G</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鍙敤</b>
+              <p>{{memFree}}G</p>
+            </div>
+          </div>
+
+          <div v-show="activeChartItem == 'net'">
+            <div class="ax_default_label">
+              <b>鎺ユ敹</b>
+              <p>{{netRecive |byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鍙戦��</b>
+              <p>{{netSend |byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>IP鍦板潃</b>
+              <p>{{ipAddr}}</p>
+            </div>
+            <div class="ax_default_label" style="margin-left: 19px;">
+              <b>MAC鍦板潃</b>
+              <p>{{macAddr}}</p>
+            </div>
+          </div>
+
+          <div v-show="isDisk">
+            <div class="ax_default_label">
+              <b>瀹归噺</b>
+              <p>{{activeDisk.total |byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>宸茬敤</b>
+              <p>{{activeDisk.used |byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鍙敤</b>
+              <p>{{activeDisk.free |byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>璇诲彇閫熷害</b>
+              <p>{{ioRead | byteConver}}</p>
+            </div>
+            <div class="ax_default_label">
+              <b>鍐欏叆閫熷害</b>
+              <p>{{ioWrite | byteConver}}</p>
+            </div>
+          </div>
+        </div>
+      </el-tab-pane>
+
+      <el-tab-pane label="鏈嶅姟" name="service">
+        <el-table :data="vasystemServicesData">
+          <el-table-column label="鍚嶇О" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <span>{{ scope.row.name}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" prop="status">
+            <template slot-scope="scope">
+              <span>{{ scope.row.pid == 0 ? "鏈惎鍔�" : "宸插惎鍔�" }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎻忚堪" prop="desc"></el-table-column>
+        </el-table>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import echarts from "echarts";
+import { showSystemStates, showService, showProcesses } from "../api/api"
+
+export default {
+  components: {
+  },
+  computed: {
+    isDisk() {
+      return this.activeChartItem.indexOf("disk") == 0
+    },
+    isAdmin() {
+      if (
+        sessionStorage.getItem('userInfo') &&
+        sessionStorage.getItem('userInfo') !== ''
+      ) {
+        let loginName = JSON.parse(sessionStorage.getItem('userInfo')).username
+        return (
+          loginName === 'superadmin' || loginName === 'basic'
+        )
+      }
+      return false;
+    }
+  },
+  filters: {
+    byteConver(limit) {
+      var size = "";
+      if (limit < 1024) { //濡傛灉灏忎簬0.1KB杞寲鎴怋  
+        size = limit + "B";
+      } else if (limit < 1024 * 1024) {//濡傛灉灏忎簬0.1MB杞寲鎴怟B  
+        size = (limit / 1024).toFixed(2) + "KB";
+      } else if (limit < 1024 * 1024 * 1024) { //濡傛灉灏忎簬0.1GB杞寲鎴怣B  
+        size = (limit / (1024 * 1024)).toFixed(2) + "MB";
+      } else if (limit < 1024 * 1024 * 1024 * 1024) { //鍏朵粬杞寲鎴怗B  
+        size = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB";
+      } else {
+        size = (limit / (1024 * 1024 * 1024 * 1024)).toFixed(2) + "TB";
+      }
+
+      var sizestr = size + "";
+      var len = sizestr.indexOf("\.");
+      var dec = sizestr.substr(len + 1, 2);
+      if (dec == "00") {//褰撳皬鏁扮偣鍚庝负00鏃� 鍘绘帀灏忔暟閮ㄥ垎  
+        return sizestr.substring(0, len) + sizestr.substr(len + 3, 2);
+      }
+
+      return sizestr;
+    }
+  },
+  data() {
+    return {
+      activeName: "proc",
+      activeChartItem: "cpu",
+      yAxisMaxVal: "100%",
+      algoProcessData: [],
+      appProcessData: [],
+      vasystemServicesData: [],
+      eChartsObj: {},
+      eChartsBaseOpt: {
+        title: {
+          top: 10,
+        },
+        animation: false,
+        grid: {
+          show: true,
+          left: '1%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true,
+          borderWidth: 2,
+          borderColor: '#000'
+        },
+        xAxis: {
+          type: "category",
+          boundaryGap: false,
+          data: Array.from({ length: 60 }, () => 0),
+          // show: false,
+          axisLabel: {
+            show: false
+          },
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            interval: 5,
+            lineStyle: {
+              width: 1,
+              type: 'solid'
+            }
+          }
+        },
+        yAxis: {
+          type: 'value',
+          // show: false,
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            show: false
+          },
+          axisTick: {
+            show: false
+          }
+        },
+        series: [
+          {
+            type: 'line',
+            symbol: 'none',
+            data: Array.from({ length: 60 }, () => 0),
+            // smooth: true,
+            itemStyle: {},
+            areaStyle: {}
+          }
+        ]
+      },
+      cpuUtilizations: Array.from({ length: 60 }, () => 0),
+      memUtilizations: Array.from({ length: 60 }, () => 0),
+      gpuUtilizations: Array.from({ length: 60 }, () => 0),
+      diskIOWriteCount: Array.from({ length: 60 }, () => 0),
+      diskIOReadCount: Array.from({ length: 60 }, () => 0),
+      netReciveCount: Array.from({ length: 60 }, () => 0),
+      netSendCount: Array.from({ length: 60 }, () => 0),
+      cpuModel: "",
+      cpuUsedPercent: 0,
+      cpuMaxRate: 0,
+      cpuCount: 0,
+      cpuCore: 0,
+      memTotal: 0,
+      memUsed: 0,
+      memFree: 0,
+      memCache: 0,
+      memUsedPercent: 0,
+      netSend: 0,
+      netRecive: 0,
+      ipAddr: "",
+      macAddr: "",
+      gpuUsedPercent: 0,
+      disks: {},
+      activeDisk: {},
+      ioRead: 0,
+      ioWrite: 0
+    };
+  },
+  mounted() {
+    this.dataCollection();
+    this.initChart();
+  },
+  methods: {
+    // 寰幆閲囬泦鎵�鏈夋暟鎹�
+    dataCollection() {
+      this.serviceCollect();
+      this.procCollect();
+      setTimeout(() => {
+        this.dataCollection();
+      }, 5000)
+    },
+    serviceCollect() {
+      showService().then(rsp => {
+        if (rsp && rsp.success) {
+          rsp.data.sort(function (obj1, obj2) {
+            var val1 = obj1.name
+            var val2 = obj2.name
+            if (val1 < val2) {
+              return -1
+            } else if (val1 > val2) {
+              return 1
+            } else {
+              return 0
+            }
+          })
+          this.vasystemServicesData = rsp.data;
+        }
+      }).catch(() => { })
+
+    },
+    procCollect() {
+      showProcesses().then(rsp => {
+        if (rsp && rsp.success) {
+          if (rsp.data.algos)
+            this.algoProcessData = rsp.data.algos;
+
+          if (rsp.data.apps)
+            this.appProcessData = rsp.data.apps;
+        }
+
+      }).catch(() => { })
+    },
+    getSystemState() {
+      showSystemStates().then(rsp => {
+        if (rsp && rsp.success) {
+          // 澶勭悊cpu
+          this.cpuUtilizations = this.cpuUtilizations.slice(1);
+          this.cpuUtilizations.push(rsp.data.cpu.toFixed(2));
+          this.cpuUsedPercent = this.cpuUtilizations[59];
+          if (rsp.data.cpu_info) {
+            this.cpuMaxRate = (rsp.data.cpu_info[0].mhz / 1024).toFixed(2);
+            this.cpuModel = rsp.data.cpu_info[0].modelName;
+            this.cpuCore = Number(rsp.data.cpu_info[rsp.data.cpu_info.length - 1].coreId) + 1;
+            this.cpuCount = (rsp.data.cpu_info.length / this.cpuCore).toFixed(0);
+          }
+
+          // 鍐呭瓨
+          this.memUtilizations = this.memUtilizations.slice(1);
+          this.memUtilizations.push(rsp.data.mem.usedPercent.toFixed(2));
+          this.memTotal = (rsp.data.mem.total / 1024 / 1024 / 1000).toFixed(0);
+          this.memUsed = (rsp.data.mem.used / 1024 / 1024 / 1000).toFixed(2);
+          this.memFree = (rsp.data.mem.free / 1024 / 1024 / 1000).toFixed(2);
+          this.memCache = ((rsp.data.mem.cached + rsp.data.mem.buffers) / 1024 / 1024 / 1000).toFixed(2);
+          this.memUsedPercent = rsp.data.mem.usedPercent.toFixed(2);
+
+          // 绠楀姏
+          this.gpuUtilizations = this.gpuUtilizations.slice(1);
+          this.gpuUtilizations.push(rsp.data.gpu.toFixed(2));
+          this.gpuUsedPercent = this.gpuUtilizations[59];
+
+          // 缃戠粶
+          this.netReciveCount = this.netReciveCount.slice(1);
+          this.netReciveCount.push(rsp.data.net.bytesRecv);
+          this.netSendCount = this.netSendCount.slice(1);
+          this.netSendCount.push(rsp.data.net.bytesSent);
+
+          this.netRecive = this.netReciveCount[59];
+          this.netSend = this.netSendCount[59];
+          this.macAddr = rsp.data.net.mac;
+          if (rsp.data.net.addr.length) {
+            this.ipAddr = rsp.data.net.addr[0].addr;
+          }
+
+          // 纾佺洏
+          rsp.data.disk.sort(function (obj1, obj2) {
+            var val1 = obj1.name;
+            var val2 = obj2.name;
+            if (val1 < val2) {
+              return -1;
+            } else if (val1 > val2) {
+              return 1;
+            } else {
+              return 0;
+            }
+          })
+
+          rsp.data.disk.forEach(d => {
+            if (d.name in this.disks) {
+              this.disks[d.name].readBytes = this.disks[d.name].readBytes.slice(1);
+              this.disks[d.name].readBytes.push(d.readBytes);
+              this.disks[d.name].writeBytes = this.disks[d.name].writeBytes.slice(1);
+              this.disks[d.name].writeBytes.push(d.writeBytes);
+            } else {
+              this.disks[d.name] = {};
+              this.disks[d.name]["info"] = d.info;
+              this.disks[d.name]["readBytes"] = Array.from({ length: 60 }, () => 0);
+              this.disks[d.name]["writeBytes"] = Array.from({ length: 60 }, () => 0);
+            }
+          });
+
+          // this.disks = rsp.data.disk;
+        }
+
+
+        this.setChartData();
+        setTimeout(() => {
+          this.getSystemState();
+        }, 1000)
+      })
+    },
+    isShow(authority) {
+      if (this.isAdmin) {
+        return true
+      } else if (
+        this.buttonAuthority.indexOf(',' + authority + ',') > -1
+      ) {
+        return true
+      } else {
+        return false
+      }
+    },
+    format(array) {
+      return [
+        this.$moment(array[0]).format("YYYY-MM-DD"),
+        this.$moment(array[1]).format("YYYY-MM-DD")
+      ];
+    },
+    setActiveChartItem(item) {
+      this.activeChartItem = item;
+      this.eChartsObj.clear();
+      this.setChartData();
+    },
+    initChart() {
+      this.eChartsObj = echarts.init(this.$refs.graphs);
+      this.getSystemState();
+    },
+    setChartData() {
+      let option = JSON.parse(JSON.stringify(this.eChartsBaseOpt));
+      switch (this.activeChartItem) {
+        case 'cpu':
+          this.yAxisMaxVal = this.cpuModel;
+          option.title.text = "CPU";
+          option.title.subtext = "%鍗犵敤鐜�";
+          option.yAxis.max = 100;
+          option.yAxis.min = 0;
+          option.grid.borderColor = "#8aadd0";
+          option.series[0].itemStyle.color = "#8aadd0";
+          option.series[0].areaStyle.color = "#a8d4ff";
+          option.series[0].data = this.cpuUtilizations;
+
+          break;
+        case 'mem':
+          this.yAxisMaxVal = this.memTotal + "G";
+          option.title.text = "鍐呭瓨";
+          option.title.subtext = "鍐呭瓨浣跨敤閲�";
+          option.yAxis.max = 100;
+          option.yAxis.min = 0;
+          option.grid.borderColor = "#ff9900";
+          option.series[0].itemStyle.color = "#ff9900";
+          option.series[0].areaStyle.color = "#f7bb88";
+          option.series[0].data = this.memUtilizations;
+          break;
+        case 'gpu':
+          this.yAxisMaxVal = "100%";
+          option.title.text = "绠楀姏";
+          option.title.subtext = "%浣跨敤鐜�";
+          option.yAxis.max = 100;
+          option.yAxis.min = 0;
+          option.grid.borderColor = "#bc84d8";
+          option.series[0].itemStyle.color = "#bc84d8";
+          option.series[0].areaStyle.color = "#de9dff";
+          option.series[0].data = this.gpuUtilizations;
+          break;
+        case 'net':
+          this.yAxisMaxVal = "";
+          option.title.text = "缃戠粶";
+          option.title.subtext = "缃戠粶璐熻浇";
+          option.grid.borderColor = "#4696da";
+          option.series[0].itemStyle.color = "#ffa16a";
+          option.series[0].areaStyle.color = "#d68658";
+          option.series[0].data = this.netReciveCount;
+          option.series.push({
+            type: 'line',
+            symbol: 'none',
+            data: this.netSendCount,
+            // smooth: true,
+            itemStyle: {
+              color: "#4696da"
+            },
+            areaStyle: {
+              color: "#4eacfd"
+            }
+          })
+          break;
+        default:
+          if (this.activeChartItem.indexOf("disk|") == 0) {
+            let dev = this.activeChartItem.split("|")[1];
+
+            this.yAxisMaxVal = "";
+            option.title.text = "纾佺洏";
+            option.title.subtext = "纾佺洏浼犺緭閫熺巼";
+            option.grid.borderColor = "#33cc66";
+            option.series[0].itemStyle.color = "#4696da";
+            option.series[0].areaStyle.color = "#4eacfd";
+            option.series[0].data = this.disks[dev].readBytes;
+            option.series.push({
+              type: 'line',
+              symbol: 'none',
+              data: this.disks[dev].writeBytes,
+              // smooth: true,
+              itemStyle: {
+                color: "#33ff66"
+              },
+              areaStyle: {
+                color: "#33cc66"
+              }
+            })
+
+            this.activeDisk = this.disks[dev].info;
+            this.ioRead = this.disks[dev].readBytes[59];
+            this.ioWrite = this.disks[dev].writeBytes[59];
+          }
+          break;
+      }
+
+      this.eChartsObj.setOption(option);
+    }
+
+  }
+};
+</script>
+<style lang="scss">
+.s-system-monitor {
+  width: 100% !important;
+  min-width: 759px;
+  box-sizing: border-box;
+  padding: 10px;
+  // background-color: #e9ebf2;
+  background-color: #fff;
+  .form-title {
+    text-align: left;
+    font-size: 14px;
+  }
+
+  .graphs-chart {
+    height: 500px;
+    width: 900px;
+    margin-left: 15px;
+    // border: 1px solid rgb(69, 69, 172);
+  }
+
+  .column-left {
+    background-color: #fff;
+    position: relative;
+    float: left;
+  }
+
+  .column-right {
+    //overflow: hidden;
+    overflow-y: hidden;
+    overflow-x: auto;
+  }
+
+  .max-val {
+    position: absolute;
+    right: 4%;
+    top: 8%;
+  }
+
+  .resize-bar {
+    width: 238px;
+    height: 610px;
+  }
+
+  /* 鎷栨嫿绾� */
+  .resize-line {
+    position: absolute;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    border-right: 1px solid #efefef;
+    border-left: 1px solid #e0e0e0;
+    pointer-events: none;
+  }
+
+  .ax_default {
+    width: 207px;
+    height: 45px;
+    padding: 10px;
+    font-size: 15px;
+    margin: 5px;
+    cursor: pointer;
+  }
+
+  .selected {
+    background: inherit;
+    background-color: #cde8ff;
+    border: none;
+    border-radius: 8px;
+  }
+
+  .ax_default_pic {
+    position: absolute;
+    border-width: 0px;
+    width: 66px;
+    height: 45px;
+    box-sizing: border-box;
+    border: 1px solid rgba(255, 153, 0, 1);
+    background-repeat: no-repeat;
+    background-position: bottom;
+  }
+
+  .color-cpu {
+    border-color: #8aadd0;
+    background-image: url("/images/systemMonitor/cpu.png");
+  }
+
+  .color-mem {
+    border-color: #ff9900;
+    background-image: url("/images/systemMonitor/mem.png");
+  }
+
+  .color-gpu {
+    border-color: #bc84d8;
+    background-image: url("/images/systemMonitor/gpu.png");
+  }
+
+  .color-net {
+    border-color: #4696da;
+    background-image: url("/images/systemMonitor/net.png");
+  }
+
+  .color-disk {
+    border-color: #33cc66;
+    background-image: url("/images/systemMonitor/disk.png");
+  }
+
+  .ax_default_text {
+    position: relative;
+    text-align: left;
+    margin-left: 72px;
+  }
+
+  .ax_default_subtext {
+    font-size: 13px;
+    margin-left: 72px;
+    line-height: 35px;
+    color: #4e4d4d;
+    text-align: left;
+  }
+
+  .ax_default_label {
+    width: 120px;
+    font-size: 15px;
+    display: inline-block;
+    float: left;
+
+    b {
+      font-family: "鎬濇簮榛戜綋";
+      font-weight: 400;
+      font-style: normal;
+      color: #a1a1a1;
+    }
+
+    p {
+      margin-top: 5px;
+    }
+  }
+  .ax_label_flex {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+  }
+  .s-system-monitor-breadcrumb {
+    height: 5%;
+    box-sizing: border-box;
+    border: 1px solid #e4e7ed;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    border-radius: 5px;
+  }
+
+  .el-tabs--border-card {
+    border: 0px solid #dcdfe6;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+    .el-tabs__header {
+      border: 0px solid #dcdfe6;
+      .el-tabs__item {
+        padding: 5px 50px;
+        height: 50px;
+        font-family: PingFangSC-Regular;
+        font-size: 15px;
+        color: #222222;
+        text-align: center;
+        border: 0px solid transparent;
+      }
+      .el-tabs__item:nth-child(2) {
+        padding-left: 50px !important;
+      }
+      .el-tabs__item:last-child {
+        padding-right: 50px !important;
+      }
+      .el-tabs__item.is-active {
+        color: #3d68e1;
+        font-weight: bold;
+        // border-right-color: #fff;
+        // border-left-color: #fff;
+      }
+      .el-tabs__item:not(.is-disabled):hover {
+        color: #3d68e1;
+      }
+    }
+  }
+
+  .el-tabs__content {
+    height: calc(100% - 64px);
+    width: calc(100% - 20px);
+    box-sizing: border-box;
+    overflow-y: auto;
+    padding: 10px 10px !important;
+    .el-tab-pane {
+      width: 100%;
+      .s-title {
+        text-align: left;
+        padding: 15px 0px;
+        font-size: 16px;
+      }
+    }
+  }
+
+  .s-table {
+    border: 1px solid #e8e8e9;
+    margin-top: 40px;
+  }
+
+  .ui-top-title {
+    padding-bottom: 10px;
+    /* border-bottom: 1px solid #ebebeb; */
+    position: relative;
+    text-align: left;
+    padding-left: 15px;
+    font-size: 16px;
+    font-weight: bold;
+  }
+
+  .ui-top-title:before {
+    content: " ";
+    border-left: 4px solid #f53d3d;
+    display: inline-block;
+    height: 16px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    margin-top: -13px;
+  }
+
+  .el-button--text {
+    color: #3d68e1;
+    text-decoration: underline;
+  }
+}
+
+#systemMonitor {
+  .el-tabs__header {
+    border: 0px solid #dcdfe6;
+    .el-tabs__item {
+      padding: 5px 50px;
+      height: 50px;
+      font-family: PingFangSC-Regular;
+      font-size: 14px;
+      color: #222222;
+      text-align: center;
+      border: 0px solid transparent;
+    }
+    .el-tabs__item:nth-child(2) {
+      padding-left: 50px;
+    }
+    .el-tabs__item:last-child {
+      padding-right: 50px;
+    }
+    .el-tabs__item.is-active {
+      color: #ff7733;
+      font-weight: bold;
+      // border-right-color: #fff;
+      // border-left-color: #fff;
+    }
+    .el-tabs__item:not(.is-disabled):hover {
+      color: #ff7733;
+    }
+  }
+  .el-tabs__active-bar {
+    background-color: #ff7733;
+  }
+  .el-tabs__content {
+    padding-left: 15px !important;
+  }
+}
+</style>
diff --git a/src/pages/systemMonitor/index/main.ts b/src/pages/systemMonitor/index/main.ts
new file mode 100644
index 0000000..b5ea667
--- /dev/null
+++ b/src/pages/systemMonitor/index/main.ts
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import App from './App.vue';
+
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import "@/assets/css/element-variables.scss";
+
+import moment from 'moment';
+
+Vue.use(ElementUI)
+Vue.prototype.$moment = moment;
+
+new Vue({
+  el: '#app',
+  render: h => h(App)
+})
\ No newline at end of file
diff --git a/src/pages/vindicate/index/App.vue b/src/pages/vindicate/index/App.vue
new file mode 100644
index 0000000..7f0e417
--- /dev/null
+++ b/src/pages/vindicate/index/App.vue
@@ -0,0 +1,617 @@
+<template>
+  <div class="s-system-manage">
+    <el-tabs
+      id="systemMaintenance"
+      v-model="activeName"
+      v-loading="loading"
+      :element-loading-text="loadingText"
+    >
+      <el-tab-pane label="璁惧缁存姢" name="device" v-if="isShow('vindicate:device')">
+        <div class="s-system-maintenance">
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">閲嶅惎</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-button type="primary" size="small" style="width:80px" @click="reboot">閲嶅惎</el-button>
+
+              <b class="card-text">閲嶅惎鑺傜偣</b>
+
+              <el-row style="margin-top:20px">
+                <el-col>
+                  <vue-cron :expression="rebootCron" @update="setRebootCron" />
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          <!--
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鎭㈠榛樿鍊�</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-row>
+                <el-col :span="1">
+                  <el-button type="primary" size="small">绠�鍗曟仮澶�</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">绠�鍗曟仮澶嶈澶囧弬鏁�</b>
+                </el-col>
+              </el-row>
+              <el-row style="margin-top:20px">
+                <el-col :span="1">
+                  <el-button type="primary" size="small">瀹屽叏鎭㈠</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">瀹屽叏鎭㈠璁惧鍙傛暟鍒板嚭鍘傝缃�</b>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鍙傛暟瀵煎叆瀵煎嚭</div>
+            </div>
+            <el-divider></el-divider>
+
+            <div class="box-card-content">
+              <el-row :gutter="4">
+                <el-col :span="1">
+                  <el-button type="info" size="small" style="width:80px">瀵煎叆</el-button>
+                </el-col>
+                <el-col :span="3" style="padding-left:30px">
+                  <el-input placeholder="涓婁紶鍙傛暟鏂囦欢" size="small" :readonly="true">
+                    <el-upload slot="suffix" action="https://jsonplaceholder.typicode.com/posts/">
+                      <el-button
+                        type="text"
+                        icon="el-icon-upload2"
+                        size="small"
+                        style="font-size:18px; color:#0088ff"
+                      ></el-button>
+                    </el-upload>
+                  </el-input>
+                </el-col>
+              </el-row>
+              <el-row style="margin-top:20px">
+                <el-col :span="1">
+                  <el-button type="primary" size="small">璁惧鍙傛暟</el-button>
+                </el-col>
+                <el-col :span="23">
+                  <b class="card-text">鍙傛暟瀵煎嚭</b>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+          -->
+          <div class="box-card">
+            <div class="ui-top-view">
+              <div class="ui-top-title">鍗囩骇</div>
+            </div>
+          </div>
+          <el-divider></el-divider>
+          <div class="box-card-content">
+            <el-row :gutter="4">
+              <el-col :span="12">
+                <file-uploader
+                  single
+                  uploadPlaceholder="涓婁紶鍗囩骇鏂囦欢"
+                  url="/data/api-v/sysset/patchUpdate"
+                  @complete="onFileUpload"
+                  @file-added="onFileAdded"
+                />
+              </el-col>
+              <el-col :span="2">
+                <el-button
+                  type="primary"
+                  size="small"
+                  style="width:80px"
+                  @click="upgrade"
+                  :disabled="!fileAdded"
+                  :loading="upgrading"
+                >鍗囩骇</el-button>
+              </el-col>
+              <el-col :span="16" class="upload-msg">
+                <span v-html="patchUpdateStatus"></span>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="鏁版嵁搴撶淮鎶�" name="dbvdc" v-if="isShow('vindicate:db')">
+        <div class="box">
+          <p class="title">
+            <label>鏁版嵁娓呯悊</label>
+          </p>
+          <div class="range">
+            <div class="left">
+              <p>閫夋嫨鏁版嵁鑼冨洿锛�</p>
+            </div>
+            <div class="middle">
+              <el-date-picker
+                v-model="dataRange"
+                type="daterange"
+                range-separator="鑷�"
+                start-placeholder="寮�濮嬫棩鏈�"
+                end-placeholder="缁撴潫鏃ユ湡"
+                style="height:38px"
+                :picker-options="pickerOptions"
+              ></el-date-picker>
+            </div>
+            <div class="right">
+              <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">鍒犻櫎鏁版嵁</el-button>
+            </div>
+          </div>
+          <div class="tip">
+            <i class="iconfont icontishi-zhuyi"></i>
+            <p class="zhuyi">璇锋敞鎰忥紝鎸変互涓婃棩鏈熻寖鍥村垹闄ょ殑鏁版嵁涓嶅彲鎭㈠锛岀珛鍗崇敓鏁堬紝璇疯皑鎱庢搷浣�</p>
+          </div>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade, deleteDate } from "@/api/system"
+import VueCron from "@/components/subComponents/VueCron"
+import FileUploader from "@/components/subComponents/FileUpload/index"
+
+export default {
+  components: {
+    VueCron,
+    FileUploader
+  },
+  data() {
+    return {
+      timer: null,
+      buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
+      rebootCron: "",
+      activeName: "device",
+      restartValue: "涓嶉噸鍚�",
+      restartTimeValue: new Date(2019, 9, 10, 18, 40),
+      loading: false,
+      loadingText: '',
+      probeSum: 0,
+      patchUpdateStatus: "",
+      dataRange: [
+        this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+        this.$moment().format("YYYY-MM-DD HH:mm:ss")
+      ],
+      fileUploadUrl: fileUpload,
+      patchFile: {},
+      pickerOptions: {
+        disabledDate(time) {
+          var day = new Date()
+          day.setTime(day.getTime() - 24 * 60 * 60 * 1000)
+          return time.getTime() > day;
+        },
+      },
+      upgrading: false,
+      fileAdded: false,
+    };
+  },
+  mounted() {
+    this.getRebootCron()
+    if (!this.isShow('vindicate:device')) {
+      this.activeName = "dbvdc"
+    }
+  },
+  computed: {
+    isAdmin() {
+      if (
+        sessionStorage.getItem('userInfo') &&
+        sessionStorage.getItem('userInfo') !== ''
+      ) {
+        let loginName = JSON.parse(sessionStorage.getItem('userInfo')).username
+        return (
+          loginName === 'superadmin' || loginName === 'basic'
+        )
+      }
+      return false;
+    }
+  },
+  methods: {
+    isShow(authority) {
+      if (this.isAdmin) {
+        return true
+      } else if (
+        this.buttonAuthority.indexOf(',' + authority + ',') > -1
+      ) {
+        return true
+      } else {
+        return false
+      }
+    },
+    format(array) {
+      return [
+        this.$moment(array[0]).format("YYYY-MM-DD"),
+        this.$moment(array[1]).format("YYYY-MM-DD")
+      ];
+    },
+    getRebootCron() {
+      getRebootTask().then(rsp => {
+        this.rebootCron = rsp.data
+      })
+    },
+    setRebootCron(value) {
+      this.rebootCron = value
+      setRebootTask({ task: value }).then(rsp => {
+        if (rsp && rsp.success) {
+          this.$notify({
+            type: "success",
+            message: "閰嶇疆鎴愬姛"
+          })
+        }
+      }).catch(err => {
+        this.$notify({
+          type: "error",
+          message: "閰嶇疆澶辫触"
+        })
+      })
+    },
+    reboot() {
+      this.$confirm('纭畾瑕侀噸鍚鑺傜偣鍚�?', {
+        center: true,
+        cancelButtonClass: 'comfirm-class-cancle',
+        confirmButtonClass: 'comfirm-class-sure'
+      }).then(() => {
+        this.loading = true;
+        this.loadingText = "鏅鸿兘璁$畻鑺傜偣姝e湪閲嶅惎锛岃鑰愬績绛夊緟..."
+        rebootServer().then(rsp => {
+          this.probeServer(this.reLogin)
+        }).catch(err => {
+          if (err.status == 400) {
+            this.loading = false;
+            this.$notify({
+              type: "error",
+              message: "閲嶅惎璁$畻鑺傜偣澶辫触"
+            })
+          } else {
+            this.probeServer(this.reLogin)
+          }
+        })
+      })
+    },
+    deleteData() {
+      var timeRange = this.format(this.dataRange);
+      var showStartTime = timeRange[0]
+      var showEndTime = timeRange[1]
+      console.log("鏃堕棿锛�", showStartTime, showEndTime)
+      this.$confirm("鎻愮ず锛�" + showStartTime + " 鑷� " + showEndTime + " 浜х敓鐨勫叏閮ㄦ暟鎹皢琚垹闄わ紝姝ゆ搷浣滅珛鍗崇敓鏁堬紝涓嶅彲鎭㈠锛屾槸鍚﹀垹闄わ紵", {
+        center: true,
+        cancelButtonClass: "comfirm-class-cancle",
+        confirmButtonClass: "comfirm-class-sure"
+      }).then(() => {
+        this.loading = true
+        this.loadingText = "姝e湪鍒犻櫎鏁版嵁锛岃绋嶅�欙紒"
+        var param = {
+          startTime: showStartTime,
+          endTime: showEndTime
+        }
+        deleteDate(param).then(resp => {
+          if (resp.success) {
+            this.$message({
+              type: "success",
+              message: "鍒犻櫎鏁版嵁鎴愬姛"
+            })
+            this.loading = false
+          }
+        }).catch(err => {
+          this.$message({
+            type: "error",
+            message: "鍒犻櫎鏁版嵁澶辫触锛�"
+          })
+          this.loading = false
+        })
+
+      }).catch(() => {
+        console.log("鍙栨秷浜嗭紒")
+      })
+    },
+    reLogin() {
+      this.$router.push("/")
+    },
+    probeServer(callback) {
+      this.probeSum++;
+      let _this = this
+      if (this.probeSum > 60) {
+        this.$confirm('杩炴帴鏈嶅姟鍣ㄥけ璐�, 璇峰埛鏂伴〉闈㈡垨鑱旂郴绠$悊鍛�', '澶辫触', {
+          type: 'error',
+          cancelButtonClass: 'comfirm-class-cancle',
+          confirmButtonClass: 'comfirm-class-sure'
+        }).then(() => {
+          // _this.$router.push("/")
+          callback()
+        })
+        return
+      }
+
+      this.timer = setTimeout(() => {
+        getDevInfo().then(() => {
+          // _this.$router.push("/")
+          callback()
+        }).catch(err => {
+          _this.probeServer(callback)
+        })
+      }, 10000)
+    },
+    onFileUpload(file) {
+      this.patchUpdateStatus = `<span style="color:green">涓婁紶鎴愬姛, 鐐瑰嚮鍗囩骇鎸夐挳寮�濮嬪崌绾�</span>`
+      this.patchFile = { ...file }
+      this.fileAdded = true
+    },
+    onFileAdded() {
+      this.patchUpdateStatus = ""
+    },
+    upgrade() {
+      this.upgrading = true
+      this.patchUpdateStatus = `<span style="color:red">姝e湪鍗囩骇...</span>`
+      doUpgrade(this.patchFile).then(rsp => {
+        this.upgrading = false
+
+        if (rsp && rsp.success) {
+          clearTimeout(this.timer)
+          this.doneUpgrade()
+        }
+      }).catch(err => {
+        if (err.code) {
+          this.upgrading = false
+          this.patchUpdateStatus = `<span style="color:red">${err.data}</span>`
+          clearTimeout(this.timer)
+        } else {
+          this.probeServer(this.doneUpgrade)
+        }
+      })
+    },
+    doneUpgrade() {
+      this.upgrading = false
+      this.patchUpdateStatus = `<span style="color:green">鍗囩骇鎴愬姛</span>`
+      let _this = this
+      this.$confirm('鍗囩骇鎴愬姛, 璇烽噸鏂扮櫥褰曠郴缁�', '鎴愬姛', {
+        type: 'success',
+        cancelButtonClass: 'comfirm-class-cancle',
+        confirmButtonClass: 'comfirm-class-sure'
+      }).then(() => {
+        _this.reLogin()
+      })
+    }
+  }
+};
+</script>
+<style lang="scss">
+.s-system-manage {
+  width: 100% !important;
+  min-width: 759px;
+  box-sizing: border-box;
+  padding: 10px;
+  // background-color: #e9ebf2;
+  background-color: #fff;
+  .s-system-manage-breadcrumb {
+    height: 5%;
+    box-sizing: border-box;
+    border: 1px solid #e4e7ed;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    border-radius: 5px;
+  }
+
+  .el-tabs--border-card {
+    border: 0px solid #dcdfe6;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+    .el-tabs__header {
+      border: 0px solid #dcdfe6;
+      .el-tabs__item {
+        padding: 5px 50px;
+        height: 50px;
+        font-family: PingFangSC-Regular;
+        font-size: 15px;
+        color: #222222;
+        text-align: center;
+        border: 0px solid transparent;
+      }
+      .el-tabs__item:nth-child(2) {
+        padding-left: 50px !important;
+      }
+      .el-tabs__item:last-child {
+        padding-right: 50px !important;
+      }
+      .el-tabs__item.is-active {
+        color: #3d68e1;
+        font-weight: bold;
+        // border-right-color: #fff;
+        // border-left-color: #fff;
+      }
+      .el-tabs__item:not(.is-disabled):hover {
+        color: #3d68e1;
+      }
+    }
+  }
+  .el-tabs__content {
+    height: calc(100% - 64px);
+    width: calc(100% - 20px);
+    box-sizing: border-box;
+    overflow-y: auto;
+    padding: 10px 40px !important;
+    .el-tab-pane {
+      width: 100%;
+      .s-title {
+        text-align: left;
+        padding: 15px 0px;
+        font-size: 16px;
+      }
+    }
+  }
+
+  .s-table {
+    border: 1px solid #e8e8e9;
+    margin-top: 40px;
+  }
+
+  .ui-top-title {
+    padding-bottom: 10px;
+    /* border-bottom: 1px solid #ebebeb; */
+    position: relative;
+    text-align: left;
+    padding-left: 15px;
+    font-size: 16px;
+    font-weight: bold;
+  }
+
+  .ui-top-title:before {
+    content: " ";
+    border-left: 4px solid #f53d3d;
+    display: inline-block;
+    height: 16px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    margin-top: -13px;
+  }
+
+  .el-button--text {
+    color: #3d68e1;
+    text-decoration: underline;
+  }
+}
+.s-system-maintenance {
+  width: 100%;
+  height: 100%;
+  .el-button--primary {
+    color: #ffffff;
+    background-color: #3d68e1;
+    border-color: #3d68e1;
+  }
+  .el-button--primary.is-disabled,
+  .el-button--primary.is-disabled:hover,
+  .el-button--primary.is-disabled:focus,
+  .el-button--primary.is-disabled:active {
+    color: #ffffff;
+    background-color: #9eb4f0;
+    border-color: #9eb4f0;
+  }
+  .box-card {
+    text-align: left;
+    height: auto;
+    margin: 10px 0px;
+    .box-card-content {
+      padding-bottom: 40px;
+      .card-text {
+        padding: 0 30px;
+        line-height: 32px;
+      }
+    }
+  }
+
+  .upload-icon {
+    font-size: 18px;
+    color: #0088ff;
+  }
+  .upload-msg {
+    padding-left: 10px;
+    text-align: left;
+    span {
+      line-height: 32px;
+      font-size: 13px;
+    }
+  }
+}
+.box {
+  width: 50%;
+  min-width: 700px;
+  height: 270px;
+  border: 1px solid #eee;
+  .title {
+    font-size: 20px;
+    font-weight: bold;
+    text-align: left;
+    padding: 20px;
+    border-bottom: 1px solid #eee;
+  }
+  .range {
+    width: 100%;
+    padding-top: 30px;
+    height: 38px;
+    .left {
+      width: 120px;
+      float: left;
+      text-align: right;
+      font-size: 14px;
+      p {
+        height: 38px;
+        line-height: 38px;
+        margin: 0;
+      }
+    }
+    .middle {
+      width: 50%;
+      min-width: 400px;
+      height: 38px;
+      float: left;
+    }
+    .right {
+      width: 20%;
+      height: 38px;
+      float: left;
+    }
+  }
+  .tip {
+    width: 100%;
+    padding: 30px 0px 0px 30px;
+    height: 34px;
+
+    .zhuyi {
+      font-size: 14px;
+      height: 34px;
+      line-height: 34px;
+      margin-left: 20px;
+      float: left;
+    }
+    i {
+      font-size: 32px;
+      color: #e99038;
+      float: left;
+    }
+  }
+}
+#systemMaintenance {
+  .el-tabs__header {
+    border: 0px solid #dcdfe6;
+    .el-tabs__item {
+      padding: 5px 50px;
+      height: 50px;
+      font-family: PingFangSC-Regular;
+      font-size: 14px;
+      color: #222222;
+      text-align: center;
+      border: 0px solid transparent;
+    }
+    .el-tabs__item:nth-child(2) {
+      padding-left: 50px;
+    }
+    .el-tabs__item:last-child {
+      padding-right: 50px;
+    }
+    .el-tabs__item.is-active {
+      color: #ff7733;
+      font-weight: bold;
+      // border-right-color: #fff;
+      // border-left-color: #fff;
+    }
+    .el-tabs__item:not(.is-disabled):hover {
+      color: #ff7733;
+    }
+  }
+  .el-tabs__active-bar {
+    background-color: #ff7733;
+  }
+  .el-tabs__content {
+    padding-left: 15px !important;
+  }
+}
+</style>
diff --git a/src/pages/vindicate/index/main.ts b/src/pages/vindicate/index/main.ts
new file mode 100644
index 0000000..b5ea667
--- /dev/null
+++ b/src/pages/vindicate/index/main.ts
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import App from './App.vue';
+
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import "@/assets/css/element-variables.scss";
+
+import moment from 'moment';
+
+Vue.use(ElementUI)
+Vue.prototype.$moment = moment;
+
+new Vue({
+  el: '#app',
+  render: h => h(App)
+})
\ No newline at end of file

--
Gitblit v1.8.0